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 COMPILE_ASSERT(gpu::kInvalidResource
== 0,
23 INVALID_RESOURCE_NOT_0_AS_GL_EXPECTS
);
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(GLuint id
) override
{
73 base::AutoLock
auto_lock(lock_
);
74 return id_allocator_
.MarkAsUsed(id
);
77 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
81 IdAllocator id_allocator_
;
84 // An id handler that requires Gen before Bind.
85 class StrictIdHandler
: public IdHandlerInterface
{
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 */,
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();
106 // Record kIdInUse state.
107 DCHECK(id_states_
[ids
[ii
] - 1] == kIdFree
);
108 id_states_
[ids
[ii
] - 1] = kIdInUse
;
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
,
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
) {
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
);
149 // Overridden from IdHandler.
150 bool MarkAsUsedForBind(GLuint id
) override
{
153 base::AutoLock
auto_lock(lock_
);
154 DCHECK(id_states_
[id
- 1] == kIdInUse
);
160 // Overridden from IdHandlerInterface.
161 void FreeContext(GLES2Implementation
* gl_impl
) override
{
162 base::AutoLock
auto_lock(lock_
);
163 CollectPendingFreeIds(gl_impl
);
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
;
182 ctxt_data
->freed_ids_
.clear();
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
{
196 NonReusedIdHandler() : last_id_(0) {}
197 ~NonReusedIdHandler() override
{}
199 // Overridden from IdHandlerInterface.
200 void MakeIds(GLES2Implementation
* /* gl_impl */,
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
,
214 DeleteFn delete_fn
) override
{
215 // Ids are never freed.
216 (gl_impl
->*delete_fn
)(n
, ids
);
220 // Overridden from IdHandlerInterface.
221 bool MarkAsUsedForBind(GLuint
/* id */) override
{
222 // This is only used for Shaders and Programs which have no bind.
226 void FreeContext(GLES2Implementation
* gl_impl
) override
{}
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());
240 id_handlers_
[i
].reset(new IdHandler());
244 for (int i
= 0; i
< id_namespaces::kNumIdNamespaces
; ++i
) {
245 if (i
== id_namespaces::kProgramsAndShaders
) {
246 id_handlers_
[i
].reset(new NonReusedIdHandler());
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() {}