- add sources.
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / client / cmd_buffer_helper.h
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 // This file contains the command buffer helper class.
6
7 #ifndef GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_
8 #define GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_
9
10 #include <string.h>
11 #include <time.h>
12
13 #include "gpu/command_buffer/common/cmd_buffer_common.h"
14 #include "gpu/command_buffer/common/command_buffer.h"
15 #include "gpu/command_buffer/common/constants.h"
16 #include "gpu/command_buffer/common/logging.h"
17 #include "gpu/gpu_export.h"
18
19 namespace gpu {
20
21 // Command buffer helper class. This class simplifies ring buffer management:
22 // it will allocate the buffer, give it to the buffer interface, and let the
23 // user add commands to it, while taking care of the synchronization (put and
24 // get). It also provides a way to ensure commands have been executed, through
25 // the token mechanism:
26 //
27 // helper.AddCommand(...);
28 // helper.AddCommand(...);
29 // int32 token = helper.InsertToken();
30 // helper.AddCommand(...);
31 // helper.AddCommand(...);
32 // [...]
33 //
34 // helper.WaitForToken(token);  // this doesn't return until the first two
35 //                              // commands have been executed.
36 class GPU_EXPORT CommandBufferHelper {
37  public:
38   explicit CommandBufferHelper(CommandBuffer* command_buffer);
39   virtual ~CommandBufferHelper();
40
41   // Initializes the CommandBufferHelper.
42   // Parameters:
43   //   ring_buffer_size: The size of the ring buffer portion of the command
44   //       buffer.
45   bool Initialize(int32 ring_buffer_size);
46
47   // Sets whether the command buffer should automatically flush periodically
48   // to try to increase performance. Defaults to true.
49   void SetAutomaticFlushes(bool enabled);
50
51   // True if the context is lost.
52   bool IsContextLost();
53
54   // Asynchronously flushes the commands, setting the put pointer to let the
55   // buffer interface know that new commands have been added. After a flush
56   // returns, the command buffer service is aware of all pending commands.
57   void Flush();
58
59   // Flushes the commands, setting the put pointer to let the buffer interface
60   // know that new commands have been added. After a flush returns, the command
61   // buffer service is aware of all pending commands and it is guaranteed to
62   // have made some progress in processing them. Returns whether the flush was
63   // successful. The flush will fail if the command buffer service has
64   // disconnected.
65   bool FlushSync();
66
67   // Waits until all the commands have been executed. Returns whether it
68   // was successful. The function will fail if the command buffer service has
69   // disconnected.
70   bool Finish();
71
72   // Waits until a given number of available entries are available.
73   // Parameters:
74   //   count: number of entries needed. This value must be at most
75   //     the size of the buffer minus one.
76   void WaitForAvailableEntries(int32 count);
77
78   // Inserts a new token into the command buffer. This token either has a value
79   // different from previously inserted tokens, or ensures that previously
80   // inserted tokens with that value have already passed through the command
81   // stream.
82   // Returns:
83   //   the value of the new token or -1 if the command buffer reader has
84   //   shutdown.
85   int32 InsertToken();
86
87   // Waits until the token of a particular value has passed through the command
88   // stream (i.e. commands inserted before that token have been executed).
89   // NOTE: This will call Flush if it needs to block.
90   // Parameters:
91   //   the value of the token to wait for.
92   void WaitForToken(int32 token);
93
94   // Called prior to each command being issued. Waits for a certain amount of
95   // space to be available. Returns address of space.
96   CommandBufferEntry* GetSpace(uint32 entries);
97
98   // Typed version of GetSpace. Gets enough room for the given type and returns
99   // a reference to it.
100   template <typename T>
101   T* GetCmdSpace() {
102     COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed);
103     uint32 space_needed = ComputeNumEntries(sizeof(T));
104     void* data = GetSpace(space_needed);
105     return reinterpret_cast<T*>(data);
106   }
107
108   // Typed version of GetSpace for immediate commands.
109   template <typename T>
110   T* GetImmediateCmdSpace(size_t data_space) {
111     COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
112     uint32 space_needed = ComputeNumEntries(sizeof(T) + data_space);
113     void* data = GetSpace(space_needed);
114     return reinterpret_cast<T*>(data);
115   }
116
117   // Typed version of GetSpace for immediate commands.
118   template <typename T>
119   T* GetImmediateCmdSpaceTotalSize(size_t total_space) {
120     COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
121     uint32 space_needed = ComputeNumEntries(total_space);
122     void* data = GetSpace(space_needed);
123     return reinterpret_cast<T*>(data);
124   }
125
126   int32 last_token_read() const {
127     return command_buffer_->GetLastToken();
128   }
129
130   int32 get_offset() const {
131     return command_buffer_->GetLastState().get_offset;
132   }
133
134   // Common Commands
135   void Noop(uint32 skip_count) {
136     cmd::Noop* cmd = GetImmediateCmdSpace<cmd::Noop>(
137         (skip_count - 1) * sizeof(CommandBufferEntry));
138     if (cmd) {
139       cmd->Init(skip_count);
140     }
141   }
142
143   void SetToken(uint32 token) {
144     cmd::SetToken* cmd = GetCmdSpace<cmd::SetToken>();
145     if (cmd) {
146       cmd->Init(token);
147     }
148   }
149
150   void SetBucketSize(uint32 bucket_id, uint32 size) {
151     cmd::SetBucketSize* cmd = GetCmdSpace<cmd::SetBucketSize>();
152     if (cmd) {
153       cmd->Init(bucket_id, size);
154     }
155   }
156
157   void SetBucketData(uint32 bucket_id,
158                      uint32 offset,
159                      uint32 size,
160                      uint32 shared_memory_id,
161                      uint32 shared_memory_offset) {
162     cmd::SetBucketData* cmd = GetCmdSpace<cmd::SetBucketData>();
163     if (cmd) {
164       cmd->Init(bucket_id,
165                 offset,
166                 size,
167                 shared_memory_id,
168                 shared_memory_offset);
169     }
170   }
171
172   void SetBucketDataImmediate(
173       uint32 bucket_id, uint32 offset, const void* data, uint32 size) {
174     cmd::SetBucketDataImmediate* cmd =
175         GetImmediateCmdSpace<cmd::SetBucketDataImmediate>(size);
176     if (cmd) {
177       cmd->Init(bucket_id, offset, size);
178       memcpy(ImmediateDataAddress(cmd), data, size);
179     }
180   }
181
182   void GetBucketStart(uint32 bucket_id,
183                       uint32 result_memory_id,
184                       uint32 result_memory_offset,
185                       uint32 data_memory_size,
186                       uint32 data_memory_id,
187                       uint32 data_memory_offset) {
188     cmd::GetBucketStart* cmd = GetCmdSpace<cmd::GetBucketStart>();
189     if (cmd) {
190       cmd->Init(bucket_id,
191                 result_memory_id,
192                 result_memory_offset,
193                 data_memory_size,
194                 data_memory_id,
195                 data_memory_offset);
196     }
197   }
198
199   void GetBucketData(uint32 bucket_id,
200                      uint32 offset,
201                      uint32 size,
202                      uint32 shared_memory_id,
203                      uint32 shared_memory_offset) {
204     cmd::GetBucketData* cmd = GetCmdSpace<cmd::GetBucketData>();
205     if (cmd) {
206       cmd->Init(bucket_id,
207                 offset,
208                 size,
209                 shared_memory_id,
210                 shared_memory_offset);
211     }
212   }
213
214   CommandBuffer* command_buffer() const {
215     return command_buffer_;
216   }
217
218   Buffer get_ring_buffer() const {
219     return ring_buffer_;
220   }
221
222   void FreeRingBuffer();
223
224   bool HaveRingBuffer() const {
225     return ring_buffer_id_ != -1;
226   }
227
228   bool usable () const {
229     return usable_;
230   }
231
232   void ClearUsable() {
233     usable_ = false;
234   }
235
236  private:
237   // Waits until get changes, updating the value of get_.
238   void WaitForGetChange();
239
240   // Returns the number of available entries (they may not be contiguous).
241   int32 AvailableEntries() {
242     return (get_offset() - put_ - 1 + total_entry_count_) % total_entry_count_;
243   }
244
245   bool AllocateRingBuffer();
246   void FreeResources();
247
248   CommandBuffer* command_buffer_;
249   int32 ring_buffer_id_;
250   int32 ring_buffer_size_;
251   Buffer ring_buffer_;
252   CommandBufferEntry* entries_;
253   int32 total_entry_count_;  // the total number of entries
254   int32 token_;
255   int32 put_;
256   int32 last_put_sent_;
257   int commands_issued_;
258   bool usable_;
259   bool context_lost_;
260   bool flush_automatically_;
261
262   // Using C runtime instead of base because this file cannot depend on base.
263   clock_t last_flush_time_;
264
265   friend class CommandBufferHelperTest;
266   DISALLOW_COPY_AND_ASSIGN(CommandBufferHelper);
267 };
268
269 }  // namespace gpu
270
271 #endif  // GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_