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 "gpu/command_buffer/client/share_group.h"
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "base/synchronization/lock.h"
12 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
13 #include "gpu/command_buffer/client/gles2_implementation.h"
14 #include "gpu/command_buffer/client/program_info_manager.h"
15 #include "gpu/command_buffer/common/id_allocator.h"
20 ShareGroupContextData::IdHandlerData::IdHandlerData() : flush_generation_(0) {}
21 ShareGroupContextData::IdHandlerData::~IdHandlerData() {}
23 static_assert(gpu::kInvalidResource
== 0,
24 "GL expects kInvalidResource to be 0");
26 // The standard id handler.
27 class IdHandler
: public IdHandlerInterface
{
30 ~IdHandler() override
{}
32 // Overridden from IdHandlerInterface.
33 void MakeIds(GLES2Implementation
* /* gl_impl */,
36 GLuint
* ids
) override
{
37 base::AutoLock
auto_lock(lock_
);
39 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
40 ids
[ii
] = id_allocator_
.AllocateID();
43 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
44 ids
[ii
] = id_allocator_
.AllocateIDAtOrAbove(id_offset
);
45 id_offset
= ids
[ii
] + 1;
50 // Overridden from IdHandlerInterface.
51 bool FreeIds(GLES2Implementation
* gl_impl
,
54 DeleteFn delete_fn
) override
{
55 base::AutoLock
auto_lock(lock_
);
57 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
58 id_allocator_
.FreeID(ids
[ii
]);
61 (gl_impl
->*delete_fn
)(n
, ids
);
62 // We need to ensure that the delete call is evaluated on the service side
63 // before any other contexts issue commands using these client ids.
64 gl_impl
->helper()->CommandBufferHelper::OrderingBarrier();
68 // Overridden from IdHandlerInterface.
69 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
72 BindFn bind_fn
) override
{
73 base::AutoLock
auto_lock(lock_
);
74 bool result
= id
? id_allocator_
.MarkAsUsed(id
) : true;
75 (gl_impl
->*bind_fn
)(target
, id
);
78 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
82 BindIndexedFn bind_fn
) override
{
83 base::AutoLock
auto_lock(lock_
);
84 bool result
= id
? id_allocator_
.MarkAsUsed(id
) : true;
85 (gl_impl
->*bind_fn
)(target
, index
, id
);
88 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
94 BindIndexedRangeFn bind_fn
) override
{
95 base::AutoLock
auto_lock(lock_
);
96 bool result
= id
? id_allocator_
.MarkAsUsed(id
) : true;
97 (gl_impl
->*bind_fn
)(target
, index
, id
, offset
, size
);
101 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
105 IdAllocator id_allocator_
;
108 // An id handler that requires Gen before Bind.
109 class StrictIdHandler
: public IdHandlerInterface
{
111 explicit StrictIdHandler(int id_namespace
) : id_namespace_(id_namespace
) {}
112 ~StrictIdHandler() override
{}
114 // Overridden from IdHandler.
115 void MakeIds(GLES2Implementation
* gl_impl
,
116 GLuint
/* id_offset */,
118 GLuint
* ids
) override
{
119 base::AutoLock
auto_lock(lock_
);
121 // Collect pending FreeIds from other flush_generation.
122 CollectPendingFreeIds(gl_impl
);
124 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
125 if (!free_ids_
.empty()) {
126 // Allocate a previously freed Id.
127 ids
[ii
] = free_ids_
.top();
130 // Record kIdInUse state.
131 DCHECK(id_states_
[ids
[ii
] - 1] == kIdFree
);
132 id_states_
[ids
[ii
] - 1] = kIdInUse
;
134 // Allocate a new Id.
135 id_states_
.push_back(kIdInUse
);
136 ids
[ii
] = id_states_
.size();
141 // Overridden from IdHandler.
142 bool FreeIds(GLES2Implementation
* gl_impl
,
145 DeleteFn delete_fn
) override
{
146 // Delete stub must run before CollectPendingFreeIds.
147 (gl_impl
->*delete_fn
)(n
, ids
);
150 base::AutoLock
auto_lock(lock_
);
152 // Collect pending FreeIds from other flush_generation.
153 CollectPendingFreeIds(gl_impl
);
155 // Save Ids to free in a later flush_generation.
156 ShareGroupContextData::IdHandlerData
* ctxt_data
=
157 gl_impl
->share_group_context_data()->id_handler_data(id_namespace_
);
159 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
162 // Save freed Id for later.
163 DCHECK(id_states_
[id
- 1] == kIdInUse
);
164 id_states_
[id
- 1] = kIdPendingFree
;
165 ctxt_data
->freed_ids_
.push_back(id
);
173 // Overridden from IdHandler.
174 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
177 BindFn bind_fn
) override
{
180 base::AutoLock
auto_lock(lock_
);
181 DCHECK(id_states_
[id
- 1] == kIdInUse
);
184 // StrictIdHandler is used if |bind_generates_resource| is false. In that
185 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
186 // to call |bind_fn| without holding the lock.
187 (gl_impl
->*bind_fn
)(target
, id
);
190 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
194 BindIndexedFn bind_fn
) override
{
197 base::AutoLock
auto_lock(lock_
);
198 DCHECK(id_states_
[id
- 1] == kIdInUse
);
201 // StrictIdHandler is used if |bind_generates_resource| is false. In that
202 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
203 // to call |bind_fn| without holding the lock.
204 (gl_impl
->*bind_fn
)(target
, index
, id
);
207 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
213 BindIndexedRangeFn bind_fn
) override
{
216 base::AutoLock
auto_lock(lock_
);
217 DCHECK(id_states_
[id
- 1] == kIdInUse
);
220 // StrictIdHandler is used if |bind_generates_resource| is false. In that
221 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
222 // to call |bind_fn| without holding the lock.
223 (gl_impl
->*bind_fn
)(target
, index
, id
, offset
, size
);
227 // Overridden from IdHandlerInterface.
228 void FreeContext(GLES2Implementation
* gl_impl
) override
{
229 base::AutoLock
auto_lock(lock_
);
230 CollectPendingFreeIds(gl_impl
);
234 enum IdState
{ kIdFree
, kIdPendingFree
, kIdInUse
};
236 void CollectPendingFreeIds(GLES2Implementation
* gl_impl
) {
237 uint32 flush_generation
= gl_impl
->helper()->flush_generation();
238 ShareGroupContextData::IdHandlerData
* ctxt_data
=
239 gl_impl
->share_group_context_data()->id_handler_data(id_namespace_
);
241 if (ctxt_data
->flush_generation_
!= flush_generation
) {
242 ctxt_data
->flush_generation_
= flush_generation
;
243 for (uint32 ii
= 0; ii
< ctxt_data
->freed_ids_
.size(); ++ii
) {
244 const GLuint id
= ctxt_data
->freed_ids_
[ii
];
245 DCHECK(id_states_
[id
- 1] == kIdPendingFree
);
246 id_states_
[id
- 1] = kIdFree
;
249 ctxt_data
->freed_ids_
.clear();
256 std::vector
<uint8
> id_states_
;
257 std::stack
<uint32
> free_ids_
;
260 // An id handler for ids that are never reused.
261 class NonReusedIdHandler
: public IdHandlerInterface
{
263 NonReusedIdHandler() : last_id_(0) {}
264 ~NonReusedIdHandler() override
{}
266 // Overridden from IdHandlerInterface.
267 void MakeIds(GLES2Implementation
* /* gl_impl */,
270 GLuint
* ids
) override
{
271 base::AutoLock
auto_lock(lock_
);
272 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
273 ids
[ii
] = ++last_id_
+ id_offset
;
277 // Overridden from IdHandlerInterface.
278 bool FreeIds(GLES2Implementation
* gl_impl
,
281 DeleteFn delete_fn
) override
{
282 // Ids are never freed.
283 (gl_impl
->*delete_fn
)(n
, ids
);
287 // Overridden from IdHandlerInterface.
288 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
291 BindFn
/* bind_fn */) override
{
292 // This is only used for Shaders and Programs which have no bind.
295 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
299 BindIndexedFn
/* bind_fn */) override
{
300 // This is only used for Shaders and Programs which have no bind.
303 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
307 GLintptr
/* offset */,
308 GLsizeiptr
/* size */,
309 BindIndexedRangeFn
/* bind_fn */) override
{
310 // This is only used for Shaders and Programs which have no bind.
314 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
321 class RangeIdHandler
: public RangeIdHandlerInterface
{
325 void MakeIdRange(GLES2Implementation
* /*gl_impl*/,
327 GLuint
* first_id
) override
{
328 base::AutoLock
auto_lock(lock_
);
329 *first_id
= id_allocator_
.AllocateIDRange(n
);
332 void FreeIdRange(GLES2Implementation
* gl_impl
,
333 const GLuint first_id
,
335 DeleteRangeFn delete_fn
) override
{
336 base::AutoLock
auto_lock(lock_
);
338 id_allocator_
.FreeIDRange(first_id
, range
);
339 (gl_impl
->*delete_fn
)(first_id
, range
);
340 gl_impl
->helper()->CommandBufferHelper::OrderingBarrier();
343 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
347 IdAllocator id_allocator_
;
350 ShareGroup::ShareGroup(bool bind_generates_resource
, uint64_t tracing_guid
)
351 : bind_generates_resource_(bind_generates_resource
),
352 tracing_guid_(tracing_guid
) {
353 if (bind_generates_resource
) {
354 for (int i
= 0; i
< id_namespaces::kNumIdNamespaces
; ++i
) {
355 if (i
== id_namespaces::kProgramsAndShaders
) {
356 id_handlers_
[i
].reset(new NonReusedIdHandler());
358 id_handlers_
[i
].reset(new IdHandler());
362 for (int i
= 0; i
< id_namespaces::kNumIdNamespaces
; ++i
) {
363 if (i
== id_namespaces::kProgramsAndShaders
) {
364 id_handlers_
[i
].reset(new NonReusedIdHandler());
366 id_handlers_
[i
].reset(new StrictIdHandler(i
));
370 program_info_manager_
.reset(new ProgramInfoManager
);
371 for (auto& range_id_handler
: range_id_handlers_
) {
372 range_id_handler
.reset(new RangeIdHandler());
376 void ShareGroup::set_program_info_manager(ProgramInfoManager
* manager
) {
377 program_info_manager_
.reset(manager
);
380 ShareGroup::~ShareGroup() {}