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_