// 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/safe_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/common/gles2_cmd_utils.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() : NULL;
}

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;
  }
}

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);
}

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;
  }
  base::CheckedNumeric<int32_t> max = offset;
  max += size;
  return max.IsValid() && max.ValueOrDefault(0) <= 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 NULL;
  }
  if (!CheckRange(offset, size)) {
    return NULL;
  }
  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);
    RangeToMaxValueMap::iterator 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 (!SafeMultiplyUint32(
      count, GLES2Util::GetGLTypeSizeForBuffers(type), &size)) {
    return false;
  }

  if (!SafeAddUint32(offset, size, &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);
}

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, GLenum target, GLsizeiptr size,
    const GLvoid* data, GLenum usage) {
  ErrorState* error_state = context_state->GetErrorState();
  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 (!memory_type_tracker_->EnsureGPUMemoryAvailable(size)) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_OUT_OF_MEMORY, "glBufferData", "out of memory");
    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(target, 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, GLenum target, GLintptr offset, GLsizeiptr size,
  const GLvoid * data) {
  Buffer* buffer = RequestBufferAccess(
      context_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, GLenum readtarget, GLenum writetarget,
    GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
  const char* func_name = "glCopyBufferSubData";
  Buffer* readbuffer = RequestBufferAccess(
      context_state, readtarget, readoffset, size, func_name);
  if (!readbuffer)
    return;
  Buffer* writebuffer = RequestBufferAccess(
      context_state, writetarget, writeoffset, size, func_name);
  if (!writebuffer)
    return;

  ErrorState* error_state = context_state->GetErrorState();
  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, GLenum target, GLenum pname, GLint64* params) {
  Buffer* buffer = GetBufferInfoForTarget(context_state, target);
  if (!buffer) {
    ERRORSTATE_SET_GL_ERROR(
        context_state->GetErrorState(), 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, GLenum target, GLenum pname, GLint* params) {
  Buffer* buffer = GetBufferInfoForTarget(context_state, target);
  if (!buffer) {
    ERRORSTATE_SET_GL_ERROR(
        context_state->GetErrorState(), 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.

    // Note that we don't force the WebGL 2 rule that a buffer bound to
    // TRANSFORM_FEEDBACK_BUFFER target should not be bound to any other
    // targets, because that is not a security threat, so we only enforce it
    // in the WebGL2RenderingContextBase.
    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/share_group_0x%" PRIX64 "",
                           memory_tracker_->ShareGroupTracingGUID());
    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;
  }

  const uint64_t share_group_tracing_guid =
      memory_tracker_->ShareGroupTracingGUID();
  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/share_group_0x%" PRIX64 "/buffer_0x%" PRIX32,
        share_group_tracing_guid, 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()->shared_memory_handle().GetGUID();
    if (!shared_memory_guid.is_empty()) {
      pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
                                           0 /* importance */);
    } else {
      auto guid = gl::GetGLBufferGUIDForTracing(share_group_tracing_guid,
                                                client_buffer_id);
      pmd->CreateSharedGlobalAllocatorDump(guid);
      pmd->AddOwnershipEdge(dump->guid(), guid);
    }
  }

  return true;
}

Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
                                           GLenum target,
                                           GLintptr offset,
                                           GLsizeiptr size,
                                           const char* func_name) {
  DCHECK(context_state);
  ErrorState* error_state = context_state->GetErrorState();

  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,
                                           GLenum target,
                                           const char* func_name) {
  DCHECK(context_state);
  ErrorState* error_state = context_state->GetErrorState();

  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;
    }
    GLsizeiptr size = bindings->GetEffectiveBufferSize(ii);
    base::CheckedNumeric<GLsizeiptr> required_size = variable_sizes[ii];
    required_size *= count;
    if (size < required_size.ValueOrDefault(
            std::numeric_limits<GLsizeiptr>::max())) {
      std::string msg = base::StringPrintf(
          "%s : buffer or buffer range not large enough at index %zu",
          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;
  }
  return true;
}

}  // namespace gles2
}  // namespace gpu
