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 // TODO(vmiura): Can remove this by virtualizing internal ids, however
64 // this code only affects PPAPI for now.
65 gl_impl
->helper()->CommandBufferHelper::Flush();
69 // Overridden from IdHandlerInterface.
70 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
73 BindFn bind_fn
) override
{
74 base::AutoLock
auto_lock(lock_
);
75 bool result
= id
? id_allocator_
.MarkAsUsed(id
) : true;
76 (gl_impl
->*bind_fn
)(target
, id
);
79 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
83 BindIndexedFn bind_fn
) override
{
84 base::AutoLock
auto_lock(lock_
);
85 bool result
= id
? id_allocator_
.MarkAsUsed(id
) : true;
86 (gl_impl
->*bind_fn
)(target
, index
, id
);
89 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
95 BindIndexedRangeFn bind_fn
) override
{
96 base::AutoLock
auto_lock(lock_
);
97 bool result
= id
? id_allocator_
.MarkAsUsed(id
) : true;
98 (gl_impl
->*bind_fn
)(target
, index
, id
, offset
, size
);
102 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
106 IdAllocator id_allocator_
;
109 // An id handler that requires Gen before Bind.
110 class StrictIdHandler
: public IdHandlerInterface
{
112 explicit StrictIdHandler(int id_namespace
) : id_namespace_(id_namespace
) {}
113 ~StrictIdHandler() override
{}
115 // Overridden from IdHandler.
116 void MakeIds(GLES2Implementation
* gl_impl
,
117 GLuint
/* id_offset */,
119 GLuint
* ids
) override
{
120 base::AutoLock
auto_lock(lock_
);
122 // Collect pending FreeIds from other flush_generation.
123 CollectPendingFreeIds(gl_impl
);
125 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
126 if (!free_ids_
.empty()) {
127 // Allocate a previously freed Id.
128 ids
[ii
] = free_ids_
.top();
131 // Record kIdInUse state.
132 DCHECK(id_states_
[ids
[ii
] - 1] == kIdFree
);
133 id_states_
[ids
[ii
] - 1] = kIdInUse
;
135 // Allocate a new Id.
136 id_states_
.push_back(kIdInUse
);
137 ids
[ii
] = id_states_
.size();
142 // Overridden from IdHandler.
143 bool FreeIds(GLES2Implementation
* gl_impl
,
146 DeleteFn delete_fn
) override
{
147 // Delete stub must run before CollectPendingFreeIds.
148 (gl_impl
->*delete_fn
)(n
, ids
);
151 base::AutoLock
auto_lock(lock_
);
153 // Collect pending FreeIds from other flush_generation.
154 CollectPendingFreeIds(gl_impl
);
156 // Save Ids to free in a later flush_generation.
157 ShareGroupContextData::IdHandlerData
* ctxt_data
=
158 gl_impl
->share_group_context_data()->id_handler_data(id_namespace_
);
160 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
163 // Save freed Id for later.
164 DCHECK(id_states_
[id
- 1] == kIdInUse
);
165 id_states_
[id
- 1] = kIdPendingFree
;
166 ctxt_data
->freed_ids_
.push_back(id
);
174 // Overridden from IdHandler.
175 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
178 BindFn bind_fn
) override
{
181 base::AutoLock
auto_lock(lock_
);
182 DCHECK(id_states_
[id
- 1] == kIdInUse
);
185 // StrictIdHandler is used if |bind_generates_resource| is false. In that
186 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
187 // to call |bind_fn| without holding the lock.
188 (gl_impl
->*bind_fn
)(target
, id
);
191 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
195 BindIndexedFn bind_fn
) override
{
198 base::AutoLock
auto_lock(lock_
);
199 DCHECK(id_states_
[id
- 1] == kIdInUse
);
202 // StrictIdHandler is used if |bind_generates_resource| is false. In that
203 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
204 // to call |bind_fn| without holding the lock.
205 (gl_impl
->*bind_fn
)(target
, index
, id
);
208 bool MarkAsUsedForBind(GLES2Implementation
* gl_impl
,
214 BindIndexedRangeFn bind_fn
) override
{
217 base::AutoLock
auto_lock(lock_
);
218 DCHECK(id_states_
[id
- 1] == kIdInUse
);
221 // StrictIdHandler is used if |bind_generates_resource| is false. In that
222 // case, |bind_fn| will not use Flush() after helper->Bind*(), so it is OK
223 // to call |bind_fn| without holding the lock.
224 (gl_impl
->*bind_fn
)(target
, index
, id
, offset
, size
);
228 // Overridden from IdHandlerInterface.
229 void FreeContext(GLES2Implementation
* gl_impl
) override
{
230 base::AutoLock
auto_lock(lock_
);
231 CollectPendingFreeIds(gl_impl
);
235 enum IdState
{ kIdFree
, kIdPendingFree
, kIdInUse
};
237 void CollectPendingFreeIds(GLES2Implementation
* gl_impl
) {
238 uint32 flush_generation
= gl_impl
->helper()->flush_generation();
239 ShareGroupContextData::IdHandlerData
* ctxt_data
=
240 gl_impl
->share_group_context_data()->id_handler_data(id_namespace_
);
242 if (ctxt_data
->flush_generation_
!= flush_generation
) {
243 ctxt_data
->flush_generation_
= flush_generation
;
244 for (uint32 ii
= 0; ii
< ctxt_data
->freed_ids_
.size(); ++ii
) {
245 const GLuint id
= ctxt_data
->freed_ids_
[ii
];
246 DCHECK(id_states_
[id
- 1] == kIdPendingFree
);
247 id_states_
[id
- 1] = kIdFree
;
250 ctxt_data
->freed_ids_
.clear();
257 std::vector
<uint8
> id_states_
;
258 std::stack
<uint32
> free_ids_
;
261 // An id handler for ids that are never reused.
262 class NonReusedIdHandler
: public IdHandlerInterface
{
264 NonReusedIdHandler() : last_id_(0) {}
265 ~NonReusedIdHandler() override
{}
267 // Overridden from IdHandlerInterface.
268 void MakeIds(GLES2Implementation
* /* gl_impl */,
271 GLuint
* ids
) override
{
272 base::AutoLock
auto_lock(lock_
);
273 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
274 ids
[ii
] = ++last_id_
+ id_offset
;
278 // Overridden from IdHandlerInterface.
279 bool FreeIds(GLES2Implementation
* gl_impl
,
282 DeleteFn delete_fn
) override
{
283 // Ids are never freed.
284 (gl_impl
->*delete_fn
)(n
, ids
);
288 // Overridden from IdHandlerInterface.
289 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
292 BindFn
/* bind_fn */) override
{
293 // This is only used for Shaders and Programs which have no bind.
296 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
300 BindIndexedFn
/* bind_fn */) override
{
301 // This is only used for Shaders and Programs which have no bind.
304 bool MarkAsUsedForBind(GLES2Implementation
* /* gl_impl */,
308 GLintptr
/* offset */,
309 GLsizeiptr
/* size */,
310 BindIndexedRangeFn
/* bind_fn */) override
{
311 // This is only used for Shaders and Programs which have no bind.
315 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
322 ShareGroup::ShareGroup(bool bind_generates_resource
)
323 : bind_generates_resource_(bind_generates_resource
) {
324 if (bind_generates_resource
) {
325 for (int i
= 0; i
< id_namespaces::kNumIdNamespaces
; ++i
) {
326 if (i
== id_namespaces::kProgramsAndShaders
) {
327 id_handlers_
[i
].reset(new NonReusedIdHandler());
329 id_handlers_
[i
].reset(new IdHandler());
333 for (int i
= 0; i
< id_namespaces::kNumIdNamespaces
; ++i
) {
334 if (i
== id_namespaces::kProgramsAndShaders
) {
335 id_handlers_
[i
].reset(new NonReusedIdHandler());
337 id_handlers_
[i
].reset(new StrictIdHandler(i
));
341 program_info_manager_
.reset(new ProgramInfoManager
);
344 void ShareGroup::set_program_info_manager(ProgramInfoManager
* manager
) {
345 program_info_manager_
.reset(manager
);
348 ShareGroup::~ShareGroup() {}