Home | History | Annotate | Download | only in service
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_
      6 #define GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_
      7 
      8 #include <map>
      9 #include <stack>
     10 #include <string>
     11 #include "base/memory/linked_ptr.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "gpu/command_buffer/common/buffer.h"
     14 #include "gpu/command_buffer/service/cmd_parser.h"
     15 #include "gpu/gpu_export.h"
     16 
     17 namespace gpu {
     18 
     19 class CommandBufferEngine;
     20 
     21 // This class is a helper base class for implementing the common parts of the
     22 // o3d/gl2 command buffer decoder.
     23 class GPU_EXPORT CommonDecoder : NON_EXPORTED_BASE(public AsyncAPIInterface) {
     24  public:
     25   typedef error::Error Error;
     26 
     27   static const unsigned int kMaxStackDepth = 32;
     28 
     29   // A bucket is a buffer to help collect memory across a command buffer. When
     30   // creating a command buffer implementation of an existing API, sometimes that
     31   // API has functions that take a pointer to data.  A good example is OpenGL's
     32   // glBufferData. Because the data is separated between client and service,
     33   // there are 2 ways to get this data across. 1 is to put all the data in
     34   // shared memory. The problem with this is the data can be arbitarily large
     35   // and the host OS may not support that much shared memory. Another solution
     36   // is to shuffle memory across a little bit at a time, collecting it on the
     37   // service side and when it is all there then call glBufferData. Buckets
     38   // implement this second solution. Using the common commands, SetBucketSize,
     39   // SetBucketData, SetBucketDataImmediate the client can fill a bucket. It can
     40   // then call a command that uses that bucket (like BufferDataBucket in the
     41   // GLES2 command buffer implementation).
     42   //
     43   // If you are designing an API from scratch you can avoid this need for
     44   // Buckets by making your API always take an offset and a size
     45   // similar to glBufferSubData.
     46   //
     47   // Buckets also help pass strings to/from the service. To return a string of
     48   // arbitary size, the service puts the string in a bucket. The client can
     49   // then query the size of a bucket and request sections of the bucket to
     50   // be passed across shared memory.
     51   class GPU_EXPORT Bucket {
     52    public:
     53     Bucket();
     54     ~Bucket();
     55 
     56     size_t size() const {
     57       return size_;
     58     }
     59 
     60     // Gets a pointer to a section the bucket. Returns NULL if offset or size is
     61     // out of range.
     62     void* GetData(size_t offset, size_t size) const;
     63 
     64     template <typename T>
     65     T GetDataAs(size_t offset, size_t size) const {
     66       return reinterpret_cast<T>(GetData(offset, size));
     67     }
     68 
     69     // Sets the size of the bucket.
     70     void SetSize(size_t size);
     71 
     72     // Sets a part of the bucket.
     73     // Returns false if offset or size is out of range.
     74     bool SetData(const void* src, size_t offset, size_t size);
     75 
     76     // Sets the bucket data from a string. Strings are passed NULL terminated to
     77     // distinguish between empty string and no string.
     78     void SetFromString(const char* str);
     79 
     80     // Gets the bucket data as a string. Strings are passed NULL terminated to
     81     // distrinquish between empty string and no string. Returns False if there
     82     // is no string.
     83     bool GetAsString(std::string* str);
     84 
     85    private:
     86     bool OffsetSizeValid(size_t offset, size_t size) const {
     87       size_t temp = offset + size;
     88       return temp <= size_ && temp >= offset;
     89     }
     90 
     91     size_t size_;
     92     ::scoped_ptr<int8[]> data_;
     93 
     94     DISALLOW_COPY_AND_ASSIGN(Bucket);
     95   };
     96 
     97   CommonDecoder();
     98   virtual ~CommonDecoder();
     99 
    100   // Sets the engine, to get shared memory buffers from, and to set the token
    101   // to.
    102   void set_engine(CommandBufferEngine* engine) {
    103     engine_ = engine;
    104   }
    105   CommandBufferEngine* engine() const { return engine_; }
    106 
    107   // Creates a bucket. If the bucket already exists returns that bucket.
    108   Bucket* CreateBucket(uint32 bucket_id);
    109 
    110   // Gets a bucket. Returns NULL if the bucket does not exist.
    111   Bucket* GetBucket(uint32 bucket_id) const;
    112 
    113   // Gets the address of shared memory data, given a shared memory ID and an
    114   // offset. Also checks that the size is consistent with the shared memory
    115   // size.
    116   // Parameters:
    117   //   shm_id: the id of the shared memory buffer.
    118   //   offset: the offset of the data in the shared memory buffer.
    119   //   size: the size of the data.
    120   // Returns:
    121   //   NULL if shm_id isn't a valid shared memory buffer ID or if the size
    122   //   check fails. Return a pointer to the data otherwise.
    123   void* GetAddressAndCheckSize(unsigned int shm_id,
    124                                unsigned int offset,
    125                                unsigned int size);
    126 
    127   // Typed version of GetAddressAndCheckSize.
    128   template <typename T>
    129   T GetSharedMemoryAs(unsigned int shm_id, unsigned int offset,
    130                       unsigned int size) {
    131     return static_cast<T>(GetAddressAndCheckSize(shm_id, offset, size));
    132   }
    133 
    134   // Get the actual shared memory buffer.
    135   scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(unsigned int shm_id);
    136 
    137  protected:
    138   // Executes a common command.
    139   // Parameters:
    140   //    command: the command index.
    141   //    arg_count: the number of CommandBufferEntry arguments.
    142   //    cmd_data: the command data.
    143   // Returns:
    144   //   error::kNoError if no error was found, one of
    145   //   error::Error otherwise.
    146   error::Error DoCommonCommand(
    147       unsigned int command,
    148       unsigned int arg_count,
    149       const void* cmd_data);
    150 
    151   // Gets an name for a common command.
    152   const char* GetCommonCommandName(cmd::CommandId command_id) const;
    153 
    154  private:
    155   // Generate a member function prototype for each command in an automated and
    156   // typesafe way.
    157   #define COMMON_COMMAND_BUFFER_CMD_OP(name)             \
    158      error::Error Handle##name(                          \
    159        uint32 immediate_data_size,                       \
    160        const cmd::name& args);                           \
    161 
    162   COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
    163 
    164   #undef COMMON_COMMAND_BUFFER_CMD_OP
    165 
    166   CommandBufferEngine* engine_;
    167 
    168   typedef std::map<uint32, linked_ptr<Bucket> > BucketMap;
    169   BucketMap buckets_;
    170 };
    171 
    172 }  // namespace gpu
    173 
    174 #endif  // GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_
    175 
    176