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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/common_decoder.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/cmd_buffer_engine.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu {
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommonDecoder::Bucket::Bucket() : size_(0) {}
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommonDecoder::Bucket::~Bucket() {}
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* CommonDecoder::Bucket::GetData(size_t offset, size_t size) const {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (OffsetSizeValid(offset, size)) {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data_.get() + offset;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommonDecoder::Bucket::SetSize(size_t size) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size != size_) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_.reset(size ? new int8[size] : NULL);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_ = size;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(data_.get(), 0, size);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommonDecoder::Bucket::SetData(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* src, size_t offset, size_t size) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (OffsetSizeValid(offset, size)) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(data_.get() + offset, src, size);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommonDecoder::Bucket::SetFromString(const char* str) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strings are passed NULL terminated to distinguish between empty string
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and no string.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!str) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetSize(0);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size = strlen(str) + 1;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetSize(size);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetData(str, 0, size);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommonDecoder::Bucket::GetAsString(std::string* str) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(str);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size_ == 0) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  str->assign(GetDataAs<const char*>(0, size_ - 1), size_ - 1);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommonDecoder::CommonDecoder() : engine_(NULL) {}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommonDecoder::~CommonDecoder() {}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id,
64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                            unsigned int data_offset,
65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                            unsigned int data_size) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(engine_);
67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  scoped_refptr<gpu::Buffer> buffer = engine_->GetSharedMemoryBuffer(shm_id);
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!buffer.get())
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return buffer->GetDataAddress(data_offset, data_size);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_refptr<gpu::Buffer> CommonDecoder::GetSharedMemoryBuffer(
74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    unsigned int shm_id) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return engine_->GetSharedMemoryBuffer(shm_id);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* CommonDecoder::GetCommonCommandName(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd::CommandId command_id) const {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return cmd::GetCommandName(command_id);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommonDecoder::Bucket* CommonDecoder::GetBucket(uint32 bucket_id) const {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BucketMap::const_iterator iter(buckets_.find(bucket_id));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return iter != buckets_.end() ? &(*iter->second) : NULL;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommonDecoder::Bucket* CommonDecoder::CreateBucket(uint32 bucket_id) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bucket* bucket = GetBucket(bucket_id);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bucket) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bucket = new Bucket();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buckets_[bucket_id] = linked_ptr<Bucket>(bucket);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bucket;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the address of the first byte after a struct.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T>
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void* AddressAfterStruct(const T& pod) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the address of the frst byte after the struct.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename RETURN_TYPE, typename COMMAND_TYPE>
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod)));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(vmiura): Looks like this g_command_info is duplicated in
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// common_decoder.cc
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// and gles2_cmd_decoder.cc.  Fix it!
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A struct to hold info about each command.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CommandInfo {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint8 arg_flags;   // How to handle the arguments for this command
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint8 cmd_flags;   // How to handle this command
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint16 arg_count;  // How many arguments are expected for this command.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A table of CommandInfo for all the commands.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CommandInfo g_command_info[] = {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define COMMON_COMMAND_BUFFER_CMD_OP(name) {                           \
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmd::name::kArgFlags,                                                \
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cmd::name::cmd_flags,                                                \
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, },  /* NOLINT */
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #undef COMMON_COMMAND_BUFFER_CMD_OP
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decode command with its arguments, and call the corresponding method.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: args is a pointer to the command buffer. As such, it could be changed
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by a (malicious) client at any time, so if validation has to happen, it
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// should operate on a copy of them.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error::Error CommonDecoder::DoCommonCommand(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int command,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int arg_count,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* cmd_data) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (command < arraysize(g_command_info)) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CommandInfo& info = g_command_info[command];
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32 immediate_data_size =
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (arg_count - info_arg_count) * sizeof(CommandBufferEntry);  // NOLINT
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (command) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #define COMMON_COMMAND_BUFFER_CMD_OP(name)                      \
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          case cmd::name::kCmdId:                                       \
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return Handle ## name(                                      \
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                immediate_data_size,                                    \
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *static_cast<const cmd::name*>(cmd_data));              \
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        #undef COMMON_COMMAND_BUFFER_CMD_OP
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return error::kInvalidArguments;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error::kUnknownCommand;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error::Error CommonDecoder::HandleNoop(
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 immediate_data_size,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const cmd::Noop& args) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error::kNoError;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error::Error CommonDecoder::HandleSetToken(
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 immediate_data_size,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const cmd::SetToken& args) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  engine_->set_token(args.token);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error::kNoError;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error::Error CommonDecoder::HandleSetBucketSize(
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 immediate_data_size,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const cmd::SetBucketSize& args) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bucket_id = args.bucket_id;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size = args.size;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bucket* bucket = CreateBucket(bucket_id);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bucket->SetSize(size);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error::kNoError;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error::Error CommonDecoder::HandleSetBucketData(
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 immediate_data_size,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const cmd::SetBucketData& args) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bucket_id = args.bucket_id;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 offset = args.offset;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size = args.size;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void* data = GetSharedMemoryAs<const void*>(
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      args.shared_memory_id, args.shared_memory_offset, size);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bucket* bucket = GetBucket(bucket_id);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bucket) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bucket->SetData(data, offset, size)) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error::kNoError;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error::Error CommonDecoder::HandleSetBucketDataImmediate(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 immediate_data_size,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const cmd::SetBucketDataImmediate& args) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void* data = GetImmediateDataAs<const void*>(args);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bucket_id = args.bucket_id;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 offset = args.offset;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size = args.size;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size > immediate_data_size) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bucket* bucket = GetBucket(bucket_id);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bucket) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bucket->SetData(data, offset, size)) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error::kNoError;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error::Error CommonDecoder::HandleGetBucketStart(
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 immediate_data_size,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const cmd::GetBucketStart& args) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bucket_id = args.bucket_id;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32* result = GetSharedMemoryAs<uint32*>(
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      args.result_memory_id, args.result_memory_offset, sizeof(*result));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 data_memory_id = args.data_memory_id;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 data_memory_offset = args.data_memory_offset;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 data_memory_size = args.data_memory_size;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* data = NULL;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data_memory_size != 0 || data_memory_id != 0 || data_memory_offset != 0) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data = GetSharedMemoryAs<uint8*>(
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        args.data_memory_id, args.data_memory_offset, args.data_memory_size);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return error::kInvalidArguments;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the client initialized the result.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*result != 0) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bucket* bucket = GetBucket(bucket_id);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bucket) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bucket_size = bucket->size();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = bucket_size;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 size = std::min(data_memory_size, bucket_size);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(data, bucket->GetData(0, size), size);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error::kNoError;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error::Error CommonDecoder::HandleGetBucketData(
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 immediate_data_size,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const cmd::GetBucketData& args) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bucket_id = args.bucket_id;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 offset = args.offset;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size = args.size;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* data = GetSharedMemoryAs<void*>(
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      args.shared_memory_id, args.shared_memory_offset, size);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bucket* bucket = GetBucket(bucket_id);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!bucket) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error::kInvalidArguments;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void* src = bucket->GetData(offset, size);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!src) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return error::kInvalidArguments;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(data, src, size);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error::kNoError;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gpu
296