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
|
// 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/command_buffer/service/gpu_command_buffer_service_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_COMMAND_BUFFER_SERVICE_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_COMMAND_BUFFER_SERVICE_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_
|