// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/service/buffer_manager.h"

#include <stdint.h>

#include <limits>

#include "base/format_macros.h"
#include "base/logging.h"
#include "base/numerics/checked_math.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "gpu/command_buffer/service/context_state.h"
#include "gpu/command_buffer/service/error_state.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/transform_feedback_manager.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/trace_util.h"

namespace gpu {
namespace gles2 {
namespace {
static const GLsizeiptr kDefaultMaxBufferSize = 1u << 30;  // 1GB
}

BufferManager::BufferManager(MemoryTracker* memory_tracker,
                             FeatureInfo* feature_info)
    : memory_type_tracker_(
          new MemoryTypeTracker(memory_tracker)),
      memory_tracker_(memory_tracker),
      feature_info_(feature_info),
      max_buffer_size_(kDefaultMaxBufferSize),
      allow_buffers_on_multiple_targets_(false),
      allow_fixed_attribs_(false),
      buffer_count_(0),
      primitive_restart_fixed_index_(0),
      lost_context_(false),
      use_client_side_arrays_for_stream_buffers_(
          feature_info
              ? feature_info->workarounds()
                    .use_client_side_arrays_for_stream_buffers
              : 0) {
  // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
  // so don't register a dump provider.
  if (memory_tracker_) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "gpu::BufferManager", base::ThreadTaskRunnerHandle::Get());
  }
}

BufferManager::~BufferManager() {
  DCHECK(buffers_.empty());
  CHECK_EQ(buffer_count_, 0u);

  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);
}

void BufferManager::MarkContextLost() {
  lost_context_ = true;
}

void BufferManager::Destroy() {
  buffers_.clear();
  DCHECK_EQ(0u, memory_type_tracker_->GetMemRepresented());
}

void BufferManager::CreateBuffer(GLuint client_id, GLuint service_id) {
  scoped_refptr<Buffer> buffer(new Buffer(this, service_id));
  std::pair<BufferMap::iterator, bool> result =
      buffers_.insert(std::make_pair(client_id, buffer));
  DCHECK(result.second);
}

Buffer* BufferManager::GetBuffer(
    GLuint client_id) {
  BufferMap::iterator it = buffers_.find(client_id);
  return it != buffers_.end() ? it->second.get() : nullptr;
}

void BufferManager::RemoveBuffer(GLuint client_id) {
  BufferMap::iterator it = buffers_.find(client_id);
  if (it != buffers_.end()) {
    Buffer* buffer = it->second.get();
    buffer->MarkAsDeleted();
    buffers_.erase(it);
  }
}

void BufferManager::StartTracking(Buffer* /* buffer */) {
  ++buffer_count_;
}

void BufferManager::StopTracking(Buffer* buffer) {
  memory_type_tracker_->TrackMemFree(buffer->size());
  --buffer_count_;
}

Buffer::MappedRange::MappedRange(
    GLintptr offset, GLsizeiptr size, GLenum access, void* pointer,
    scoped_refptr<gpu::Buffer> shm, unsigned int shm_offset)
    : offset(offset),
      size(size),
      access(access),
      pointer(pointer),
      shm(shm),
      shm_offset(shm_offset) {
  DCHECK(pointer);
  DCHECK(shm.get() && GetShmPointer());
}

Buffer::MappedRange::~MappedRange() = default;

void* Buffer::MappedRange::GetShmPointer() const {
  DCHECK(shm.get());
  return shm->GetDataAddress(shm_offset, static_cast<unsigned int>(size));
}

Buffer::Buffer(BufferManager* manager, GLuint service_id)
    : manager_(manager),
      size_(0),
      deleted_(false),
      is_client_side_array_(false),
      service_id_(service_id),
      initial_target_(0),
      usage_(GL_STATIC_DRAW) {
  manager_->StartTracking(this);
}

Buffer::~Buffer() {
  if (manager_) {
    if (!manager_->lost_context_) {
      GLuint id = service_id();
      glDeleteBuffersARB(1, &id);
    }
    RemoveMappedRange();
    manager_->StopTracking(this);
    manager_ = nullptr;
  }
}

void Buffer::OnBind(GLenum target, bool indexed) {
  if (target == GL_TRANSFORM_FEEDBACK_BUFFER && indexed) {
    ++transform_feedback_indexed_binding_count_;
  } else if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
    ++non_transform_feedback_binding_count_;
  }
  // Note that the transform feedback generic (non-indexed) binding point does
  // not count as a transform feedback indexed binding point *or* a non-
  // transform- feedback binding point, so no reference counts need to change in
  // that case. See https://crbug.com/853978
}

void Buffer::OnUnbind(GLenum target, bool indexed) {
  if (target == GL_TRANSFORM_FEEDBACK_BUFFER && indexed) {
    --transform_feedback_indexed_binding_count_;
  } else if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
    --non_transform_feedback_binding_count_;
  }
  DCHECK(transform_feedback_indexed_binding_count_ >= 0);
  DCHECK(non_transform_feedback_binding_count_ >= 0);
}

const GLvoid* Buffer::StageShadow(bool use_shadow,
                                  GLsizeiptr size,
                                  const GLvoid* data) {
  shadow_.clear();
  if (use_shadow) {
    if (data) {
      shadow_.insert(shadow_.begin(),
                     static_cast<const uint8_t*>(data),
                     static_cast<const uint8_t*>(data) + size);
    } else {
      shadow_.resize(size);
      memset(shadow_.data(), 0, static_cast<size_t>(size));
    }
    return shadow_.data();
  } else {
    return data;
  }
}

void Buffer::SetInfo(GLsizeiptr size,
                     GLenum usage,
                     bool use_shadow,
                     bool is_client_side_array) {
  usage_ = usage;
  is_client_side_array_ = is_client_side_array;
  ClearCache();

  // Shadow must have been setup already.
  DCHECK_EQ(shadow_.size(), static_cast<size_t>(use_shadow ? size : 0u));
  size_ = size;

  mapped_range_.reset(nullptr);
  readback_shm_ = nullptr;
  readback_shm_offset_ = 0;
}

bool Buffer::CheckRange(GLintptr offset, GLsizeiptr size) const {
  if (offset < 0 || offset > std::numeric_limits<int32_t>::max() ||
      size < 0 || size > std::numeric_limits<int32_t>::max()) {
    return false;
  }
  int32_t max;
  return base::CheckAdd(offset, size).AssignIfValid(&max) && max <= size_;
}

void Buffer::SetRange(GLintptr offset, GLsizeiptr size, const GLvoid * data) {
  DCHECK(CheckRange(offset, size));
  if (!shadow_.empty()) {
    DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
    memcpy(shadow_.data() + offset, data, size);
    ClearCache();
  }
}

const void* Buffer::GetRange(GLintptr offset, GLsizeiptr size) const {
  if (shadow_.empty()) {
    return nullptr;
  }
  if (!CheckRange(offset, size)) {
    return nullptr;
  }
  DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
  return shadow_.data() + offset;
}

void Buffer::ClearCache() {
  range_set_.clear();
}

template <typename T>
GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count,
    GLuint primitive_restart_index) {
  GLuint max_value = 0;
  const T* element =
      reinterpret_cast<const T*>(static_cast<const int8_t*>(data) + offset);
  const T* end = element + count;
  for (; element < end; ++element) {
    if (*element > max_value) {
      if (*element == primitive_restart_index) {
        continue;
      }
      max_value = *element;
    }
  }
  return max_value;
}

bool Buffer::GetMaxValueForRange(
    GLuint offset, GLsizei count, GLenum type, bool primitive_restart_enabled,
    GLuint* max_value) {
  GLuint primitive_restart_index = 0;
  if (primitive_restart_enabled) {
    switch (type) {
      case GL_UNSIGNED_BYTE:
        primitive_restart_index = 0xFF;
        break;
      case GL_UNSIGNED_SHORT:
        primitive_restart_index = 0xFFFF;
        break;
      case GL_UNSIGNED_INT:
        primitive_restart_index = 0xFFFFFFFF;
        break;
      default:
        NOTREACHED();  // should never get here by validation.
        break;
    }
  }

  Range range(offset, count, type, primitive_restart_enabled);
  RangeToMaxValueMap::iterator it = range_set_.find(range);
  if (it != range_set_.end()) {
    *max_value = it->second;
    return true;
  }
  // Optimization. If:
  //  - primitive restart is enabled
  //  - we don't have an entry in the range set for these parameters
  //    for the situation when primitive restart is enabled
  //  - we do have an entry in the range set for these parameters for
  //    the situation when primitive restart is disabled
  //  - this entry is less than the primitive restart index
  // Then we can repurpose this entry for the situation when primitive
  // restart is enabled. Otherwise, we need to compute the max index
  // from scratch.
  if (primitive_restart_enabled) {
    Range disabled_range(offset, count, type, false);
    it = range_set_.find(disabled_range);
    if (it != range_set_.end() && it->second < primitive_restart_index) {
      // This reuses the max value for the case where primitive
      // restart is enabled.
      range_set_.insert(std::make_pair(range, it->second));
      *max_value = it->second;
      return true;
    }
  }

  uint32_t size;
  if (!base::CheckAdd(
           offset,
           base::CheckMul(count, GLES2Util::GetGLTypeSizeForBuffers(type)))
           .AssignIfValid(&size)) {
    return false;
  }

  if (size > static_cast<uint32_t>(size_)) {
    return false;
  }

  if (shadow_.empty()) {
    return false;
  }

  // Scan the range for the max value and store
  GLuint max_v = 0;
  switch (type) {
    case GL_UNSIGNED_BYTE:
      max_v = GetMaxValue<uint8_t>(shadow_.data(), offset, count,
                                   primitive_restart_index);
      break;
    case GL_UNSIGNED_SHORT:
      // Check we are not accessing an odd byte for a 2 byte value.
      if ((offset & 1) != 0) {
        return false;
      }
      max_v = GetMaxValue<uint16_t>(shadow_.data(), offset, count,
                                    primitive_restart_index);
      break;
    case GL_UNSIGNED_INT:
      // Check we are not accessing a non aligned address for a 4 byte value.
      if ((offset & 3) != 0) {
        return false;
      }
      max_v = GetMaxValue<uint32_t>(shadow_.data(), offset, count,
                                    primitive_restart_index);
      break;
    default:
      NOTREACHED();  // should never get here by validation.
      break;
  }
  range_set_.insert(std::make_pair(range, max_v));
  *max_value = max_v;
  return true;
}

void Buffer::SetMappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
                            void* pointer, scoped_refptr<gpu::Buffer> shm,
                            unsigned int shm_offset) {
  mapped_range_.reset(
      new MappedRange(offset, size, access, pointer, shm, shm_offset));
}

void Buffer::RemoveMappedRange() {
  mapped_range_.reset(nullptr);
}

void Buffer::SetReadbackShadowAllocation(scoped_refptr<gpu::Buffer> shm,
                                         uint32_t shm_offset) {
  DCHECK(shm);
  readback_shm_ = std::move(shm);
  readback_shm_offset_ = shm_offset;
}

scoped_refptr<gpu::Buffer> Buffer::TakeReadbackShadowAllocation(void** data) {
  DCHECK(readback_shm_);
  *data = readback_shm_->GetDataAddress(readback_shm_offset_, size_);
  readback_shm_offset_ = 0;
  return std::move(readback_shm_);
}

bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const {
  // This doesn't need to be fast. It's only used during slow queries.
  for (BufferMap::const_iterator it = buffers_.begin();
       it != buffers_.end(); ++it) {
    if (it->second->service_id() == service_id) {
      *client_id = it->first;
      return true;
    }
  }
  return false;
}

bool BufferManager::IsUsageClientSideArray(GLenum usage) {
  return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_;
}

bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() {
  return feature_info_.get() &&
         feature_info_->workarounds()
             .use_non_zero_size_for_client_side_stream_buffers;
}

bool BufferManager::UseShadowBuffer(GLenum target, GLenum usage) {
  const bool is_client_side_array = IsUsageClientSideArray(usage);
  // feature_info_ can be null in some unit tests.
  const bool support_fixed_attribs =
      !feature_info_ || feature_info_->gl_version_info().SupportsFixedType();

  // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002.
  return (
      target == GL_ELEMENT_ARRAY_BUFFER || allow_buffers_on_multiple_targets_ ||
      (allow_fixed_attribs_ && !support_fixed_attribs) || is_client_side_array);
}

void BufferManager::SetInfo(Buffer* buffer,
                            GLenum target,
                            GLsizeiptr size,
                            GLenum usage,
                            bool use_shadow) {
  DCHECK(buffer);
  memory_type_tracker_->TrackMemFree(buffer->size());
  buffer->SetInfo(size, usage, use_shadow, IsUsageClientSideArray(usage));
  memory_type_tracker_->TrackMemAlloc(buffer->size());
}

void BufferManager::ValidateAndDoBufferData(ContextState* context_state,
                                            ErrorState* error_state,
                                            GLenum target,
                                            GLsizeiptr size,
                                            const GLvoid* data,
                                            GLenum usage) {
  if (!feature_info_->validators()->buffer_target.IsValid(target)) {
    ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
        error_state, "glBufferData", target, "target");
    return;
  }
  if (!feature_info_->validators()->buffer_usage.IsValid(usage)) {
    ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
        error_state, "glBufferData", usage, "usage");
    return;
  }
  if (size < 0) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_VALUE, "glBufferData", "size < 0");
    return;
  }

  if (size > max_buffer_size_) {
    ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, "glBufferData",
                            "cannot allocate more than 1GB.");
    return;
  }

  Buffer* buffer = GetBufferInfoForTarget(context_state, target);
  if (!buffer) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_VALUE, "glBufferData", "unknown buffer");
    return;
  }

  if (buffer->IsBoundForTransformFeedbackAndOther()) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_OPERATION, "glBufferData",
        "buffer is bound for transform feedback and other use simultaneously");
    return;
  }

  DoBufferData(error_state, buffer, target, size, usage, data);

  if (context_state->bound_transform_feedback.get()) {
    // buffer size might have changed, and on Desktop GL lower than 4.2,
    // we might need to reset transform feedback buffer range.
    context_state->bound_transform_feedback->OnBufferData(buffer);
  }
}

void BufferManager::DoBufferData(
    ErrorState* error_state,
    Buffer* buffer,
    GLenum target,
    GLsizeiptr size,
    GLenum usage,
    const GLvoid* data) {
  // Stage the shadow buffer first if we are using a shadow buffer so that we
  // validate what we store internally.
  const bool use_shadow = UseShadowBuffer(buffer->initial_target(), usage);
  data = buffer->StageShadow(use_shadow, size, data);

  ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData");
  if (IsUsageClientSideArray(usage)) {
    GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0;
    glBufferData(target, empty_size, nullptr, usage);
  } else {
    if (data || !size) {
      glBufferData(target, size, data, usage);
    } else {
      std::unique_ptr<char[]> zero(new char[size]);
      memset(zero.get(), 0, size);
      glBufferData(target, size, zero.get(), usage);
    }
  }
  GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData");
  if (error != GL_NO_ERROR) {
    DCHECK_EQ(static_cast<GLenum>(GL_OUT_OF_MEMORY), error);
    size = 0;
    // TODO(zmo): This doesn't seem correct. There might be shadow data from
    // a previous successful BufferData() call.
    buffer->StageShadow(false, 0, nullptr);  // Also clear the shadow.
    return;
  }

  SetInfo(buffer, target, size, usage, use_shadow);
}

void BufferManager::ValidateAndDoBufferSubData(ContextState* context_state,
                                               ErrorState* error_state,
                                               GLenum target,
                                               GLintptr offset,
                                               GLsizeiptr size,
                                               const GLvoid* data) {
  Buffer* buffer = RequestBufferAccess(context_state, error_state, target,
                                       offset, size, "glBufferSubData");
  if (!buffer) {
    return;
  }
  DoBufferSubData(buffer, target, offset, size, data);
}

void BufferManager::DoBufferSubData(
    Buffer* buffer, GLenum target, GLintptr offset, GLsizeiptr size,
    const GLvoid* data) {
  buffer->SetRange(offset, size, data);

  if (!buffer->IsClientSideArray()) {
    glBufferSubData(target, offset, size, data);
  }
}

void BufferManager::ValidateAndDoCopyBufferSubData(ContextState* context_state,
                                                   ErrorState* error_state,
                                                   GLenum readtarget,
                                                   GLenum writetarget,
                                                   GLintptr readoffset,
                                                   GLintptr writeoffset,
                                                   GLsizeiptr size) {
  const char* func_name = "glCopyBufferSubData";
  Buffer* readbuffer = RequestBufferAccess(
      context_state, error_state, readtarget, readoffset, size, func_name);
  if (!readbuffer)
    return;
  Buffer* writebuffer = RequestBufferAccess(
      context_state, error_state, writetarget, writeoffset, size, func_name);
  if (!writebuffer)
    return;

  if (readbuffer == writebuffer &&
      ((writeoffset >= readoffset && writeoffset < readoffset + size) ||
       (readoffset >= writeoffset && readoffset < writeoffset + size))) {
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
        "read/write ranges overlap");
    return;
  }

  if (!allow_buffers_on_multiple_targets_) {
    if ((readbuffer->initial_target() == GL_ELEMENT_ARRAY_BUFFER &&
         writebuffer->initial_target() != GL_ELEMENT_ARRAY_BUFFER) ||
        (writebuffer->initial_target() == GL_ELEMENT_ARRAY_BUFFER &&
         readbuffer->initial_target() != GL_ELEMENT_ARRAY_BUFFER)) {
      ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
          "copying between ELEMENT_ARRAY_BUFFER and another buffer type");
      return;
    }
  }

  DoCopyBufferSubData(readbuffer, readtarget, readoffset,
                      writebuffer, writetarget, writeoffset, size);
}

void BufferManager::DoCopyBufferSubData(
    Buffer* readbuffer,
    GLenum readtarget,
    GLintptr readoffset,
    Buffer* writebuffer,
    GLenum writetarget,
    GLintptr writeoffset,
    GLsizeiptr size) {
  DCHECK(readbuffer);
  DCHECK(writebuffer);
  if (writebuffer->shadowed()) {
    const void* data = readbuffer->GetRange(readoffset, size);
    DCHECK(data);
    writebuffer->SetRange(writeoffset, size, data);
  }

  glCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size);
}

void BufferManager::ValidateAndDoGetBufferParameteri64v(
    ContextState* context_state,
    ErrorState* error_state,
    GLenum target,
    GLenum pname,
    GLint64* params) {
  Buffer* buffer = GetBufferInfoForTarget(context_state, target);
  if (!buffer) {
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION,
                            "glGetBufferParameteri64v",
                            "no buffer bound for target");
    return;
  }
  switch (pname) {
    case GL_BUFFER_SIZE:
      *params = buffer->size();
      break;
    case GL_BUFFER_MAP_LENGTH:
      {
        const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
        *params = mapped_range ? mapped_range->size : 0;
        break;
      }
    case GL_BUFFER_MAP_OFFSET:
      {
        const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
        *params = mapped_range ? mapped_range->offset : 0;
        break;
      }
    default:
      NOTREACHED();
  }
}

void BufferManager::ValidateAndDoGetBufferParameteriv(
    ContextState* context_state,
    ErrorState* error_state,
    GLenum target,
    GLenum pname,
    GLint* params) {
  Buffer* buffer = GetBufferInfoForTarget(context_state, target);
  if (!buffer) {
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION,
                            "glGetBufferParameteriv",
                            "no buffer bound for target");
    return;
  }
  switch (pname) {
    case GL_BUFFER_SIZE:
      *params = buffer->size();
      break;
    case GL_BUFFER_USAGE:
      *params = buffer->usage();
      break;
    case GL_BUFFER_ACCESS_FLAGS:
      {
        const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
        *params = mapped_range ? mapped_range->access : 0;
        break;
      }
    case GL_BUFFER_MAPPED:
      *params = buffer->GetMappedRange() == nullptr ? false : true;
      break;
    default:
      NOTREACHED();
  }
}

bool BufferManager::SetTarget(Buffer* buffer, GLenum target) {
  if (!allow_buffers_on_multiple_targets_) {
    // After being bound to ELEMENT_ARRAY_BUFFER target, a buffer cannot be
    // bound to any other targets except for COPY_READ/WRITE_BUFFER target;
    // After being bound to non ELEMENT_ARRAY_BUFFER target, a buffer cannot
    // be bound to ELEMENT_ARRAY_BUFFER target.

    switch (buffer->initial_target()) {
      case GL_ELEMENT_ARRAY_BUFFER:
        switch (target) {
          case GL_ARRAY_BUFFER:
          case GL_PIXEL_PACK_BUFFER:
          case GL_PIXEL_UNPACK_BUFFER:
          case GL_TRANSFORM_FEEDBACK_BUFFER:
          case GL_UNIFORM_BUFFER:
            return false;
          default:
            break;
        }
        break;
      case GL_ARRAY_BUFFER:
      case GL_COPY_READ_BUFFER:
      case GL_COPY_WRITE_BUFFER:
      case GL_PIXEL_PACK_BUFFER:
      case GL_PIXEL_UNPACK_BUFFER:
      case GL_TRANSFORM_FEEDBACK_BUFFER:
      case GL_UNIFORM_BUFFER:
        if (target == GL_ELEMENT_ARRAY_BUFFER) {
          return false;
        }
        break;
      default:
        break;
    }
  }
  if (buffer->initial_target() == 0)
    buffer->set_initial_target(target);
  return true;
}

// Since one BufferManager can be shared by multiple decoders, ContextState is
// passed in each time and not just passed in during initialization.
Buffer* BufferManager::GetBufferInfoForTarget(
    ContextState* state, GLenum target) const {
  switch (target) {
    case GL_ARRAY_BUFFER:
      return state->bound_array_buffer.get();
    case GL_ELEMENT_ARRAY_BUFFER:
      return state->vertex_attrib_manager->element_array_buffer();
    case GL_COPY_READ_BUFFER:
      return state->bound_copy_read_buffer.get();
    case GL_COPY_WRITE_BUFFER:
      return state->bound_copy_write_buffer.get();
    case GL_PIXEL_PACK_BUFFER:
      return state->bound_pixel_pack_buffer.get();
    case GL_PIXEL_UNPACK_BUFFER:
      return state->bound_pixel_unpack_buffer.get();
    case GL_TRANSFORM_FEEDBACK_BUFFER:
      return state->bound_transform_feedback_buffer.get();
    case GL_UNIFORM_BUFFER:
      return state->bound_uniform_buffer.get();
    default:
      NOTREACHED();
      return nullptr;
  }
}

void BufferManager::SetPrimitiveRestartFixedIndexIfNecessary(GLenum type) {
  GLuint index = 0;
  switch (type) {
    case GL_UNSIGNED_BYTE:
      index = 0xFF;
      break;
    case GL_UNSIGNED_SHORT:
      index = 0xFFFF;
      break;
    case GL_UNSIGNED_INT:
      index = 0xFFFFFFFF;
      break;
    default:
      NOTREACHED();  // should never get here by validation.
      break;
  }
  if (primitive_restart_fixed_index_ != index) {
    glPrimitiveRestartIndex(index);
    primitive_restart_fixed_index_ = index;
  }
}

bool BufferManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                                 base::trace_event::ProcessMemoryDump* pmd) {
  using base::trace_event::MemoryAllocatorDump;
  using base::trace_event::MemoryDumpLevelOfDetail;

  if (args.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND) {
    std::string dump_name =
        base::StringPrintf("gpu/gl/buffers/context_group_0x%" PRIX64 "",
                           memory_tracker_->ContextGroupTracingId());
    MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
    dump->AddScalar(MemoryAllocatorDump::kNameSize,
                    MemoryAllocatorDump::kUnitsBytes, mem_represented());

    // Early out, no need for more detail in a BACKGROUND dump.
    return true;
  }

  for (const auto& buffer_entry : buffers_) {
    const auto& client_buffer_id = buffer_entry.first;
    const auto& buffer = buffer_entry.second;

    std::string dump_name = base::StringPrintf(
        "gpu/gl/buffers/context_group_0x%" PRIX64 "/buffer_0x%" PRIX32,
        memory_tracker_->ContextGroupTracingId(), client_buffer_id);
    MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
    dump->AddScalar(MemoryAllocatorDump::kNameSize,
                    MemoryAllocatorDump::kUnitsBytes,
                    static_cast<uint64_t>(buffer->size()));

    auto* mapped_range = buffer->GetMappedRange();
    if (!mapped_range)
      continue;
    auto shared_memory_guid = mapped_range->shm->backing()->GetGUID();
    if (!shared_memory_guid.is_empty()) {
      pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
                                           0 /* importance */);
    } else {
      auto guid = gl::GetGLBufferGUIDForTracing(
          memory_tracker_->ContextGroupTracingId(), client_buffer_id);
      pmd->CreateSharedGlobalAllocatorDump(guid);
      pmd->AddOwnershipEdge(dump->guid(), guid);
    }
  }

  return true;
}

Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
                                           ErrorState* error_state,
                                           GLenum target,
                                           GLintptr offset,
                                           GLsizeiptr size,
                                           const char* func_name) {
  DCHECK(context_state);
  Buffer* buffer = GetBufferInfoForTarget(context_state, target);
  if (!RequestBufferAccess(error_state, buffer, func_name,
                           "bound to target 0x%04x", target)) {
    return nullptr;
  }
  if (!buffer->CheckRange(offset, size)) {
    std::string msg = base::StringPrintf(
        "bound to target 0x%04x : offset/size out of range", target);
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
                            msg.c_str());
    return nullptr;
  }
  return buffer;
}

Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
                                           ErrorState* error_state,
                                           GLenum target,
                                           const char* func_name) {
  DCHECK(context_state);
  Buffer* buffer = GetBufferInfoForTarget(context_state, target);
  return RequestBufferAccess(error_state, buffer, func_name,
                             "bound to target 0x%04x", target)
             ? buffer
             : nullptr;
}

bool BufferManager::RequestBufferAccess(ErrorState* error_state,
                                        Buffer* buffer,
                                        const char* func_name,
                                        const char* error_message_format,
                                        ...) {
  DCHECK(error_state);

  va_list varargs;
  va_start(varargs, error_message_format);
  bool result = RequestBufferAccessV(error_state, buffer, func_name,
                                     error_message_format, varargs);
  va_end(varargs);
  return result;
}

bool BufferManager::RequestBufferAccess(ErrorState* error_state,
                                        Buffer* buffer,
                                        GLintptr offset,
                                        GLsizeiptr size,
                                        const char* func_name,
                                        const char* error_message) {
  if (!RequestBufferAccess(error_state, buffer, func_name, error_message)) {
    return false;
  }
  if (!buffer->CheckRange(offset, size)) {
    std::string msg = base::StringPrintf(
        "%s : offset/size out of range", error_message);
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_OPERATION, func_name, msg.c_str());
    return false;
  }
  return true;
}

bool BufferManager::RequestBuffersAccess(
    ErrorState* error_state,
    const IndexedBufferBindingHost* bindings,
    const std::vector<GLsizeiptr>& variable_sizes,
    GLsizei count,
    const char* func_name,
    const char* message_tag) {
  DCHECK(error_state);
  DCHECK(bindings);

  for (size_t ii = 0; ii < variable_sizes.size(); ++ii) {
    if (variable_sizes[ii] == 0)
      continue;
    Buffer* buffer = bindings->GetBufferBinding(ii);
    if (!buffer) {
      std::string msg = base::StringPrintf(
          "%s : no buffer bound at index %zu", message_tag, ii);
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, func_name, msg.c_str());
      return false;
    }
    if (buffer->GetMappedRange()) {
      std::string msg = base::StringPrintf(
          "%s : buffer is mapped at index %zu", message_tag, ii);
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, func_name, msg.c_str());
      return false;
    }
    if (buffer->IsBoundForTransformFeedbackAndOther()) {
      std::string msg = base::StringPrintf(
          "%s : buffer at index %zu is bound for transform feedback and other "
          "use simultaneously",
          message_tag, ii);
      ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
                              msg.c_str());
      return false;
    }
    GLsizeiptr size = bindings->GetEffectiveBufferSize(ii);
    GLsizeiptr required_size;
    if (!base::CheckMul(variable_sizes[ii], count)
             .AssignIfValid(&required_size) ||
        size < required_size) {
      std::string msg = base::StringPrintf(
          "%s : buffer or buffer range at index %zu not large enough",
          message_tag, ii);
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, func_name, msg.c_str());
      return false;
    }
  }
  return true;
}

bool BufferManager::RequestBufferAccessV(ErrorState* error_state,
                                         Buffer* buffer,
                                         const char* func_name,
                                         const char* error_message_format,
                                         va_list varargs) {
  DCHECK(error_state);

  if (!buffer || buffer->IsDeleted()) {
    std::string message_tag = base::StringPrintV(error_message_format, varargs);
    std::string msg = base::StringPrintf("%s : no buffer", message_tag.c_str());
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
                            msg.c_str());
    return false;
  }
  if (buffer->GetMappedRange()) {
    std::string message_tag = base::StringPrintV(error_message_format, varargs);
    std::string msg = base::StringPrintf("%s : buffer is mapped",
                                         message_tag.c_str());
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
                            msg.c_str());
    return false;
  }
  if (buffer->IsBoundForTransformFeedbackAndOther()) {
    std::string message_tag = base::StringPrintV(error_message_format, varargs);
    std::string msg = base::StringPrintf(
        "%s : buffer is bound for transform feedback and other use "
        "simultaneously",
        message_tag.c_str());
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
                            msg.c_str());
    return false;
  }
  return true;
}

}  // namespace gles2
}  // namespace gpu
