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.
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"
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
{
29 ~IdHandler() override
{}
31 // Overridden from IdHandlerInterface.
32 void MakeIds(GLES2Implementation
* /* gl_impl */,
35 GLuint
* ids
) override
{
36 base::AutoLock
auto_lock(lock_
);
38 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
39 ids
[ii
] = id_allocator_
.AllocateID();
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
,
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();
67 // Overridden from IdHandlerInterface.
68 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
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
);
77 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
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
);
87 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
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
);
100 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
104 IdAllocator id_allocator_
;
107 // An id handler that requires Gen before Bind.
108 class StrictIdHandler
: public IdHandlerInterface
{
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 */,
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();
129 // Record kIdInUse state.
130 DCHECK(id_states_
[ids
[ii
] - 1] == kIdFree
);
131 id_states_
[ids
[ii
] - 1] = kIdInUse
;
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
,
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
) {
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
);
172 // Overridden from IdHandler.
173 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
176 BindFn bind_fn
) override
{
179 base::AutoLock
auto_lock(lock_
);
180 DCHECK(id_states_
[id
- 1] == kIdInUse
);
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
);
189 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
193 BindIndexedFn bind_fn
) override
{
196 base::AutoLock
auto_lock(lock_
);
197 DCHECK(id_states_
[id
- 1] == kIdInUse
);
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
);
206 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
212 BindIndexedRangeFn bind_fn
) override
{
215 base::AutoLock
auto_lock(lock_
);
216 DCHECK(id_states_
[id
- 1] == kIdInUse
);
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
);
226 // Overridden from IdHandlerInterface.
227 void FreeContext(GLES2Implementation
* gl_impl
) override
{
228 base::AutoLock
auto_lock(lock_
);
229 CollectPendingFreeIds(gl_impl
);
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
;
248 ctxt_data
->freed_ids_
.clear();
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
{
262 NonReusedIdHandler() : last_id_(0) {}
263 ~NonReusedIdHandler() override
{}
265 // Overridden from IdHandlerInterface.
266 void MakeIds(GLES2Implementation
* /* gl_impl */,
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
,
280 DeleteFn delete_fn
) override
{
281 // Ids are never freed.
282 (gl_impl
->*delete_fn
)(n
, ids
);
286 // Overridden from IdHandlerInterface.
287 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
290 BindFn
/* bind_fn */) override
{
291 // This is only used for Shaders and Programs which have no bind.
294 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
298 BindIndexedFn
/* bind_fn */) override
{
299 // This is only used for Shaders and Programs which have no bind.
302 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
306 GLintptr
/* offset */,
307 GLsizeiptr
/* size */,
308 BindIndexedRangeFn
/* bind_fn */) override
{
309 // This is only used for Shaders and Programs which have no bind.
313 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
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());
327 id_handlers_
[i
].reset(new IdHandler());
331 for (int i
= 0; i
< id_namespaces::kNumIdNamespaces
; ++i
) {
332 if (i
== id_namespaces::kProgramsAndShaders
) {
333 id_handlers_
[i
].reset(new NonReusedIdHandler());
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() {}