// 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 <limits>
#include "base/logging.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 "ui/gl/gl_bindings.h"
#include "ui/gl/gl_implementation.h"

namespace gpu {
namespace gles2 {

BufferManager::BufferManager(
    MemoryTracker* memory_tracker,
    FeatureInfo* feature_info)
    : memory_tracker_(
          new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)),
      feature_info_(feature_info),
      allow_buffers_on_multiple_targets_(false),
      allow_fixed_attribs_(false),
      buffer_count_(0),
      have_context_(true),
      use_client_side_arrays_for_stream_buffers_(
          feature_info ? feature_info->workarounds(
              ).use_client_side_arrays_for_stream_buffers : 0) {
}

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

void BufferManager::Destroy(bool have_context) {
  have_context_ = have_context;
  buffers_.clear();
  DCHECK_EQ(0u, memory_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_tracker_->TrackMemFree(buffer->size());
  --buffer_count_;
}

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

Buffer::~Buffer() {
  if (manager_) {
    if (manager_->have_context_) {
      GLuint id = service_id();
      glDeleteBuffersARB(1, &id);
    }
    manager_->StopTracking(this);
    manager_ = NULL;
  }
}

void Buffer::SetInfo(
    GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data,
    bool is_client_side_array) {
  usage_ = usage;
  is_client_side_array_ = is_client_side_array;
  ClearCache();
  if (size != size_ || shadow != shadowed_) {
    shadowed_ = shadow;
    size_ = size;
    if (shadowed_) {
      shadow_.reset(new int8[size]);
    } else {
      shadow_.reset();
    }
  }
  if (shadowed_) {
    if (data) {
      memcpy(shadow_.get(), data, size);
    } else {
      memset(shadow_.get(), 0, size);
    }
  }
}

bool Buffer::CheckRange(
    GLintptr offset, GLsizeiptr size) const {
  int32 end = 0;
  return offset >= 0 && size >= 0 &&
         offset <= std::numeric_limits<int32>::max() &&
         size <= std::numeric_limits<int32>::max() &&
         SafeAddInt32(offset, size, &end) && end <= size_;
}

bool Buffer::SetRange(
    GLintptr offset, GLsizeiptr size, const GLvoid * data) {
  if (!CheckRange(offset, size)) {
    return false;
  }
  if (shadowed_) {
    memcpy(shadow_.get() + offset, data, size);
    ClearCache();
  }
  return true;
}

const void* Buffer::GetRange(
    GLintptr offset, GLsizeiptr size) const {
  if (!shadowed_) {
    return NULL;
  }
  if (!CheckRange(offset, size)) {
    return NULL;
  }
  return shadow_.get() + offset;
}

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

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

bool Buffer::GetMaxValueForRange(
    GLuint offset, GLsizei count, GLenum type, GLuint* max_value) {
  Range range(offset, count, type);
  RangeToMaxValueMap::iterator it = range_set_.find(range);
  if (it != range_set_.end()) {
    *max_value = it->second;
    return true;
  }

  uint32 size;
  if (!SafeMultiplyUint32(
      count, GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type), &size)) {
    return false;
  }

  if (!SafeAddUint32(offset, size, &size)) {
    return false;
  }

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

  if (!shadowed_) {
    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>(shadow_.get(), offset, count);
      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>(shadow_.get(), offset, count);
      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>(shadow_.get(), offset, count);
      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;
}

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

void BufferManager::SetInfo(
    Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data) {
  DCHECK(buffer);
  memory_tracker_->TrackMemFree(buffer->size());
  const bool is_client_side_array = IsUsageClientSideArray(usage);
  const bool support_fixed_attribs =
    gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
  const bool shadow = buffer->target() == GL_ELEMENT_ARRAY_BUFFER ||
                      allow_buffers_on_multiple_targets_ ||
                      (allow_fixed_attribs_ && !support_fixed_attribs) ||
                      is_client_side_array;
  buffer->SetInfo(size, usage, shadow, data, is_client_side_array);
  memory_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;
  }

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

  if (!memory_tracker_->EnsureGPUMemoryAvailable(size)) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_OUT_OF_MEMORY, "glBufferData", "out of memory");
    return;
  }

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


void BufferManager::DoBufferData(
    ErrorState* error_state,
    Buffer* buffer,
    GLsizeiptr size,
    GLenum usage,
    const GLvoid* data) {
  // Clear the buffer to 0 if no initial data was passed in.
  scoped_ptr<int8[]> zero;
  if (!data) {
    zero.reset(new int8[size]);
    memset(zero.get(), 0, size);
    data = zero.get();
  }

  ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData");
  if (IsUsageClientSideArray(usage)) {
    GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0;
    glBufferData(buffer->target(), empty_size, NULL, usage);
  } else {
    glBufferData(buffer->target(), size, data, usage);
  }
  GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData");
  if (error == GL_NO_ERROR) {
    SetInfo(buffer, size, usage, data);
  } else {
    SetInfo(buffer, 0, usage, NULL);
  }
}

void BufferManager::ValidateAndDoBufferSubData(
  ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size,
  const GLvoid * data) {
  ErrorState* error_state = context_state->GetErrorState();
  Buffer* buffer = GetBufferInfoForTarget(context_state, target);
  if (!buffer) {
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData",
                            "unknown buffer");
    return;
  }

  DoBufferSubData(error_state, buffer, offset, size, data);
}

void BufferManager::DoBufferSubData(
    ErrorState* error_state,
    Buffer* buffer,
    GLintptr offset,
    GLsizeiptr size,
    const GLvoid* data) {
  if (!buffer->SetRange(offset, size, data)) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_VALUE, "glBufferSubData", "out of range");
    return;
  }

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

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;
    default:
      NOTREACHED();
  }
}

bool BufferManager::SetTarget(Buffer* buffer, GLenum target) {
  // Check that we are not trying to bind it to a different target.
  if (buffer->target() != 0 && buffer->target() != target &&
      !allow_buffers_on_multiple_targets_) {
    return false;
  }
  if (buffer->target() == 0) {
    buffer->set_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) {
  DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
  if (target == GL_ARRAY_BUFFER) {
    return state->bound_array_buffer.get();
  } else {
    return state->vertex_attrib_manager->element_array_buffer();
  }
}

}  // namespace gles2
}  // namespace gpu


