// 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/common_decoder.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>

#include "base/numerics/safe_math.h"
#include "gpu/command_buffer/service/command_buffer_service.h"

namespace gpu {
namespace {
static const size_t kDefaultMaxBucketSize = 1u << 30;  // 1 GB
}

const CommonDecoder::CommandInfo CommonDecoder::command_info[] = {
#define COMMON_COMMAND_BUFFER_CMD_OP(name)                       \
  {                                                              \
    &CommonDecoder::Handle##name, cmd::name::kArgFlags,          \
        cmd::name::cmd_flags,                                    \
        sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1,      \
  }                                                              \
  ,  /* NOLINT */
  COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
  #undef COMMON_COMMAND_BUFFER_CMD_OP
};


CommonDecoder::Bucket::Bucket() : size_(0) {}

CommonDecoder::Bucket::~Bucket() = default;

void* CommonDecoder::Bucket::GetData(size_t offset, size_t size) const {
  if (OffsetSizeValid(offset, size)) {
    return data_.get() + offset;
  }
  return NULL;
}

void CommonDecoder::Bucket::SetSize(size_t size) {
  if (size != size_) {
    data_.reset(size ? new int8_t[size] : NULL);
    size_ = size;
    memset(data_.get(), 0, size);
  }
}

bool CommonDecoder::Bucket::SetData(
    const volatile void* src, size_t offset, size_t size) {
  if (OffsetSizeValid(offset, size)) {
    memcpy(data_.get() + offset, const_cast<const void*>(src), size);
    return true;
  }
  return false;
}

void CommonDecoder::Bucket::SetFromString(const char* str) {
  // Strings are passed NULL terminated to distinguish between empty string
  // and no string.
  if (!str) {
    SetSize(0);
  } else {
    size_t size = strlen(str) + 1;
    SetSize(size);
    SetData(str, 0, size);
  }
}

bool CommonDecoder::Bucket::GetAsString(std::string* str) {
  DCHECK(str);
  if (size_ == 0) {
    return false;
  }
  str->assign(GetDataAs<const char*>(0, size_ - 1), size_ - 1);
  return true;
}

bool CommonDecoder::Bucket::GetAsStrings(
    GLsizei* _count, std::vector<char*>* _string, std::vector<GLint>* _length) {
  const size_t kMinBucketSize = sizeof(GLint);
  // Each string has at least |length| in the header and a NUL character.
  const size_t kMinStringSize = sizeof(GLint) + 1;
  const size_t bucket_size = this->size();
  if (bucket_size < kMinBucketSize) {
    return false;
  }
  char* bucket_data = this->GetDataAs<char*>(0, bucket_size);
  GLint* header = reinterpret_cast<GLint*>(bucket_data);
  GLsizei count = static_cast<GLsizei>(header[0]);
  if (count < 0) {
    return false;
  }
  const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize;
  if (max_count < static_cast<size_t>(count)) {
    return false;
  }
  GLint* length = header + 1;
  std::vector<char*> strs(count);
  base::CheckedNumeric<size_t> total_size = sizeof(GLint);
  total_size *= count + 1;  // Header size.
  if (!total_size.IsValid())
    return false;
  for (GLsizei ii = 0; ii < count; ++ii) {
    strs[ii] = bucket_data + total_size.ValueOrDefault(0);
    total_size += length[ii];
    total_size += 1;  // NUL char at the end of each char array.
    if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size ||
        strs[ii][length[ii]] != 0) {
      return false;
    }
  }
  if (total_size.ValueOrDefault(0) != bucket_size) {
    return false;
  }
  DCHECK(_count && _string && _length);
  *_count = count;
  *_string = strs;
  _length->resize(count);
  for (GLsizei ii = 0; ii < count; ++ii) {
    (*_length)[ii] = length[ii];
  }
  return true;
}

CommonDecoder::CommonDecoder(CommandBufferServiceBase* command_buffer_service)
    : command_buffer_service_(command_buffer_service),
      max_bucket_size_(kDefaultMaxBucketSize) {
  DCHECK(command_buffer_service_);
}

CommonDecoder::~CommonDecoder() = default;

void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id,
                                            unsigned int data_offset,
                                            unsigned int data_size) {
  scoped_refptr<gpu::Buffer> buffer =
      command_buffer_service_->GetTransferBuffer(shm_id);
  if (!buffer.get())
    return nullptr;
  return buffer->GetDataAddress(data_offset, data_size);
}

void* CommonDecoder::GetAddressAndSize(unsigned int shm_id,
                                       unsigned int data_offset,
                                       unsigned int minimum_size,
                                       unsigned int* data_size) {
  scoped_refptr<gpu::Buffer> buffer =
      command_buffer_service_->GetTransferBuffer(shm_id);
  if (!buffer.get() || buffer->GetRemainingSize(data_offset) < minimum_size)
    return nullptr;
  return buffer->GetDataAddressAndSize(data_offset, data_size);
}

unsigned int CommonDecoder::GetSharedMemorySize(unsigned int shm_id,
                                                unsigned int offset) {
  scoped_refptr<gpu::Buffer> buffer =
      command_buffer_service_->GetTransferBuffer(shm_id);
  if (!buffer.get())
    return 0;
  return buffer->GetRemainingSize(offset);
}

scoped_refptr<gpu::Buffer> CommonDecoder::GetSharedMemoryBuffer(
    unsigned int shm_id) {
  return command_buffer_service_->GetTransferBuffer(shm_id);
}

const char* CommonDecoder::GetCommonCommandName(
    cmd::CommandId command_id) const {
  return cmd::GetCommandName(command_id);
}

CommonDecoder::Bucket* CommonDecoder::GetBucket(uint32_t bucket_id) const {
  BucketMap::const_iterator iter(buckets_.find(bucket_id));
  return iter != buckets_.end() ? &(*iter->second) : NULL;
}

CommonDecoder::Bucket* CommonDecoder::CreateBucket(uint32_t bucket_id) {
  Bucket* bucket = GetBucket(bucket_id);
  if (!bucket) {
    bucket = new Bucket();
    buckets_[bucket_id] = std::unique_ptr<Bucket>(bucket);
  }
  return bucket;
}

namespace {

// Returns the address of the first byte after a struct.
template <typename T>
const volatile void* AddressAfterStruct(const volatile T& pod) {
  return reinterpret_cast<const volatile uint8_t*>(&pod) + sizeof(pod);
}

// Returns the address of the frst byte after the struct.
template <typename RETURN_TYPE, typename COMMAND_TYPE>
RETURN_TYPE GetImmediateDataAs(const volatile COMMAND_TYPE& pod) {
  return static_cast<RETURN_TYPE>(
      const_cast<volatile void*>(AddressAfterStruct(pod)));
}

}  // anonymous namespace.

// Decode command with its arguments, and call the corresponding method.
// Note: args is a pointer to the command buffer. As such, it could be changed
// by a (malicious) client at any time, so if validation has to happen, it
// should operate on a copy of them.
error::Error CommonDecoder::DoCommonCommand(unsigned int command,
                                            unsigned int arg_count,
                                            const volatile void* cmd_data) {
  if (command < arraysize(command_info)) {
    const CommandInfo& info = command_info[command];
    unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
    if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
        (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
      uint32_t immediate_data_size =
          (arg_count - info_arg_count) * sizeof(CommandBufferEntry);  // NOLINT
      return (this->*info.cmd_handler)(immediate_data_size, cmd_data);
    } else {
      return error::kInvalidArguments;
    }
  }
  return error::kUnknownCommand;
}

error::Error CommonDecoder::HandleNoop(uint32_t immediate_data_size,
                                       const volatile void* cmd_data) {
  return error::kNoError;
}

error::Error CommonDecoder::HandleSetToken(uint32_t immediate_data_size,
                                           const volatile void* cmd_data) {
  const volatile cmd::SetToken& args =
      *static_cast<const volatile cmd::SetToken*>(cmd_data);
  command_buffer_service_->SetToken(args.token);
  return error::kNoError;
}

error::Error CommonDecoder::HandleSetBucketSize(uint32_t immediate_data_size,
                                                const volatile void* cmd_data) {
  const volatile cmd::SetBucketSize& args =
      *static_cast<const volatile cmd::SetBucketSize*>(cmd_data);
  uint32_t bucket_id = args.bucket_id;
  uint32_t size = args.size;
  if (size > max_bucket_size_)
    return error::kOutOfBounds;

  Bucket* bucket = CreateBucket(bucket_id);
  bucket->SetSize(size);
  return error::kNoError;
}

error::Error CommonDecoder::HandleSetBucketData(uint32_t immediate_data_size,
                                                const volatile void* cmd_data) {
  const volatile cmd::SetBucketData& args =
      *static_cast<const volatile cmd::SetBucketData*>(cmd_data);
  uint32_t bucket_id = args.bucket_id;
  uint32_t offset = args.offset;
  uint32_t size = args.size;
  const void* data = GetSharedMemoryAs<const void*>(
      args.shared_memory_id, args.shared_memory_offset, size);
  if (!data) {
    return error::kInvalidArguments;
  }
  Bucket* bucket = GetBucket(bucket_id);
  if (!bucket) {
    return error::kInvalidArguments;
  }
  if (!bucket->SetData(data, offset, size)) {
    return error::kInvalidArguments;
  }

  return error::kNoError;
}

error::Error CommonDecoder::HandleSetBucketDataImmediate(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile cmd::SetBucketDataImmediate& args =
      *static_cast<const volatile cmd::SetBucketDataImmediate*>(cmd_data);
  const volatile void* data = GetImmediateDataAs<const volatile void*>(args);
  uint32_t bucket_id = args.bucket_id;
  uint32_t offset = args.offset;
  uint32_t size = args.size;
  if (size > immediate_data_size) {
    return error::kInvalidArguments;
  }
  Bucket* bucket = GetBucket(bucket_id);
  if (!bucket) {
    return error::kInvalidArguments;
  }
  if (!bucket->SetData(data, offset, size)) {
    return error::kInvalidArguments;
  }
  return error::kNoError;
}

error::Error CommonDecoder::HandleGetBucketStart(
    uint32_t immediate_data_size,
    const volatile void* cmd_data) {
  const volatile cmd::GetBucketStart& args =
      *static_cast<const volatile cmd::GetBucketStart*>(cmd_data);
  uint32_t bucket_id = args.bucket_id;
  uint32_t* result = GetSharedMemoryAs<uint32_t*>(
      args.result_memory_id, args.result_memory_offset, sizeof(*result));
  int32_t data_memory_id = args.data_memory_id;
  uint32_t data_memory_offset = args.data_memory_offset;
  uint32_t data_memory_size = args.data_memory_size;
  uint8_t* data = NULL;
  if (data_memory_size != 0 || data_memory_id != 0 || data_memory_offset != 0) {
    data = GetSharedMemoryAs<uint8_t*>(data_memory_id, data_memory_offset,
                                       data_memory_size);
    if (!data) {
      return error::kInvalidArguments;
    }
  }
  if (!result) {
    return error::kInvalidArguments;
  }
  // Check that the client initialized the result.
  if (*result != 0) {
    return error::kInvalidArguments;
  }
  Bucket* bucket = GetBucket(bucket_id);
  if (!bucket) {
    return error::kInvalidArguments;
  }
  uint32_t bucket_size = bucket->size();
  *result = bucket_size;
  if (data) {
    uint32_t size = std::min(data_memory_size, bucket_size);
    memcpy(data, bucket->GetData(0, size), size);
  }
  return error::kNoError;
}

error::Error CommonDecoder::HandleGetBucketData(uint32_t immediate_data_size,
                                                const volatile void* cmd_data) {
  const volatile cmd::GetBucketData& args =
      *static_cast<const volatile cmd::GetBucketData*>(cmd_data);
  uint32_t bucket_id = args.bucket_id;
  uint32_t offset = args.offset;
  uint32_t size = args.size;
  void* data = GetSharedMemoryAs<void*>(
      args.shared_memory_id, args.shared_memory_offset, size);
  if (!data) {
    return error::kInvalidArguments;
  }
  Bucket* bucket = GetBucket(bucket_id);
  if (!bucket) {
    return error::kInvalidArguments;
  }
  const void* src = bucket->GetData(offset, size);
  if (!src) {
      return error::kInvalidArguments;
  }
  memcpy(data, src, size);
  return error::kNoError;
}

}  // namespace gpu
