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 #include "gpu/command_buffer/client/share_group.h"
6
7 #include "base/logging.h"
8 #include "base/synchronization/lock.h"
9 #include "gpu/command_buffer/client/gles2_implementation.h"
10 #include "gpu/command_buffer/client/program_info_manager.h"
11 #include "gpu/command_buffer/common/id_allocator.h"
12
13 namespace gpu {
14 namespace gles2 {
15
16 COMPILE_ASSERT(gpu::kInvalidResource == 0,
17 INVALID_RESOURCE_NOT_0_AS_GL_EXPECTS);
18
19 // The standard id handler.
20 class IdHandler : public IdHandlerInterface {
21 public:
IdHandler()22 IdHandler() { }
~IdHandler()23 virtual ~IdHandler() { }
24
25 // Overridden from IdHandlerInterface.
MakeIds(GLES2Implementation *,GLuint id_offset,GLsizei n,GLuint * ids)26 virtual void MakeIds(
27 GLES2Implementation* /* gl_impl */,
28 GLuint id_offset, GLsizei n, GLuint* ids) OVERRIDE {
29 if (id_offset == 0) {
30 for (GLsizei ii = 0; ii < n; ++ii) {
31 ids[ii] = id_allocator_.AllocateID();
32 }
33 } else {
34 for (GLsizei ii = 0; ii < n; ++ii) {
35 ids[ii] = id_allocator_.AllocateIDAtOrAbove(id_offset);
36 id_offset = ids[ii] + 1;
37 }
38 }
39 }
40
41 // Overridden from IdHandlerInterface.
FreeIds(GLES2Implementation * gl_impl,GLsizei n,const GLuint * ids,DeleteFn delete_fn)42 virtual bool FreeIds(
43 GLES2Implementation* gl_impl,
44 GLsizei n, const GLuint* ids, DeleteFn delete_fn) OVERRIDE {
45 for (GLsizei ii = 0; ii < n; ++ii) {
46 id_allocator_.FreeID(ids[ii]);
47 }
48 (gl_impl->*delete_fn)(n, ids);
49 // We need to ensure that the delete call is evaluated on the service side
50 // before any other contexts issue commands using these client ids.
51 gl_impl->helper()->CommandBufferHelper::Flush();
52 return true;
53 }
54
55 // Overridden from IdHandlerInterface.
MarkAsUsedForBind(GLuint id)56 virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE {
57 return id == 0 ? true : id_allocator_.MarkAsUsed(id);
58 }
59 protected:
60 IdAllocator id_allocator_;
61 };
62
63 // An id handler that require Gen before Bind.
64 class StrictIdHandler : public IdHandler {
65 public:
StrictIdHandler()66 StrictIdHandler() {}
~StrictIdHandler()67 virtual ~StrictIdHandler() {}
68
69 // Overridden from IdHandler.
MarkAsUsedForBind(GLuint id)70 virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE {
71 DCHECK(id == 0 || id_allocator_.InUse(id));
72 return IdHandler::MarkAsUsedForBind(id);
73 }
74 };
75
76 // An id handler for ids that are never reused.
77 class NonReusedIdHandler : public IdHandlerInterface {
78 public:
NonReusedIdHandler()79 NonReusedIdHandler() : last_id_(0) {}
~NonReusedIdHandler()80 virtual ~NonReusedIdHandler() {}
81
82 // Overridden from IdHandlerInterface.
MakeIds(GLES2Implementation *,GLuint id_offset,GLsizei n,GLuint * ids)83 virtual void MakeIds(
84 GLES2Implementation* /* gl_impl */,
85 GLuint id_offset, GLsizei n, GLuint* ids) OVERRIDE {
86 for (GLsizei ii = 0; ii < n; ++ii) {
87 ids[ii] = ++last_id_ + id_offset;
88 }
89 }
90
91 // Overridden from IdHandlerInterface.
FreeIds(GLES2Implementation * gl_impl,GLsizei n,const GLuint * ids,DeleteFn delete_fn)92 virtual bool FreeIds(
93 GLES2Implementation* gl_impl,
94 GLsizei n, const GLuint* ids, DeleteFn delete_fn) OVERRIDE {
95 // Ids are never freed.
96 (gl_impl->*delete_fn)(n, ids);
97 return true;
98 }
99
100 // Overridden from IdHandlerInterface.
MarkAsUsedForBind(GLuint)101 virtual bool MarkAsUsedForBind(GLuint /* id */) OVERRIDE {
102 // This is only used for Shaders and Programs which have no bind.
103 return false;
104 }
105
106 private:
107 GLuint last_id_;
108 };
109
110 // An id handler for shared ids.
111 class SharedIdHandler : public IdHandlerInterface {
112 public:
SharedIdHandler(id_namespaces::IdNamespaces id_namespace)113 SharedIdHandler(
114 id_namespaces::IdNamespaces id_namespace)
115 : id_namespace_(id_namespace) {
116 }
117
~SharedIdHandler()118 virtual ~SharedIdHandler() {}
119
MakeIds(GLES2Implementation * gl_impl,GLuint id_offset,GLsizei n,GLuint * ids)120 virtual void MakeIds(GLES2Implementation* gl_impl,
121 GLuint id_offset,
122 GLsizei n,
123 GLuint* ids) OVERRIDE {
124 gl_impl->GenSharedIdsCHROMIUM(id_namespace_, id_offset, n, ids);
125 }
126
FreeIds(GLES2Implementation * gl_impl,GLsizei n,const GLuint * ids,DeleteFn delete_fn)127 virtual bool FreeIds(GLES2Implementation* gl_impl,
128 GLsizei n,
129 const GLuint* ids,
130 DeleteFn delete_fn) OVERRIDE {
131 gl_impl->DeleteSharedIdsCHROMIUM(id_namespace_, n, ids);
132 (gl_impl->*delete_fn)(n, ids);
133 // We need to ensure that the delete call is evaluated on the service side
134 // before any other contexts issue commands using these client ids.
135 gl_impl->helper()->CommandBufferHelper::Flush();
136 return true;
137 }
138
MarkAsUsedForBind(GLuint id)139 virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE {
140 // This has no meaning for shared resources.
141 return true;
142 }
143
144 private:
145 id_namespaces::IdNamespaces id_namespace_;
146 };
147
148 class ThreadSafeIdHandlerWrapper : public IdHandlerInterface {
149 public:
ThreadSafeIdHandlerWrapper(IdHandlerInterface * id_handler)150 ThreadSafeIdHandlerWrapper(IdHandlerInterface* id_handler)
151 : id_handler_(id_handler) {
152 }
~ThreadSafeIdHandlerWrapper()153 virtual ~ThreadSafeIdHandlerWrapper() { }
154
155 // Overridden from IdHandlerInterface.
MakeIds(GLES2Implementation * gl_impl,GLuint id_offset,GLsizei n,GLuint * ids)156 virtual void MakeIds(GLES2Implementation* gl_impl,
157 GLuint id_offset,
158 GLsizei n,
159 GLuint* ids) OVERRIDE {
160 base::AutoLock auto_lock(lock_);
161 id_handler_->MakeIds(gl_impl, id_offset, n, ids);
162 }
163
164 // Overridden from IdHandlerInterface.
FreeIds(GLES2Implementation * gl_impl,GLsizei n,const GLuint * ids,DeleteFn delete_fn)165 virtual bool FreeIds(GLES2Implementation* gl_impl,
166 GLsizei n,
167 const GLuint* ids,
168 DeleteFn delete_fn) OVERRIDE {
169 base::AutoLock auto_lock(lock_);
170 return id_handler_->FreeIds(gl_impl, n, ids, delete_fn);
171 }
172
173 // Overridden from IdHandlerInterface.
MarkAsUsedForBind(GLuint id)174 virtual bool MarkAsUsedForBind(GLuint id) OVERRIDE {
175 base::AutoLock auto_lock(lock_);
176 return id_handler_->MarkAsUsedForBind(id);
177 }
178
179 private:
180 scoped_ptr<IdHandlerInterface> id_handler_;
181 base::Lock lock_;
182 };
183
ShareGroup(bool bind_generates_resource)184 ShareGroup::ShareGroup(bool bind_generates_resource)
185 : bind_generates_resource_(bind_generates_resource) {
186 if (bind_generates_resource) {
187 for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
188 if (i == id_namespaces::kProgramsAndShaders) {
189 id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
190 new NonReusedIdHandler()));
191 } else {
192 id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
193 new IdHandler()));
194 }
195 }
196 } else {
197 for (int i = 0; i < id_namespaces::kNumIdNamespaces; ++i) {
198 if (i == id_namespaces::kProgramsAndShaders) {
199 id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
200 new NonReusedIdHandler()));
201 } else {
202 id_handlers_[i].reset(new ThreadSafeIdHandlerWrapper(
203 new StrictIdHandler()));
204 }
205 }
206 }
207 program_info_manager_.reset(ProgramInfoManager::Create(false));
208 }
209
set_program_info_manager(ProgramInfoManager * manager)210 void ShareGroup::set_program_info_manager(ProgramInfoManager* manager) {
211 program_info_manager_.reset(manager);
212 }
213
~ShareGroup()214 ShareGroup::~ShareGroup() {}
215
216 } // namespace gles2
217 } // namespace gpu
218