Don't add an aura tooltip to bubble close buttons on Windows.
[chromium-blink-merge.git] / gpu / command_buffer / service / mailbox_manager_sync.cc
blob4cdc80df64039e754e6fe5b0a299069ebdcdff97
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.
5 #include "gpu/command_buffer/service/mailbox_manager_sync.h"
7 #include <algorithm>
8 #include <queue>
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"
16 #if !defined(OS_MACOSX)
17 #include "ui/gl/gl_fence_egl.h"
18 #endif
20 namespace gpu {
21 namespace gles2 {
23 namespace {
25 base::LazyInstance<base::Lock> g_lock = LAZY_INSTANCE_INITIALIZER;
27 typedef std::map<uint32, linked_ptr<gfx::GLFence>> SyncPointToFenceMap;
28 base::LazyInstance<SyncPointToFenceMap> g_sync_point_to_fence =
29 LAZY_INSTANCE_INITIALIZER;
30 #if !defined(OS_MACOSX)
31 base::LazyInstance<std::queue<SyncPointToFenceMap::iterator>> g_sync_points =
32 LAZY_INSTANCE_INITIALIZER;
33 #endif
35 void CreateFenceLocked(uint32 sync_point) {
36 g_lock.Get().AssertAcquired();
37 if (gfx::GetGLImplementation() == gfx::kGLImplementationMockGL)
38 return;
40 #if !defined(OS_MACOSX)
41 std::queue<SyncPointToFenceMap::iterator>& sync_points = g_sync_points.Get();
42 SyncPointToFenceMap& sync_point_to_fence = g_sync_point_to_fence.Get();
43 if (sync_point) {
44 while (!sync_points.empty() &&
45 sync_points.front()->second->HasCompleted()) {
46 sync_point_to_fence.erase(sync_points.front());
47 sync_points.pop();
49 // Need to use EGL fences since we are likely not in a single share group.
50 linked_ptr<gfx::GLFence> fence(make_linked_ptr(new gfx::GLFenceEGL));
51 if (fence.get()) {
52 std::pair<SyncPointToFenceMap::iterator, bool> result =
53 sync_point_to_fence.insert(std::make_pair(sync_point, fence));
54 DCHECK(result.second);
55 sync_points.push(result.first);
57 DCHECK(sync_points.size() == sync_point_to_fence.size());
59 #endif
62 void AcquireFenceLocked(uint32 sync_point) {
63 g_lock.Get().AssertAcquired();
64 SyncPointToFenceMap::iterator fence_it =
65 g_sync_point_to_fence.Get().find(sync_point);
66 if (fence_it != g_sync_point_to_fence.Get().end()) {
67 fence_it->second->ServerWait();
71 static const unsigned kNewTextureVersion = 1;
73 } // anonymous namespace
75 base::LazyInstance<MailboxManagerSync::TextureGroup::MailboxToGroupMap>
76 MailboxManagerSync::TextureGroup::mailbox_to_group_ =
77 LAZY_INSTANCE_INITIALIZER;
79 // static
80 MailboxManagerSync::TextureGroup*
81 MailboxManagerSync::TextureGroup::CreateFromTexture(const Mailbox& name,
82 MailboxManagerSync* manager,
83 Texture* texture) {
84 TextureGroup* group = new TextureGroup();
85 group->AddTexture(manager, texture);
86 group->AddName(name);
87 if (!SkipTextureWorkarounds(texture)) {
88 group->definition_ =
89 TextureDefinition(texture, kNewTextureVersion, NULL);
91 return group;
94 // static
95 MailboxManagerSync::TextureGroup* MailboxManagerSync::TextureGroup::FromName(
96 const Mailbox& name) {
97 MailboxToGroupMap::iterator it = mailbox_to_group_.Get().find(name);
98 if (it == mailbox_to_group_.Get().end())
99 return NULL;
101 return it->second.get();
104 MailboxManagerSync::TextureGroup::TextureGroup() {
107 MailboxManagerSync::TextureGroup::~TextureGroup() {
110 void MailboxManagerSync::TextureGroup::AddName(const Mailbox& name) {
111 g_lock.Get().AssertAcquired();
112 DCHECK(std::find(names_.begin(), names_.end(), name) == names_.end());
113 names_.push_back(name);
114 DCHECK(mailbox_to_group_.Get().find(name) == mailbox_to_group_.Get().end());
115 mailbox_to_group_.Get()[name] = this;
118 void MailboxManagerSync::TextureGroup::RemoveName(const Mailbox& name) {
119 g_lock.Get().AssertAcquired();
120 std::vector<Mailbox>::iterator names_it =
121 std::find(names_.begin(), names_.end(), name);
122 DCHECK(names_it != names_.end());
123 names_.erase(names_it);
124 MailboxToGroupMap::iterator it = mailbox_to_group_.Get().find(name);
125 DCHECK(it != mailbox_to_group_.Get().end());
126 mailbox_to_group_.Get().erase(it);
129 void MailboxManagerSync::TextureGroup::AddTexture(MailboxManagerSync* manager,
130 Texture* texture) {
131 g_lock.Get().AssertAcquired();
132 DCHECK(std::find(textures_.begin(), textures_.end(),
133 std::make_pair(manager, texture)) == textures_.end());
134 textures_.push_back(std::make_pair(manager, texture));
137 bool MailboxManagerSync::TextureGroup::RemoveTexture(
138 MailboxManagerSync* manager,
139 Texture* texture) {
140 g_lock.Get().AssertAcquired();
141 TextureGroup::TextureList::iterator tex_list_it = std::find(
142 textures_.begin(), textures_.end(), std::make_pair(manager, texture));
143 DCHECK(tex_list_it != textures_.end());
144 if (textures_.size() == 1) {
145 // This is the last texture so the group is going away.
146 for (size_t n = 0; n < names_.size(); n++) {
147 const Mailbox& name = names_[n];
148 MailboxToGroupMap::iterator mbox_it =
149 mailbox_to_group_.Get().find(name);
150 DCHECK(mbox_it != mailbox_to_group_.Get().end());
151 DCHECK(mbox_it->second.get() == this);
152 mailbox_to_group_.Get().erase(mbox_it);
154 return false;
155 } else {
156 textures_.erase(tex_list_it);
157 return true;
161 Texture* MailboxManagerSync::TextureGroup::FindTexture(
162 MailboxManagerSync* manager) {
163 g_lock.Get().AssertAcquired();
164 for (TextureGroup::TextureList::iterator it = textures_.begin();
165 it != textures_.end(); it++) {
166 if (it->first == manager)
167 return it->second;
169 return NULL;
172 MailboxManagerSync::TextureGroupRef::TextureGroupRef(unsigned version,
173 TextureGroup* group)
174 : version(version), group(group) {
177 MailboxManagerSync::TextureGroupRef::~TextureGroupRef() {
180 MailboxManagerSync::MailboxManagerSync() {
183 MailboxManagerSync::~MailboxManagerSync() {
184 DCHECK_EQ(0U, texture_to_group_.size());
187 // static
188 bool MailboxManagerSync::SkipTextureWorkarounds(const Texture* texture) {
189 // Cannot support mips due to support mismatch between
190 // EGL_KHR_gl_texture_2D_image and glEGLImageTargetTexture2DOES for
191 // texture levels.
192 bool has_mips = texture->NeedsMips() && texture->texture_complete();
193 return texture->target() != GL_TEXTURE_2D || has_mips;
196 bool MailboxManagerSync::UsesSync() {
197 return true;
200 Texture* MailboxManagerSync::ConsumeTexture(const Mailbox& mailbox) {
201 base::AutoLock lock(g_lock.Get());
202 TextureGroup* group = TextureGroup::FromName(mailbox);
203 if (!group)
204 return NULL;
206 // Check if a texture already exists in this share group.
207 Texture* texture = group->FindTexture(this);
208 if (texture)
209 return texture;
211 // Otherwise create a new texture.
212 texture = group->GetDefinition().CreateTexture();
213 if (texture) {
214 DCHECK(!SkipTextureWorkarounds(texture));
215 texture->SetMailboxManager(this);
216 group->AddTexture(this, texture);
218 TextureGroupRef new_ref =
219 TextureGroupRef(group->GetDefinition().version(), group);
220 texture_to_group_.insert(std::make_pair(texture, new_ref));
223 return texture;
226 void MailboxManagerSync::ProduceTexture(const Mailbox& mailbox,
227 Texture* texture) {
228 base::AutoLock lock(g_lock.Get());
230 TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
231 TextureGroup* group_for_mailbox = TextureGroup::FromName(mailbox);
232 TextureGroup* group_for_texture = NULL;
234 if (tex_it != texture_to_group_.end()) {
235 group_for_texture = tex_it->second.group.get();
236 DCHECK(group_for_texture);
237 if (group_for_mailbox == group_for_texture) {
238 // The texture is already known under this name.
239 return;
243 if (group_for_mailbox) {
244 // Unlink the mailbox from its current group.
245 group_for_mailbox->RemoveName(mailbox);
248 if (group_for_texture) {
249 group_for_texture->AddName(mailbox);
250 } else {
251 // This is a new texture, so create a new group.
252 texture->SetMailboxManager(this);
253 group_for_texture =
254 TextureGroup::CreateFromTexture(mailbox, this, texture);
255 texture_to_group_.insert(std::make_pair(
256 texture, TextureGroupRef(kNewTextureVersion, group_for_texture)));
259 DCHECK(texture->mailbox_manager_ == this);
262 void MailboxManagerSync::TextureDeleted(Texture* texture) {
263 base::AutoLock lock(g_lock.Get());
264 TextureToGroupMap::iterator tex_it = texture_to_group_.find(texture);
265 DCHECK(tex_it != texture_to_group_.end());
266 TextureGroup* group_for_texture = tex_it->second.group.get();
267 if (group_for_texture->RemoveTexture(this, texture))
268 UpdateDefinitionLocked(texture, &tex_it->second);
269 texture_to_group_.erase(tex_it);
272 void MailboxManagerSync::UpdateDefinitionLocked(
273 Texture* texture,
274 TextureGroupRef* group_ref) {
275 g_lock.Get().AssertAcquired();
277 if (SkipTextureWorkarounds(texture))
278 return;
280 gfx::GLImage* gl_image = texture->GetLevelImage(texture->target(), 0);
281 TextureGroup* group = group_ref->group.get();
282 const TextureDefinition& definition = group->GetDefinition();
283 scoped_refptr<NativeImageBuffer> image_buffer = definition.image();
285 // Make sure we don't clobber with an older version
286 if (!definition.IsOlderThan(group_ref->version))
287 return;
289 // Also don't push redundant updates. Note that it would break the
290 // versioning.
291 if (definition.Matches(texture))
292 return;
294 DCHECK_IMPLIES(gl_image, image_buffer.get());
295 if (gl_image && !image_buffer->IsClient(gl_image)) {
296 LOG(ERROR) << "MailboxSync: Incompatible attachment";
297 return;
300 group->SetDefinition(TextureDefinition(texture, ++group_ref->version,
301 gl_image ? image_buffer : NULL));
304 void MailboxManagerSync::PushTextureUpdates(uint32 sync_point) {
305 base::AutoLock lock(g_lock.Get());
307 for (TextureToGroupMap::iterator it = texture_to_group_.begin();
308 it != texture_to_group_.end(); it++) {
309 UpdateDefinitionLocked(it->first, &it->second);
311 CreateFenceLocked(sync_point);
314 void MailboxManagerSync::PullTextureUpdates(uint32 sync_point) {
315 base::AutoLock lock(g_lock.Get());
316 AcquireFenceLocked(sync_point);
318 for (TextureToGroupMap::iterator it = texture_to_group_.begin();
319 it != texture_to_group_.end(); it++) {
320 const TextureDefinition& definition = it->second.group->GetDefinition();
321 Texture* texture = it->first;
322 unsigned& texture_version = it->second.version;
323 if (texture_version == definition.version() ||
324 definition.IsOlderThan(texture_version))
325 continue;
326 texture_version = definition.version();
327 definition.UpdateTexture(texture);
331 } // namespace gles2
332 } // namespace gpu