Roll leveldb 3f7758:803d69 (v1.17 -> v1.18)
[chromium-blink-merge.git] / gpu / command_buffer / client / share_group.cc
blobc7e3845607d73d0bb669ce5912de82bfdcab5eaf
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 COMPILE_ASSERT(gpu::kInvalidResource == 0,
23 INVALID_RESOURCE_NOT_0_AS_GL_EXPECTS);
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 // TODO(vmiura): Can remove this by virtualizing internal ids, however
64 // this code only affects PPAPI for now.
65 gl_impl->helper()->CommandBufferHelper::Flush();
66 return true;
69 // Overridden from IdHandlerInterface.
70 bool MarkAsUsedForBind(GLuint id) override {
71 if (id == 0)
72 return true;
73 base::AutoLock auto_lock(lock_);
74 return id_allocator_.MarkAsUsed(id);
77 void FreeContext(GLES2Implementation* gl_impl) override {}
79 private:
80 base::Lock lock_;
81 IdAllocator id_allocator_;
84 // An id handler that requires Gen before Bind.
85 class StrictIdHandler : public IdHandlerInterface {
86 public:
87 explicit StrictIdHandler(int id_namespace) : id_namespace_(id_namespace) {}
88 ~StrictIdHandler() override {}
90 // Overridden from IdHandler.
91 void MakeIds(GLES2Implementation* gl_impl,
92 GLuint /* id_offset */,
93 GLsizei n,
94 GLuint* ids) override {
95 base::AutoLock auto_lock(lock_);
97 // Collect pending FreeIds from other flush_generation.
98 CollectPendingFreeIds(gl_impl);
100 for (GLsizei ii = 0; ii < n; ++ii) {
101 if (!free_ids_.empty()) {
102 // Allocate a previously freed Id.
103 ids[ii] = free_ids_.top();
104 free_ids_.pop();
106 // Record kIdInUse state.
107 DCHECK(id_states_[ids[ii] - 1] == kIdFree);
108 id_states_[ids[ii] - 1] = kIdInUse;
109 } else {
110 // Allocate a new Id.
111 id_states_.push_back(kIdInUse);
112 ids[ii] = id_states_.size();
117 // Overridden from IdHandler.
118 bool FreeIds(GLES2Implementation* gl_impl,
119 GLsizei n,
120 const GLuint* ids,
121 DeleteFn delete_fn) override {
122 // Delete stub must run before CollectPendingFreeIds.
123 (gl_impl->*delete_fn)(n, ids);
126 base::AutoLock auto_lock(lock_);
128 // Collect pending FreeIds from other flush_generation.
129 CollectPendingFreeIds(gl_impl);
131 // Save Ids to free in a later flush_generation.
132 ShareGroupContextData::IdHandlerData* ctxt_data =
133 gl_impl->share_group_context_data()->id_handler_data(id_namespace_);
135 for (GLsizei ii = 0; ii < n; ++ii) {
136 GLuint id = ids[ii];
137 if (id != 0) {
138 // Save freed Id for later.
139 DCHECK(id_states_[id - 1] == kIdInUse);
140 id_states_[id - 1] = kIdPendingFree;
141 ctxt_data->freed_ids_.push_back(id);
146 return true;
149 // Overridden from IdHandler.
150 bool MarkAsUsedForBind(GLuint id) override {
151 #ifndef NDEBUG
152 if (id != 0) {
153 base::AutoLock auto_lock(lock_);
154 DCHECK(id_states_[id - 1] == kIdInUse);
156 #endif
157 return true;
160 // Overridden from IdHandlerInterface.
161 void FreeContext(GLES2Implementation* gl_impl) override {
162 base::AutoLock auto_lock(lock_);
163 CollectPendingFreeIds(gl_impl);
166 private:
167 enum IdState { kIdFree, kIdPendingFree, kIdInUse };
169 void CollectPendingFreeIds(GLES2Implementation* gl_impl) {
170 uint32 flush_generation = gl_impl->helper()->flush_generation();
171 ShareGroupContextData::IdHandlerData* ctxt_data =
172 gl_impl->share_group_context_data()->id_handler_data(id_namespace_);
174 if (ctxt_data->flush_generation_ != flush_generation) {
175 ctxt_data->flush_generation_ = flush_generation;
176 for (uint32 ii = 0; ii < ctxt_data->freed_ids_.size(); ++ii) {
177 const GLuint id = ctxt_data->freed_ids_[ii];
178 DCHECK(id_states_[id - 1] == kIdPendingFree);
179 id_states_[id - 1] = kIdFree;
180 free_ids_.push(id);
182 ctxt_data->freed_ids_.clear();
186 int id_namespace_;
188 base::Lock lock_;
189 std::vector<uint8> id_states_;
190 std::stack<uint32> free_ids_;
193 // An id handler for ids that are never reused.
194 class NonReusedIdHandler : public IdHandlerInterface {
195 public:
196 NonReusedIdHandler() : last_id_(0) {}
197 ~NonReusedIdHandler() override {}
199 // Overridden from IdHandlerInterface.
200 void MakeIds(GLES2Implementation* /* gl_impl */,
201 GLuint id_offset,
202 GLsizei n,
203 GLuint* ids) override {
204 base::AutoLock auto_lock(lock_);
205 for (GLsizei ii = 0; ii < n; ++ii) {
206 ids[ii] = ++last_id_ + id_offset;
210 // Overridden from IdHandlerInterface.
211 bool FreeIds(GLES2Implementation* gl_impl,
212 GLsizei n,
213 const GLuint* ids,
214 DeleteFn delete_fn) override {
215 // Ids are never freed.
216 (gl_impl->*delete_fn)(n, ids);
217 return true;
220 // Overridden from IdHandlerInterface.
221 bool MarkAsUsedForBind(GLuint /* id */) override {
222 // This is only used for Shaders and Programs which have no bind.
223 return false;
226 void FreeContext(GLES2Implementation* gl_impl) override {}
228 private:
229 base::Lock lock_;
230 GLuint last_id_;
233 ShareGroup::ShareGroup(bool bind_generates_resource)
234 : bind_generates_resource_(bind_generates_resource) {
235 if (bind_generates_resource) {
236 for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
237 if (i == id_namespaces::kProgramsAndShaders) {
238 id_handlers_[i].reset(new NonReusedIdHandler());
239 } else {
240 id_handlers_[i].reset(new IdHandler());
243 } else {
244 for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
245 if (i == id_namespaces::kProgramsAndShaders) {
246 id_handlers_[i].reset(new NonReusedIdHandler());
247 } else {
248 id_handlers_[i].reset(new StrictIdHandler(i));
252 program_info_manager_.reset(ProgramInfoManager::Create(false));
255 void ShareGroup::set_program_info_manager(ProgramInfoManager* manager) {
256 program_info_manager_.reset(manager);
259 ShareGroup::~ShareGroup() {}
261 } // namespace gles2
262 } // namespace gpu