OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file contains the implementation of the command buffer helper class. | 5 // This file contains the implementation of the command buffer helper class. |
6 | 6 |
7 #include "../client/cmd_buffer_helper.h" | 7 #include "../client/cmd_buffer_helper.h" |
8 #include "../common/command_buffer.h" | 8 #include "../common/command_buffer.h" |
9 | 9 |
10 namespace gpu { | 10 namespace gpu { |
11 | 11 |
12 CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) | 12 CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) |
13 : command_buffer_(command_buffer), | 13 : command_buffer_(command_buffer), |
14 entries_(NULL), | 14 entries_(NULL), |
15 entry_count_(0), | 15 total_entry_count_(0), |
| 16 usable_entry_count_(0), |
16 token_(0), | 17 token_(0), |
17 last_token_read_(-1), | 18 last_token_read_(-1), |
18 get_(0), | 19 get_(0), |
19 put_(0) { | 20 put_(0) { |
20 } | 21 } |
21 | 22 |
22 bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { | 23 bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { |
23 ring_buffer_ = command_buffer_->GetRingBuffer(); | 24 ring_buffer_ = command_buffer_->GetRingBuffer(); |
24 if (!ring_buffer_.ptr) | 25 if (!ring_buffer_.ptr) |
25 return false; | 26 return false; |
26 | 27 |
27 CommandBuffer::State state = command_buffer_->GetState(); | 28 CommandBuffer::State state = command_buffer_->GetState(); |
28 entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr); | 29 entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr); |
29 int32 num_ring_buffer_entries = ring_buffer_size / sizeof(CommandBufferEntry); | 30 int32 num_ring_buffer_entries = ring_buffer_size / sizeof(CommandBufferEntry); |
30 if (num_ring_buffer_entries > state.num_entries) { | 31 if (num_ring_buffer_entries > state.num_entries) { |
31 return false; | 32 return false; |
32 } | 33 } |
33 entry_count_ = num_ring_buffer_entries; | 34 |
| 35 const int32 kJumpEntries = |
| 36 sizeof(cmd::Jump) / sizeof(*entries_); // NOLINT |
| 37 |
| 38 total_entry_count_ = num_ring_buffer_entries; |
| 39 usable_entry_count_ = total_entry_count_ - kJumpEntries; |
34 put_ = state.put_offset; | 40 put_ = state.put_offset; |
35 SynchronizeState(state); | 41 SynchronizeState(state); |
36 return true; | 42 return true; |
37 } | 43 } |
38 | 44 |
39 CommandBufferHelper::~CommandBufferHelper() { | 45 CommandBufferHelper::~CommandBufferHelper() { |
40 } | 46 } |
41 | 47 |
42 bool CommandBufferHelper::Flush() { | 48 bool CommandBufferHelper::Flush() { |
43 CommandBuffer::State state = command_buffer_->Flush(put_); | 49 CommandBuffer::State state = command_buffer_->Flush(put_); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 } | 98 } |
93 // Do not loop forever if the flush fails, meaning the command buffer reader | 99 // Do not loop forever if the flush fails, meaning the command buffer reader |
94 // has shutdown. | 100 // has shutdown. |
95 if (!Flush()) | 101 if (!Flush()) |
96 return; | 102 return; |
97 } | 103 } |
98 } | 104 } |
99 | 105 |
100 // Waits for available entries, basically waiting until get >= put + count + 1. | 106 // Waits for available entries, basically waiting until get >= put + count + 1. |
101 // It actually waits for contiguous entries, so it may need to wrap the buffer | 107 // It actually waits for contiguous entries, so it may need to wrap the buffer |
102 // around, adding noops. Thus this function may change the value of put_. | 108 // around, adding a jump. Thus this function may change the value of put_. The |
103 // The function will return early if an error occurs, in which case the | 109 // function will return early if an error occurs, in which case the available |
104 // available space may not be available. | 110 // space may not be available. |
105 void CommandBufferHelper::WaitForAvailableEntries(int32 count) { | 111 void CommandBufferHelper::WaitForAvailableEntries(int32 count) { |
106 CHECK(count < entry_count_); | 112 CHECK(count < usable_entry_count_); |
107 if (put_ + count > entry_count_) { | 113 if (put_ + count > usable_entry_count_) { |
108 // There's not enough room between the current put and the end of the | 114 // There's not enough room between the current put and the end of the |
109 // buffer, so we need to wrap. We will add noops all the way to the end, | 115 // buffer, so we need to wrap. We will add a jump back to the start, but we |
110 // but we need to make sure get wraps first, actually that get is 1 or | 116 // need to make sure get wraps first, actually that get is 1 or more (since |
111 // more (since put will wrap to 0 after we add the noops). | 117 // put will wrap to 0 after we add the jump). |
112 DCHECK_LE(1, put_); | 118 DCHECK_LE(1, put_); |
113 Flush(); | 119 Flush(); |
114 while (get_ > put_ || get_ == 0) { | 120 while (get_ > put_ || get_ == 0) { |
115 // Do not loop forever if the flush fails, meaning the command buffer | 121 // Do not loop forever if the flush fails, meaning the command buffer |
116 // reader has shutdown. | 122 // reader has shutdown. |
117 if (!Flush()) | 123 if (!Flush()) |
118 return; | 124 return; |
119 } | 125 } |
120 // Insert Noops to fill out buffer. | 126 // Insert a jump back to the beginning. |
121 int32 num_entries = entry_count_ - put_; | 127 cmd::Jump::Set(&entries_[put_], 0); |
122 while (num_entries > 0) { | |
123 int32 num_to_skip = std::min(CommandHeader::kMaxSize, num_entries); | |
124 cmd::Noop::Set(&entries_[put_], num_to_skip); | |
125 put_ += num_to_skip; | |
126 num_entries -= num_to_skip; | |
127 } | |
128 put_ = 0; | 128 put_ = 0; |
129 } | 129 } |
130 // If we have enough room, return immediatly. | 130 // If we have enough room, return immediatly. |
131 if (count <= AvailableEntries()) return; | 131 if (count <= AvailableEntries()) return; |
132 // Otherwise flush, and wait until we do have enough room. | 132 // Otherwise flush, and wait until we do have enough room. |
133 Flush(); | 133 Flush(); |
134 while (AvailableEntries() < count) { | 134 while (AvailableEntries() < count) { |
135 // Do not loop forever if the flush fails, meaning the command buffer reader | 135 // Do not loop forever if the flush fails, meaning the command buffer reader |
136 // has shutdown. | 136 // has shutdown. |
137 if (!Flush()) | 137 if (!Flush()) |
138 return; | 138 return; |
139 } | 139 } |
140 } | 140 } |
141 | 141 |
142 CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) { | 142 CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) { |
143 WaitForAvailableEntries(entries); | 143 WaitForAvailableEntries(entries); |
144 CommandBufferEntry* space = &entries_[put_]; | 144 CommandBufferEntry* space = &entries_[put_]; |
145 put_ += entries; | 145 put_ += entries; |
146 DCHECK_LE(put_, entry_count_); | 146 DCHECK_LE(put_, usable_entry_count_); |
147 if (put_ == entry_count_) { | 147 if (put_ == usable_entry_count_) { |
| 148 cmd::Jump::Set(&entries_[put_], 0); |
148 put_ = 0; | 149 put_ = 0; |
149 } | 150 } |
150 return space; | 151 return space; |
151 } | 152 } |
152 | 153 |
153 error::Error CommandBufferHelper::GetError() { | 154 error::Error CommandBufferHelper::GetError() { |
154 CommandBuffer::State state = command_buffer_->GetState(); | 155 CommandBuffer::State state = command_buffer_->GetState(); |
155 SynchronizeState(state); | 156 SynchronizeState(state); |
156 return static_cast<error::Error>(state.error); | 157 return static_cast<error::Error>(state.error); |
157 } | 158 } |
158 | 159 |
159 void CommandBufferHelper::SynchronizeState(CommandBuffer::State state) { | 160 void CommandBufferHelper::SynchronizeState(CommandBuffer::State state) { |
160 get_ = state.get_offset; | 161 get_ = state.get_offset; |
161 last_token_read_ = state.token; | 162 last_token_read_ = state.token; |
162 } | 163 } |
163 | 164 |
164 } // namespace gpu | 165 } // namespace gpu |
OLD | NEW |