1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
gpu / command_buffer / service / gpu_fence_manager.cc [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/gpu_fence_manager.h"
#include <memory>
#include "base/check.h"
#include "base/functional/bind.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gl/gl_fence.h"
namespace gpu {
namespace gles2 {
GpuFenceManager::GpuFenceEntry::GpuFenceEntry() = default;
GpuFenceManager::GpuFenceEntry::~GpuFenceEntry() = default;
GpuFenceManager::GpuFenceManager() = default;
GpuFenceManager::~GpuFenceManager() {
DCHECK(gpu_fence_entries_.empty());
}
bool GpuFenceManager::CreateGpuFence(uint32_t client_id) {
// This must be a new entry.
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
if (it != gpu_fence_entries_.end())
return false;
auto entry = std::make_unique<GpuFenceEntry>();
entry->gl_fence_ = gl::GLFence::CreateForGpuFence();
if (!entry->gl_fence_)
return false;
std::pair<GpuFenceEntryMap::iterator, bool> result =
gpu_fence_entries_.emplace(client_id, std::move(entry));
DCHECK(result.second);
return true;
}
bool GpuFenceManager::CreateGpuFenceFromHandle(uint32_t client_id,
gfx::GpuFenceHandle handle) {
// The handle must be valid. The fallback kEmpty type cannot be duplicated.
if (handle.is_null())
return false;
// This must be a new entry.
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
if (it != gpu_fence_entries_.end())
return false;
auto entry = std::make_unique<GpuFenceEntry>();
entry->fence_handle_ = std::move(handle);
std::pair<GpuFenceEntryMap::iterator, bool> result =
gpu_fence_entries_.emplace(client_id, std::move(entry));
DCHECK(result.second);
return true;
}
bool GpuFenceManager::IsValidGpuFence(uint32_t client_id) {
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
return it != gpu_fence_entries_.end();
}
std::unique_ptr<gfx::GpuFence> GpuFenceManager::GetGpuFence(
uint32_t client_id) {
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
if (it == gpu_fence_entries_.end())
return nullptr;
GpuFenceEntry* entry = it->second.get();
DCHECK(entry->gl_fence_ || !entry->fence_handle_.is_null());
DCHECK(!entry->gl_fence_ || entry->fence_handle_.is_null());
if (!entry->fence_handle_.is_null())
return std::make_unique<gfx::GpuFence>(entry->fence_handle_.Clone());
return entry->gl_fence_->GetGpuFence();
}
bool GpuFenceManager::GpuFenceServerWait(uint32_t client_id) {
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
if (it == gpu_fence_entries_.end())
return false;
GpuFenceEntry* entry = it->second.get();
DCHECK(entry->gl_fence_ || !entry->fence_handle_.is_null());
DCHECK(!entry->gl_fence_ || entry->fence_handle_.is_null());
if (!entry->fence_handle_.is_null()) {
gfx::GpuFence gpu_fence(entry->fence_handle_.Clone());
auto gl_fence = gl::GLFence::CreateFromGpuFence(gpu_fence);
if (!gl_fence)
return false;
gl_fence->ServerWait();
return true;
}
entry->gl_fence_->ServerWait();
return true;
}
bool GpuFenceManager::RemoveGpuFence(uint32_t client_id) {
return gpu_fence_entries_.erase(client_id) == 1u;
}
void GpuFenceManager::Destroy(bool have_context) {
if (!have_context) {
// Invalidate fences on context loss. This is a no-op for EGL fences, but
// other platforms may want this.
for (auto& it : gpu_fence_entries_) {
it.second.get()->gl_fence_->Invalidate();
}
}
gpu_fence_entries_.clear();
}
} // namespace gles2
} // namespace gpu