Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: gpu/command_buffer/service/mailbox_manager_sync.cc

Issue 681713002: Update from chromium https://crrev.com/301315 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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.
4
5 #include "gpu/command_buffer/service/mailbox_manager_sync.h"
6
7 #include <algorithm>
8 #include <queue>
9
10 #include "base/memory/linked_ptr.h"
11 #include "base/synchronization/lock.h"
12 #include "gpu/command_buffer/service/texture_manager.h"
13 #include "ui/gl/gl_fence.h"
14 #include "ui/gl/gl_implementation.h"
15
16 #if !defined(OS_MACOSX)
17 #include "ui/gl/gl_fence_egl.h"
18 #endif
19
20 namespace gpu {
21 namespace gles2 {
22
23 namespace {
24
25 bool SkipTextureWorkarounds(const Texture* texture) {
26 // TODO(sievers): crbug.com/352274
27 // Should probably only fail if it already *has* mipmaps, while allowing
28 // incomplete textures here.
29 bool needs_mips =
30 texture->min_filter() != GL_NEAREST && texture->min_filter() != GL_LINEAR;
31 if (texture->target() != GL_TEXTURE_2D || needs_mips || !texture->IsDefined())
32 return true;
33
34 // Skip compositor resources/tile textures.
35 // TODO: Remove this, see crbug.com/399226.
36 if (texture->pool() == GL_TEXTURE_POOL_MANAGED_CHROMIUM)
37 return true;
38
39 return false;
40 }
41
42 base::LazyInstance<base::Lock> g_lock = LAZY_INSTANCE_INITIALIZER;
43
44 typedef std::map<uint32, linked_ptr<gfx::GLFence>> SyncPointToFenceMap;
45 base::LazyInstance<SyncPointToFenceMap> g_sync_point_to_fence =
46 LAZY_INSTANCE_INITIALIZER;
47 #if !defined(OS_MACOSX)
48 base::LazyInstance<std::queue<SyncPointToFenceMap::iterator>> g_sync_points =
49 LAZY_INSTANCE_INITIALIZER;
50 #endif
51
52 void CreateFenceLocked(uint32 sync_point) {
53 g_lock.Get().AssertAcquired();
54 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL)
55 return;
56
57 #if !defined(OS_MACOSX)
58 std::queue<SyncPointToFenceMap::iterator>& sync_points = g_sync_points.Get();
59 SyncPointToFenceMap& sync_point_to_fence = g_sync_point_to_fence.Get();
60 if (sync_point) {
61 while (!sync_points.empty() &&
62 sync_points.front()->second->HasCompleted()) {
63 sync_point_to_fence.erase(sync_points.front());
64 sync_points.pop();
65 }
66 // Need to use EGL fences since we are likely not in a single share group.
67 linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL(true)));
68 if (fence.get()) {
69 std::pair<SyncPointToFenceMap::iterator, bool> result =
70 sync_point_to_fence.insert(std::make_pair(sync_point, fence));
71 DCHECK(result.second);
72 sync_points.push(result.first);
73 }
74 DCHECK(sync_points.size() == sync_point_to_fence.size());
75 }
76 #endif
77 }
78
79 void AcquireFenceLocked(uint32 sync_point) {
80 g_lock.Get().AssertAcquired();
81 SyncPointToFenceMap::iterator fence_it =
82 g_sync_point_to_fence.Get().find(sync_point);
83 if (fence_it != g_sync_point_to_fence.Get().end()) {
84 fence_it->second->ServerWait();
85 }
86 }
87
88 static const unsigned kNewTextureVersion = 1;
89
90 } // anonymous namespace
91
92 base::LazyInstance<MailboxManagerSync::TextureGroup::MailboxToGroupMap>
93 MailboxManagerSync::TextureGroup::mailbox_to_group_ =
94 LAZY_INSTANCE_INITIALIZER;
95
96 // static
97 MailboxManagerSync::TextureGroup*
98 MailboxManagerSync::TextureGroup::CreateFromTexture(const Mailbox& name,
99 MailboxManagerSync* manager,
100 Texture* texture) {
101 TextureGroup* group = new TextureGroup();
102 group->AddTexture(manager, texture);
103 group->AddName(name);
104 if (!SkipTextureWorkarounds(texture)) {
105 group->definition_ =
106 TextureDefinition(texture, kNewTextureVersion, NULL);
107 }
108 return group;
109 }
110
111 // static
112 MailboxManagerSync::TextureGroup* MailboxManagerSync::TextureGroup::FromName(
113 const Mailbox& name) {
114 MailboxToGroupMap::iterator it = mailbox_to_group_.Get().find(name);
115 if (it == mailbox_to_group_.Get().end())
116 return NULL;
117
118 return it->second.get();
119 }
120
121 MailboxManagerSync::TextureGroup::TextureGroup() {
122 }
123
124 MailboxManagerSync::TextureGroup::~TextureGroup() {
125 }
126
127 void MailboxManagerSync::TextureGroup::AddName(const Mailbox& name) {
128 g_lock.Get().AssertAcquired();
129 DCHECK(std::find(names_.begin(), names_.end(), name) == names_.end());
130 names_.push_back(name);
131 DCHECK(mailbox_to_group_.Get().find(name) == mailbox_to_group_.Get().end());
132 mailbox_to_group_.Get()[name] = this;
133 }
134
135 void MailboxManagerSync::TextureGroup::RemoveName(const Mailbox& name) {
136 g_lock.Get().AssertAcquired();
137 std::vector<Mailbox>::iterator names_it =
138 std::find(names_.begin(), names_.end(), name);
139 DCHECK(names_it != names_.end());
140 names_.erase(names_it);
141 MailboxToGroupMap::iterator it = mailbox_to_group_.Get().find(name);
142 DCHECK(it != mailbox_to_group_.Get().end());
143 mailbox_to_group_.Get().erase(it);
144 }
145
146 void MailboxManagerSync::TextureGroup::AddTexture(MailboxManagerSync* manager,
147 Texture* texture) {
148 g_lock.Get().AssertAcquired();
149 DCHECK(std::find(textures_.begin(), textures_.end(),
150 std::make_pair(manager, texture)) == textures_.end());
151 textures_.push_back(std::make_pair(manager, texture));
152 }
153
154 bool MailboxManagerSync::TextureGroup::RemoveTexture(
155 MailboxManagerSync* manager,
156 Texture* texture) {
157 g_lock.Get().AssertAcquired();
158 TextureGroup::TextureList::iterator tex_list_it = std::find(
159 textures_.begin(), textures_.end(), std::make_pair(manager, texture));
160 DCHECK(tex_list_it != textures_.end());
161 if (textures_.size() == 1) {
162 // This is the last texture so the group is going away.
163 for (size_t n = 0; n < names_.size(); n++) {
164 const Mailbox& name = names_[n];
165 MailboxToGroupMap::iterator mbox_it =
166 mailbox_to_group_.Get().find(name);
167 DCHECK(mbox_it != mailbox_to_group_.Get().end());
168 DCHECK(mbox_it->second.get() == this);
169 mailbox_to_group_.Get().erase(mbox_it);
170 }
171 return false;
172 } else {
173 textures_.erase(tex_list_it);
174 return true;
175 }
176 }
177
178 Texture* MailboxManagerSync::TextureGroup::FindTexture(
179 MailboxManagerSync* manager) {
180 g_lock.Get().AssertAcquired();
181 for (TextureGroup::TextureList::iterator it = textures_.begin();
182 it != textures_.end(); it++) {
183 if (it->first == manager)
184 return it->second;
185 }
186 return NULL;
187 }
188
189 MailboxManagerSync::TextureGroupRef::TextureGroupRef(unsigned version,
190 TextureGroup* group)
191 : version(version), group(group) {
192 }
193
194 MailboxManagerSync::TextureGroupRef::~TextureGroupRef() {
195 }
196
197 MailboxManagerSync::MailboxManagerSync() {
198 }
199
200 MailboxManagerSync::~MailboxManagerSync() {
201 DCHECK_EQ(0U, texture_to_group_.size());
202 }
203
204 bool MailboxManagerSync::UsesSync() {
205 return true;
206 }
207
208 Texture* MailboxManagerSync::ConsumeTexture(const Mailbox& mailbox) {
209 base::AutoLock lock(g_lock.Get());
210 TextureGroup* group = TextureGroup::FromName(mailbox);
211 if (!group)
212 return NULL;
213
214 // Check if a texture already exists in this share group.
215 Texture* texture = group->FindTexture(this);
216 if (texture)
217 return texture;
218
219 // Otherwise create a new texture.
220 texture = group->GetDefinition().CreateTexture();
221 if (texture) {
222 DCHECK(!SkipTextureWorkarounds(texture));
223 texture->SetMailboxManager(this);
224 group->AddTexture(this, texture);
225
226 TextureGroupRef new_ref =
227 TextureGroupRef(group->GetDefinition().version(), group);
228 texture_to_group_.insert(std::make_pair(texture, new_ref));
229 }
230
231 return texture;
232 }
233
234 void MailboxManagerSync::ProduceTexture(const Mailbox& mailbox,
235 Texture* texture) {
236 base::AutoLock lock(g_lock.Get());
237
238 TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
239 TextureGroup* group_for_mailbox = TextureGroup::FromName(mailbox);
240 TextureGroup* group_for_texture = NULL;
241
242 if (tex_it != texture_to_group_.end()) {
243 group_for_texture = tex_it->second.group.get();
244 DCHECK(group_for_texture);
245 if (group_for_mailbox == group_for_texture) {
246 // The texture is already known under this name.
247 return;
248 }
249 }
250
251 if (group_for_mailbox) {
252 // Unlink the mailbox from its current group.
253 group_for_mailbox->RemoveName(mailbox);
254 }
255
256 if (group_for_texture) {
257 group_for_texture->AddName(mailbox);
258 } else {
259 // This is a new texture, so create a new group.
260 texture->SetMailboxManager(this);
261 group_for_texture =
262 TextureGroup::CreateFromTexture(mailbox, this, texture);
263 texture_to_group_.insert(std::make_pair(
264 texture, TextureGroupRef(kNewTextureVersion, group_for_texture)));
265 }
266
267 DCHECK(texture->mailbox_manager_ == this);
268 }
269
270 void MailboxManagerSync::TextureDeleted(Texture* texture) {
271 base::AutoLock lock(g_lock.Get());
272 TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
273 DCHECK(tex_it != texture_to_group_.end());
274 TextureGroup* group_for_texture = tex_it->second.group.get();
275 if (group_for_texture->RemoveTexture(this, texture))
276 UpdateDefinitionLocked(texture, &tex_it->second);
277 texture_to_group_.erase(tex_it);
278 }
279
280 void MailboxManagerSync::UpdateDefinitionLocked(
281 Texture* texture,
282 TextureGroupRef* group_ref) {
283 g_lock.Get().AssertAcquired();
284
285 if (SkipTextureWorkarounds(texture))
286 return;
287
288 gfx::GLImage* gl_image = texture->GetLevelImage(texture->target(), 0);
289 TextureGroup* group = group_ref->group.get();
290 const TextureDefinition& definition = group->GetDefinition();
291 scoped_refptr<NativeImageBuffer> image_buffer = definition.image();
292
293 // Make sure we don't clobber with an older version
294 if (!definition.IsOlderThan(group_ref->version))
295 return;
296
297 // Also don't push redundant updates. Note that it would break the
298 // versioning.
299 if (definition.Matches(texture))
300 return;
301
302 if (gl_image && !image_buffer->IsClient(gl_image)) {
303 LOG(ERROR) << "MailboxSync: Incompatible attachment";
304 return;
305 }
306
307 group->SetDefinition(TextureDefinition(texture, ++group_ref->version,
308 gl_image ? image_buffer : NULL));
309 }
310
311 void MailboxManagerSync::PushTextureUpdates(uint32 sync_point) {
312 base::AutoLock lock(g_lock.Get());
313
314 for (TextureToGroupMap::iterator it = texture_to_group_.begin();
315 it != texture_to_group_.end(); it++) {
316 UpdateDefinitionLocked(it->first, &it->second);
317 }
318 CreateFenceLocked(sync_point);
319 }
320
321 void MailboxManagerSync::PullTextureUpdates(uint32 sync_point) {
322 base::AutoLock lock(g_lock.Get());
323 AcquireFenceLocked(sync_point);
324
325 for (TextureToGroupMap::iterator it = texture_to_group_.begin();
326 it != texture_to_group_.end(); it++) {
327 const TextureDefinition& definition = it->second.group->GetDefinition();
328 Texture* texture = it->first;
329 unsigned& texture_version = it->second.version;
330 if (texture_version == definition.version() ||
331 definition.IsOlderThan(texture_version))
332 continue;
333 texture_version = definition.version();
334 definition.UpdateTexture(texture);
335 }
336 }
337
338 } // namespace gles2
339 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/mailbox_manager_sync.h ('k') | gpu/command_buffer/service/mailbox_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698