diff options
Diffstat (limited to 'gpu/command_buffer/client/cmd_buffer_helper.h')
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper.h | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h new file mode 100644 index 0000000..7cac568 --- /dev/null +++ b/gpu/command_buffer/client/cmd_buffer_helper.h @@ -0,0 +1,216 @@ +/* + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +// This file contains the command buffer helper class. + +#ifndef GPU_COMMAND_BUFFER_CLIENT_CROSS_CMD_BUFFER_HELPER_H_ +#define GPU_COMMAND_BUFFER_CLIENT_CROSS_CMD_BUFFER_HELPER_H_ + +#include "gpu/command_buffer/common/logging.h" +#include "gpu/command_buffer/common/constants.h" +#include "gpu/command_buffer/common/cmd_buffer_common.h" +#include "gpu/command_buffer/common/command_buffer.h" + +namespace command_buffer { + +// Command buffer helper class. This class simplifies ring buffer management: +// it will allocate the buffer, give it to the buffer interface, and let the +// user add commands to it, while taking care of the synchronization (put and +// get). It also provides a way to ensure commands have been executed, through +// the token mechanism: +// +// helper.AddCommand(...); +// helper.AddCommand(...); +// int32 token = helper.InsertToken(); +// helper.AddCommand(...); +// helper.AddCommand(...); +// [...] +// +// helper.WaitForToken(token); // this doesn't return until the first two +// // commands have been executed. +class CommandBufferHelper { + public: + explicit CommandBufferHelper(command_buffer::CommandBuffer* command_buffer); + virtual ~CommandBufferHelper(); + + bool Initialize(); + + // Flushes the commands, setting the put pointer to let the buffer interface + // know that new commands have been added. After a flush returns, the command + // buffer service is aware of all pending commands and it is guaranteed to + // have made some progress in processing them. Returns whether the flush was + // successful. The flush will fail if the command buffer service has + // disconnected. + bool Flush(); + + // Waits until all the commands have been executed. Returns whether it + // was successful. The function will fail if the command buffer service has + // disconnected. + bool Finish(); + + // Waits until a given number of available entries are available. + // Parameters: + // count: number of entries needed. This value must be at most + // the size of the buffer minus one. + void WaitForAvailableEntries(int32 count); + + // Adds a command data to the command buffer. This may wait until sufficient + // space is available. + // Parameters: + // entries: The command entries to add. + // count: The number of entries. + void AddCommandData(const CommandBufferEntry* entries, int32 count) { + WaitForAvailableEntries(count); + for (; count > 0; --count) { + entries_[put_++] = *entries++; + } + DCHECK_LE(put_, entry_count_); + if (put_ == entry_count_) put_ = 0; + } + + // A typed version of AddCommandData. + template <typename T> + void AddTypedCmdData(const T& cmd) { + AddCommandData(reinterpret_cast<const CommandBufferEntry*>(&cmd), + ComputeNumEntries(sizeof(cmd))); + } + + // Adds a command to the command buffer. This may wait until sufficient space + // is available. + // Parameters: + // command: the command index. + // arg_count: the number of arguments for the command. + // args: the arguments for the command (these are copied before the + // function returns). + void AddCommand(int32 command, + int32 arg_count, + const CommandBufferEntry *args) { + CommandHeader header; + header.size = arg_count + 1; + header.command = command; + WaitForAvailableEntries(header.size); + entries_[put_++].value_header = header; + for (int i = 0; i < arg_count; ++i) { + entries_[put_++] = args[i]; + } + DCHECK_LE(put_, entry_count_); + if (put_ == entry_count_) put_ = 0; + } + + // Inserts a new token into the command buffer. This token either has a value + // different from previously inserted tokens, or ensures that previously + // inserted tokens with that value have already passed through the command + // stream. + // Returns: + // the value of the new token or -1 if the command buffer reader has + // shutdown. + int32 InsertToken(); + + // Waits until the token of a particular value has passed through the command + // stream (i.e. commands inserted before that token have been executed). + // NOTE: This will call Flush if it needs to block. + // Parameters: + // the value of the token to wait for. + void WaitForToken(int32 token); + + // Waits for a certain amount of space to be available. Returns address + // of space. + CommandBufferEntry* GetSpace(uint32 entries); + + // Typed version of GetSpace. Gets enough room for the given type and returns + // a reference to it. + template <typename T> + T& GetCmdSpace() { + COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed); + uint32 space_needed = ComputeNumEntries(sizeof(T)); + void* data = GetSpace(space_needed); + return *reinterpret_cast<T*>(data); + } + + // Typed version of GetSpace for immediate commands. + template <typename T> + T& GetImmediateCmdSpace(size_t data_space) { + COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN); + uint32 space_needed = ComputeNumEntries(sizeof(T) + data_space); + void* data = GetSpace(space_needed); + return *reinterpret_cast<T*>(data); + } + + // Typed version of GetSpace for immediate commands. + template <typename T> + T& GetImmediateCmdSpaceTotalSize(size_t total_space) { + COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN); + uint32 space_needed = ComputeNumEntries(total_space); + void* data = GetSpace(space_needed); + return *reinterpret_cast<T*>(data); + } + + parse_error::ParseError GetParseError(); + + // Common Commands + void Noop(uint32 skip_count) { + cmd::Noop& cmd = GetImmediateCmdSpace<cmd::Noop>( + skip_count * sizeof(CommandBufferEntry)); + cmd.Init(skip_count); + } + + void SetToken(uint32 token) { + cmd::SetToken& cmd = GetCmdSpace<cmd::SetToken>(); + cmd.Init(token); + } + + + private: + // Waits until get changes, updating the value of get_. + void WaitForGetChange(); + + // Returns the number of available entries (they may not be contiguous). + int32 AvailableEntries() { + return (get_ - put_ - 1 + entry_count_) % entry_count_; + } + + command_buffer::CommandBuffer* command_buffer_; + ::base::SharedMemory* ring_buffer_; + CommandBufferEntry *entries_; + int32 entry_count_; + int32 token_; + int32 last_token_read_; + int32 get_; + int32 put_; + + friend class CommandBufferHelperTest; + DISALLOW_COPY_AND_ASSIGN(CommandBufferHelper); +}; + +} // namespace command_buffer + +#endif // GPU_COMMAND_BUFFER_CLIENT_CROSS_CMD_BUFFER_HELPER_H_ |