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 virtual ~IdHandler() { }
31 // Overridden from IdHandlerInterface.
33 GLES2Implementation
* /* gl_impl */,
34 GLuint id_offset
, GLsizei n
, GLuint
* ids
) OVERRIDE
{
35 base::AutoLock
auto_lock(lock_
);
37 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
38 ids
[ii
] = id_allocator_
.AllocateID();
41 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
42 ids
[ii
] = id_allocator_
.AllocateIDAtOrAbove(id_offset
);
43 id_offset
= ids
[ii
] + 1;
48 // Overridden from IdHandlerInterface.
50 GLES2Implementation
* gl_impl
,
51 GLsizei n
, const GLuint
* ids
, DeleteFn delete_fn
) OVERRIDE
{
52 base::AutoLock
auto_lock(lock_
);
54 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
55 id_allocator_
.FreeID(ids
[ii
]);
58 (gl_impl
->*delete_fn
)(n
, ids
);
59 // We need to ensure that the delete call is evaluated on the service side
60 // before any other contexts issue commands using these client ids.
61 // TODO(vmiura): Can remove this by virtualizing internal ids, however
62 // this code only affects PPAPI for now.
63 gl_impl
->helper()->CommandBufferHelper::Flush();
67 // Overridden from IdHandlerInterface.
68 virtual bool MarkAsUsedForBind(GLuint id
) OVERRIDE
{
71 base::AutoLock
auto_lock(lock_
);
72 return id_allocator_
.MarkAsUsed(id
);
75 virtual void FreeContext(GLES2Implementation
* gl_impl
) OVERRIDE
{}
79 IdAllocator id_allocator_
;
82 // An id handler that requires Gen before Bind.
83 class StrictIdHandler
: public IdHandlerInterface
{
85 explicit StrictIdHandler(int id_namespace
) : id_namespace_(id_namespace
) {}
86 virtual ~StrictIdHandler() {}
88 // Overridden from IdHandler.
89 virtual void MakeIds(GLES2Implementation
* gl_impl
,
90 GLuint
/* id_offset */,
92 GLuint
* ids
) OVERRIDE
{
93 base::AutoLock
auto_lock(lock_
);
95 // Collect pending FreeIds from other flush_generation.
96 CollectPendingFreeIds(gl_impl
);
98 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
99 if (!free_ids_
.empty()) {
100 // Allocate a previously freed Id.
101 ids
[ii
] = free_ids_
.top();
104 // Record kIdInUse state.
105 DCHECK(id_states_
[ids
[ii
] - 1] == kIdFree
);
106 id_states_
[ids
[ii
] - 1] = kIdInUse
;
108 // Allocate a new Id.
109 id_states_
.push_back(kIdInUse
);
110 ids
[ii
] = id_states_
.size();
115 // Overridden from IdHandler.
116 virtual bool FreeIds(GLES2Implementation
* gl_impl
,
119 DeleteFn delete_fn
) OVERRIDE
{
121 // Delete stub must run before CollectPendingFreeIds.
122 (gl_impl
->*delete_fn
)(n
, ids
);
125 base::AutoLock
auto_lock(lock_
);
127 // Collect pending FreeIds from other flush_generation.
128 CollectPendingFreeIds(gl_impl
);
130 // Save Ids to free in a later flush_generation.
131 ShareGroupContextData::IdHandlerData
* ctxt_data
=
132 gl_impl
->share_group_context_data()->id_handler_data(id_namespace_
);
134 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
137 // Save freed Id for later.
138 DCHECK(id_states_
[id
- 1] == kIdInUse
);
139 id_states_
[id
- 1] = kIdPendingFree
;
140 ctxt_data
->freed_ids_
.push_back(id
);
148 // Overridden from IdHandler.
149 virtual bool MarkAsUsedForBind(GLuint id
) OVERRIDE
{
152 base::AutoLock
auto_lock(lock_
);
153 DCHECK(id_states_
[id
- 1] == kIdInUse
);
159 // Overridden from IdHandlerInterface.
160 virtual void FreeContext(GLES2Implementation
* gl_impl
) OVERRIDE
{
161 base::AutoLock
auto_lock(lock_
);
162 CollectPendingFreeIds(gl_impl
);
166 enum IdState
{ kIdFree
, kIdPendingFree
, kIdInUse
};
168 void CollectPendingFreeIds(GLES2Implementation
* gl_impl
) {
169 uint32 flush_generation
= gl_impl
->helper()->flush_generation();
170 ShareGroupContextData::IdHandlerData
* ctxt_data
=
171 gl_impl
->share_group_context_data()->id_handler_data(id_namespace_
);
173 if (ctxt_data
->flush_generation_
!= flush_generation
) {
174 ctxt_data
->flush_generation_
= flush_generation
;
175 for (uint32 ii
= 0; ii
< ctxt_data
->freed_ids_
.size(); ++ii
) {
176 const GLuint id
= ctxt_data
->freed_ids_
[ii
];
177 DCHECK(id_states_
[id
- 1] == kIdPendingFree
);
178 id_states_
[id
- 1] = kIdFree
;
181 ctxt_data
->freed_ids_
.clear();
188 std::vector
<uint8
> id_states_
;
189 std::stack
<uint32
> free_ids_
;
192 // An id handler for ids that are never reused.
193 class NonReusedIdHandler
: public IdHandlerInterface
{
195 NonReusedIdHandler() : last_id_(0) {}
196 virtual ~NonReusedIdHandler() {}
198 // Overridden from IdHandlerInterface.
199 virtual void MakeIds(
200 GLES2Implementation
* /* gl_impl */,
201 GLuint id_offset
, GLsizei n
, GLuint
* ids
) OVERRIDE
{
202 base::AutoLock
auto_lock(lock_
);
203 for (GLsizei ii
= 0; ii
< n
; ++ii
) {
204 ids
[ii
] = ++last_id_
+ id_offset
;
208 // Overridden from IdHandlerInterface.
209 virtual bool FreeIds(
210 GLES2Implementation
* gl_impl
,
211 GLsizei n
, const GLuint
* ids
, DeleteFn delete_fn
) OVERRIDE
{
212 // Ids are never freed.
213 (gl_impl
->*delete_fn
)(n
, ids
);
217 // Overridden from IdHandlerInterface.
218 virtual bool MarkAsUsedForBind(GLuint
/* id */) OVERRIDE
{
219 // This is only used for Shaders and Programs which have no bind.
223 virtual void FreeContext(GLES2Implementation
* gl_impl
) OVERRIDE
{}
230 ShareGroup::ShareGroup(bool bind_generates_resource
)
231 : bind_generates_resource_(bind_generates_resource
) {
232 if (bind_generates_resource
) {
233 for (int i
= 0; i
< id_namespaces::kNumIdNamespaces
; ++i
) {
234 if (i
== id_namespaces::kProgramsAndShaders
) {
235 id_handlers_
[i
].reset(new NonReusedIdHandler());
237 id_handlers_
[i
].reset(new IdHandler());
241 for (int i
= 0; i
< id_namespaces::kNumIdNamespaces
; ++i
) {
242 if (i
== id_namespaces::kProgramsAndShaders
) {
243 id_handlers_
[i
].reset(new NonReusedIdHandler());
245 id_handlers_
[i
].reset(new StrictIdHandler(i
));
249 program_info_manager_
.reset(ProgramInfoManager::Create(false));
252 void ShareGroup::set_program_info_manager(ProgramInfoManager
* manager
) {
253 program_info_manager_
.reset(manager
);
256 ShareGroup::~ShareGroup() {}