1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244

gpu / command_buffer / service / common_decoder.h [blame]

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

#ifndef GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_
#define GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_

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

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "gpu/command_buffer/common/buffer.h"
#include "gpu/command_buffer/common/cmd_buffer_common.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/gpu_export.h"

// Forwardly declare a few GL types to avoid including GL header files.
using GLsizei = int;
using GLint = int;

namespace gfx {
class ColorSpace;
}  // namespace gfx

namespace gpu {

class CommandBufferServiceBase;
class DecoderClient;

// This class is a helper base class for implementing the common parts of the
// o3d/gl2 command buffer decoder.
class GPU_EXPORT CommonDecoder {
 public:
  using Error = error::Error;

  static constexpr unsigned int kMaxStackDepth = 32;

  // A bucket is a buffer to help collect memory across a command buffer. When
  // creating a command buffer implementation of an existing API, sometimes that
  // API has functions that take a pointer to data.  A good example is OpenGL's
  // glBufferData. Because the data is separated between client and service,
  // there are 2 ways to get this data across. 1 is to put all the data in
  // shared memory. The problem with this is the data can be arbitarily large
  // and the host OS may not support that much shared memory. Another solution
  // is to shuffle memory across a little bit at a time, collecting it on the
  // service side and when it is all there then call glBufferData. Buckets
  // implement this second solution. Using the common commands, SetBucketSize,
  // SetBucketData, SetBucketDataImmediate the client can fill a bucket. It can
  // then call a command that uses that bucket (like BufferDataBucket in the
  // GLES2 command buffer implementation).
  //
  // If you are designing an API from scratch you can avoid this need for
  // Buckets by making your API always take an offset and a size
  // similar to glBufferSubData.
  //
  // Buckets also help pass strings to/from the service. To return a string of
  // arbitary size, the service puts the string in a bucket. The client can
  // then query the size of a bucket and request sections of the bucket to
  // be passed across shared memory.
  class GPU_EXPORT Bucket {
   public:
    Bucket();

    Bucket(const Bucket&) = delete;
    Bucket& operator=(const Bucket&) = delete;

    ~Bucket();

    size_t size() const {
      return size_;
    }

    // Gets a pointer to a section the bucket. Returns nullptr if offset or size
    // is out of range.
    void* GetData(size_t offset, size_t size) const;

    template <typename T>
    T GetDataAs(size_t offset, size_t size) const {
      return reinterpret_cast<T>(GetData(offset, size));
    }

    // Sets the size of the bucket.
    void SetSize(size_t size);

    // Sets a part of the bucket.
    // Returns false if offset or size is out of range.
    bool SetData(const volatile void* src, size_t offset, size_t size);

    // Sets the bucket data from a string. Strings are passed NULL terminated to
    // distinguish between empty string and no string.
    void SetFromString(const char* str);

    // Gets the bucket data as a string. Strings are passed NULL terminated to
    // distrinquish between empty string and no string. Returns False if there
    // is no string.
    bool GetAsString(std::string* str);

    // Gets the bucket data as strings.
    // On success, the number of strings are in |_count|, the string data are
    // in |_string|, and string sizes are in |_length|..
    bool GetAsStrings(GLsizei* _count,
                      std::vector<char*>* _string,
                      std::vector<GLint>* _length);

   private:
    bool OffsetSizeValid(size_t offset, size_t size) const;

    size_t size_;
    ::std::unique_ptr<int8_t[]> data_;
  };

  explicit CommonDecoder(DecoderClient* client,
                         CommandBufferServiceBase* command_buffer_service);

  CommonDecoder(const CommonDecoder&) = delete;
  CommonDecoder& operator=(const CommonDecoder&) = delete;

  ~CommonDecoder();

  CommandBufferServiceBase* command_buffer_service() const {
    return command_buffer_service_;
  }

  DecoderClient* client() const { return client_; }

  // Sets the maximum size for buckets.
  void set_max_bucket_size(size_t max_bucket_size) {
    max_bucket_size_ = max_bucket_size;
  }

  // Creates a bucket. If the bucket already exists returns that bucket.
  Bucket* CreateBucket(uint32_t bucket_id);

  // Gets a bucket. Returns nullptr if the bucket does not exist.
  Bucket* GetBucket(uint32_t bucket_id) const;

  // Gets the address of shared memory data, given a shared memory ID and an
  // offset. Also checks that the size is consistent with the shared memory
  // size.
  // Parameters:
  //   shm_id: the id of the shared memory buffer.
  //   offset: the offset of the data in the shared memory buffer.
  //   size: the size of the data.
  // Returns:
  //   nullptr if shm_id isn't a valid shared memory buffer ID or if the size
  //   check fails. Return a pointer to the data otherwise.
  void* GetAddressAndCheckSize(unsigned int shm_id,
                               unsigned int offset,
                               unsigned int size);

  // Typed version of GetAddressAndCheckSize.
  template <typename T>
  T GetSharedMemoryAs(unsigned int shm_id, unsigned int offset,
                      unsigned int size) {
    return static_cast<T>(GetAddressAndCheckSize(shm_id, offset, size));
  }

  void* GetAddressAndSize(unsigned int shm_id,
                          unsigned int offset,
                          unsigned int minimum_size,
                          unsigned int* size);

  template <typename T>
  T GetSharedMemoryAndSizeAs(unsigned int shm_id,
                             unsigned int offset,
                             unsigned int minimum_size,
                             unsigned int* size) {
    return static_cast<T>(
        GetAddressAndSize(shm_id, offset, minimum_size, size));
  }

  unsigned int GetSharedMemorySize(unsigned int shm_id, unsigned int offset);

  // Get the actual shared memory buffer.
  scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(unsigned int shm_id);

 protected:
  // Executes a common command.
  // Parameters:
  //    command: the command index.
  //    arg_count: the number of CommandBufferEntry arguments.
  //    cmd_data: the command data.
  // Returns:
  //   error::kNoError if no error was found, one of
  //   error::Error otherwise.
  error::Error DoCommonCommand(unsigned int command,
                               unsigned int arg_count,
                               const volatile void* cmd_data);

  // Gets an name for a common command.
  const char* GetCommonCommandName(cmd::CommandId command_id) const;

  // Exit the command processing loop to allow context preemption and GPU
  // watchdog checks in CommandExecutor().
  virtual void ExitCommandProcessingEarly() {}

  // Read a serialized gfx::ColorSpace. Return true on success and false if the
  // serialization was invalid.
  bool ReadColorSpace(uint32_t shm_id,
                      uint32_t shm_offset,
                      uint32_t color_space_size,
                      gfx::ColorSpace* color_space);

 private:
  // Generate a member function prototype for each command in an automated and
  // typesafe way.
#define COMMON_COMMAND_BUFFER_CMD_OP(name)                \
  error::Error Handle##name(uint32_t immediate_data_size, \
                            const volatile void* data);

  COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)

  #undef COMMON_COMMAND_BUFFER_CMD_OP

  raw_ptr<CommandBufferServiceBase, DanglingUntriaged> command_buffer_service_;
  raw_ptr<DecoderClient, DanglingUntriaged> client_;
  size_t max_bucket_size_;

  using BucketMap = std::map<uint32_t, std::unique_ptr<Bucket>>;
  BucketMap buckets_;

  using CmdHandler = Error (CommonDecoder::*)(uint32_t immediate_data_size,
                                              const volatile void* data);

  // A struct to hold info about each command.
  struct CommandInfo {
    CmdHandler cmd_handler;
    uint8_t arg_flags;   // How to handle the arguments for this command
    uint8_t cmd_flags;   // How to handle this command
    uint16_t arg_count;  // How many arguments are expected for this command.
  };

  // A table of CommandInfo for all the commands.
  static const CommandInfo command_info[];
};

}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_