Reland "Non-SFI mode: Switch to newlib. (patchset #4 id:60001 of https://codereview...
[chromium-blink-merge.git] / gpu / command_buffer / client / share_group.cc
blobf5c9bf1144cfe5c148db93f0226ac664989d57e8
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.
5 #include <stack>
6 #include <vector>
8 #include "gpu/command_buffer/client/share_group.h"
10 #include "base/logging.h"
11 #include "base/synchronization/lock.h"
12 #include "gpu/command_buffer/client/gles2_implementation.h"
13 #include "gpu/command_buffer/client/program_info_manager.h"
14 #include "gpu/command_buffer/common/id_allocator.h"
16 namespace gpu {
17 namespace gles2 {
19 ShareGroupContextData::IdHandlerData::IdHandlerData() : flush_generation_(0) {}
20 ShareGroupContextData::IdHandlerData::~IdHandlerData() {}
22 static_assert(gpu::kInvalidResource == 0,
23 "GL expects kInvalidResource to be 0");
25 // The standard id handler.
26 class IdHandler : public IdHandlerInterface {
27 public:
28 IdHandler() { }
29 ~IdHandler() override {}
31 // Overridden from IdHandlerInterface.
32 void MakeIds(GLES2Implementation* /* gl_impl */,
33 GLuint id_offset,
34 GLsizei n,
35 GLuint* ids) override {
36 base::AutoLock auto_lock(lock_);
37 if (id_offset == 0) {
38 for (GLsizei ii = 0; ii < n; ++ii) {
39 ids[ii] = id_allocator_.AllocateID();
41 } else {
42 for (GLsizei ii = 0; ii < n; ++ii) {
43 ids[ii] = id_allocator_.AllocateIDAtOrAbove(id_offset);
44 id_offset = ids[ii] + 1;
49 // Overridden from IdHandlerInterface.
50 bool FreeIds(GLES2Implementation* gl_impl,
51 GLsizei n,
52 const GLuint* ids,
53 DeleteFn delete_fn) override {
54 base::AutoLock auto_lock(lock_);
56 for (GLsizei ii = 0; ii < n; ++ii) {
57 id_allocator_.FreeID(ids[ii]);
60 (gl_impl->*delete_fn)(n, ids);
61 // We need to ensure that the delete call is evaluated on the service side
62 // before any other contexts issue commands using these client ids.
63 gl_impl->helper()->CommandBufferHelper::OrderingBarrier();
64 return true;
67 // Overridden from IdHandlerInterface.
68 bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
69 GLenum target,
70 GLuint id,
71 BindFn bind_fn) override {
72 base::AutoLock auto_lock(lock_);
73 bool result = id ? id_allocator_.MarkAsUsed(id) : true;
74 (gl_impl->*bind_fn)(target, id);
75 return result;
77 bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
78 GLenum target,
79 GLuint index,
80 GLuint id,
81 BindIndexedFn bind_fn) override {
82 base::AutoLock auto_lock(lock_);
83 bool result = id ? id_allocator_.MarkAsUsed(id) : true;
84 (gl_impl->*bind_fn)(target, index, id);
85 return result;
87 bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
88 GLenum target,
89 GLuint index,
90 GLuint id,
91 GLintptr offset,
92 GLsizeiptr size,
93 BindIndexedRangeFn bind_fn) override {
94 base::AutoLock auto_lock(lock_);
95 bool result = id ? id_allocator_.MarkAsUsed(id) : true;
96 (gl_impl->*bind_fn)(target, index, id, offset, size);
97 return result;
100 void FreeContext(GLES2Implementation* gl_impl) override {}
102 private:
103 base::Lock lock_;
104 IdAllocator id_allocator_;
107 // An id handler that requires Gen before Bind.
108 class StrictIdHandler : public IdHandlerInterface {
109 public:
110 explicit StrictIdHandler(int id_namespace) : id_namespace_(id_namespace) {}
111 ~StrictIdHandler() override {}
113 // Overridden from IdHandler.
114 void MakeIds(GLES2Implementation* gl_impl,
115 GLuint /* id_offset */,
116 GLsizei n,
117 GLuint* ids) override {
118 base::AutoLock auto_lock(lock_);
120 // Collect pending FreeIds from other flush_generation.
121 CollectPendingFreeIds(gl_impl);
123 for (GLsizei ii = 0; ii < n; ++ii) {
124 if (!free_ids_.empty()) {
125 // Allocate a previously freed Id.
126 ids[ii] = free_ids_.top();
127 free_ids_.pop();
129 // Record kIdInUse state.
130 DCHECK(id_states_[ids[ii] - 1] == kIdFree);
131 id_states_[ids[ii] - 1] = kIdInUse;
132 } else {
133 // Allocate a new Id.
134 id_states_.push_back(kIdInUse);
135 ids[ii] = id_states_.size();
140 // Overridden from IdHandler.
141 bool FreeIds(GLES2Implementation* gl_impl,
142 GLsizei n,
143 const GLuint* ids,
144 DeleteFn delete_fn) override {
145 // Delete stub must run before CollectPendingFreeIds.
146 (gl_impl->*delete_fn)(n, ids);
149 base::AutoLock auto_lock(lock_);
151 // Collect pending FreeIds from other flush_generation.
152 CollectPendingFreeIds(gl_impl);
154 // Save Ids to free in a later flush_generation.
155 ShareGroupContextData::IdHandlerData* ctxt_data =
156 gl_impl->share_group_context_data()->id_handler_data(id_namespace_);
158 for (GLsizei ii = 0; ii < n; ++ii) {
159 GLuint id = ids[ii];
160 if (id != 0) {
161 // Save freed Id for later.
162 DCHECK(id_states_[id - 1] == kIdInUse);
163 id_states_[id - 1] = kIdPendingFree;
164 ctxt_data->freed_ids_.push_back(id);
169 return true;
172 // Overridden from IdHandler.
173 bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
174 GLenum target,
175 GLuint id,
176 BindFn bind_fn) override {
177 #ifndef NDEBUG
178 if (id != 0) {
179 base::AutoLock auto_lock(lock_);
180 DCHECK(id_states_[id - 1] == kIdInUse);
182 #endif
183 // StrictIdHandler is used if |bind_generates_resource| is false. In that
184 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
185 // to call |bind_fn| without holding the lock.
186 (gl_impl->*bind_fn)(target, id);
187 return true;
189 bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
190 GLenum target,
191 GLuint index,
192 GLuint id,
193 BindIndexedFn bind_fn) override {
194 #ifndef NDEBUG
195 if (id != 0) {
196 base::AutoLock auto_lock(lock_);
197 DCHECK(id_states_[id - 1] == kIdInUse);
199 #endif
200 // StrictIdHandler is used if |bind_generates_resource| is false. In that
201 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
202 // to call |bind_fn| without holding the lock.
203 (gl_impl->*bind_fn)(target, index, id);
204 return true;
206 bool MarkAsUsedForBind(GLES2Implementation* gl_impl,
207 GLenum target,
208 GLuint index,
209 GLuint id,
210 GLintptr offset,
211 GLsizeiptr size,
212 BindIndexedRangeFn bind_fn) override {
213 #ifndef NDEBUG
214 if (id != 0) {
215 base::AutoLock auto_lock(lock_);
216 DCHECK(id_states_[id - 1] == kIdInUse);
218 #endif
219 // StrictIdHandler is used if |bind_generates_resource| is false. In that
220 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
221 // to call |bind_fn| without holding the lock.
222 (gl_impl->*bind_fn)(target, index, id, offset, size);
223 return true;
226 // Overridden from IdHandlerInterface.
227 void FreeContext(GLES2Implementation* gl_impl) override {
228 base::AutoLock auto_lock(lock_);
229 CollectPendingFreeIds(gl_impl);
232 private:
233 enum IdState { kIdFree, kIdPendingFree, kIdInUse };
235 void CollectPendingFreeIds(GLES2Implementation* gl_impl) {
236 uint32 flush_generation = gl_impl->helper()->flush_generation();
237 ShareGroupContextData::IdHandlerData* ctxt_data =
238 gl_impl->share_group_context_data()->id_handler_data(id_namespace_);
240 if (ctxt_data->flush_generation_ != flush_generation) {
241 ctxt_data->flush_generation_ = flush_generation;
242 for (uint32 ii = 0; ii < ctxt_data->freed_ids_.size(); ++ii) {
243 const GLuint id = ctxt_data->freed_ids_[ii];
244 DCHECK(id_states_[id - 1] == kIdPendingFree);
245 id_states_[id - 1] = kIdFree;
246 free_ids_.push(id);
248 ctxt_data->freed_ids_.clear();
252 int id_namespace_;
254 base::Lock lock_;
255 std::vector<uint8> id_states_;
256 std::stack<uint32> free_ids_;
259 // An id handler for ids that are never reused.
260 class NonReusedIdHandler : public IdHandlerInterface {
261 public:
262 NonReusedIdHandler() : last_id_(0) {}
263 ~NonReusedIdHandler() override {}
265 // Overridden from IdHandlerInterface.
266 void MakeIds(GLES2Implementation* /* gl_impl */,
267 GLuint id_offset,
268 GLsizei n,
269 GLuint* ids) override {
270 base::AutoLock auto_lock(lock_);
271 for (GLsizei ii = 0; ii < n; ++ii) {
272 ids[ii] = ++last_id_ + id_offset;
276 // Overridden from IdHandlerInterface.
277 bool FreeIds(GLES2Implementation* gl_impl,
278 GLsizei n,
279 const GLuint* ids,
280 DeleteFn delete_fn) override {
281 // Ids are never freed.
282 (gl_impl->*delete_fn)(n, ids);
283 return true;
286 // Overridden from IdHandlerInterface.
287 bool MarkAsUsedForBind(GLES2Implementation* /* gl_impl */,
288 GLenum /* target */,
289 GLuint /* id */,
290 BindFn /* bind_fn */) override {
291 // This is only used for Shaders and Programs which have no bind.
292 return false;
294 bool MarkAsUsedForBind(GLES2Implementation* /* gl_impl */,
295 GLenum /* target */,
296 GLuint /* index */,
297 GLuint /* id */,
298 BindIndexedFn /* bind_fn */) override {
299 // This is only used for Shaders and Programs which have no bind.
300 return false;
302 bool MarkAsUsedForBind(GLES2Implementation* /* gl_impl */,
303 GLenum /* target */,
304 GLuint /* index */,
305 GLuint /* id */,
306 GLintptr /* offset */,
307 GLsizeiptr /* size */,
308 BindIndexedRangeFn /* bind_fn */) override {
309 // This is only used for Shaders and Programs which have no bind.
310 return false;
313 void FreeContext(GLES2Implementation* gl_impl) override {}
315 private:
316 base::Lock lock_;
317 GLuint last_id_;
320 ShareGroup::ShareGroup(bool bind_generates_resource)
321 : bind_generates_resource_(bind_generates_resource) {
322 if (bind_generates_resource) {
323 for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
324 if (i == id_namespaces::kProgramsAndShaders) {
325 id_handlers_[i].reset(new NonReusedIdHandler());
326 } else {
327 id_handlers_[i].reset(new IdHandler());
330 } else {
331 for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
332 if (i == id_namespaces::kProgramsAndShaders) {
333 id_handlers_[i].reset(new NonReusedIdHandler());
334 } else {
335 id_handlers_[i].reset(new StrictIdHandler(i));
339 program_info_manager_.reset(new ProgramInfoManager);
342 void ShareGroup::set_program_info_manager(ProgramInfoManager* manager) {
343 program_info_manager_.reset(manager);
346 ShareGroup::~ShareGroup() {}
348 } // namespace gles2
349 } // namespace gpu