summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/common_decoder.h
blob: 03002c8b06f2baa87f072186f6d063054f38b014 (plain)
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
// 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.

#ifndef GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_
#define GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_

#include <map>
#include <stack>
#include <string>
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "gpu/command_buffer/common/buffer.h"
#include "gpu/command_buffer/service/cmd_parser.h"
#include "gpu/gpu_export.h"

namespace gpu {

class CommandBufferEngine;

// This class is a helper base class for implementing the common parts of the
// o3d/gl2 command buffer decoder.
class GPU_EXPORT CommonDecoder : NON_EXPORTED_BASE(public AsyncAPIInterface) {
 public:
  typedef error::Error Error;

  static const 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();

    size_t size() const {
      return size_;
    }

    // Gets a pointer to a section the bucket. Returns NULL 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 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);

   private:
    bool OffsetSizeValid(size_t offset, size_t size) const {
      size_t temp = offset + size;
      return temp <= size_ && temp >= offset;
    }

    size_t size_;
    ::scoped_ptr<int8[]> data_;

    DISALLOW_COPY_AND_ASSIGN(Bucket);
  };

  CommonDecoder();
  virtual ~CommonDecoder();

  // Sets the engine, to get shared memory buffers from, and to set the token
  // to.
  void set_engine(CommandBufferEngine* engine) {
    engine_ = engine;
  }
  CommandBufferEngine* engine() const { return engine_; }

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

  // Gets a bucket. Returns NULL if the bucket does not exist.
  Bucket* GetBucket(uint32 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:
  //   NULL 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));
  }

  // Get the actual shared memory buffer.
  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 void* cmd_data);

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

 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 immediate_data_size,                       \
       const cmd::name& args);                           \

  COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)

  #undef COMMON_COMMAND_BUFFER_CMD_OP

  CommandBufferEngine* engine_;

  typedef std::map<uint32, linked_ptr<Bucket> > BucketMap;
  BucketMap buckets_;
};

}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_