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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
gpu / command_buffer / client / client_font_manager.cc [blame]
// Copyright 2018 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/client/client_font_manager.h"
#include <bit>
#include <type_traits>
#include "base/bits.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/not_fatal_until.h"
namespace gpu {
namespace raster {
namespace {
class Serializer {
public:
Serializer(char* memory, uint32_t memory_size)
: memory_(memory), memory_size_(memory_size) {}
~Serializer() = default;
template <typename T>
void Write(const T* val) {
static_assert(std::is_trivially_copyable_v<T>);
WriteData(val, sizeof(T), alignof(T));
}
void WriteData(const void* input, uint32_t bytes, size_t alignment) {
AlignMemory(bytes, alignment);
if (bytes == 0)
return;
memcpy(memory_, input, bytes);
memory_ += bytes;
bytes_written_ += bytes;
}
private:
void AlignMemory(uint32_t size, size_t alignment) {
// Due to the math below, alignment must be a power of two.
DCHECK(std::has_single_bit(alignment));
size_t memory = reinterpret_cast<size_t>(memory_.get());
size_t padding = base::bits::AlignUp(memory, alignment) - memory;
DCHECK_LE(bytes_written_ + size + padding, memory_size_);
memory_ += padding;
bytes_written_ += padding;
}
raw_ptr<char, AllowPtrArithmetic> memory_ = nullptr;
uint32_t memory_size_ = 0u;
uint32_t bytes_written_ = 0u;
};
} // namespace
ClientFontManager::ClientFontManager(Client* client,
CommandBuffer* command_buffer)
: client_(client), command_buffer_(command_buffer), strike_server_(this) {}
ClientFontManager::~ClientFontManager() = default;
SkDiscardableHandleId ClientFontManager::createHandle() {
auto client_handle =
client_discardable_manager_.CreateHandle(command_buffer_);
if (client_handle.is_null())
return kInvalidSkDiscardableHandleId;
SkDiscardableHandleId handle_id = ++last_allocated_handle_id_;
discardable_handle_map_[handle_id] = client_handle;
// Handles start with a ref-count.
locked_handles_.insert(handle_id);
return handle_id;
}
bool ClientFontManager::lockHandle(SkDiscardableHandleId handle_id) {
// Already locked.
if (locked_handles_.find(handle_id) != locked_handles_.end())
return true;
auto it = discardable_handle_map_.find(handle_id);
if (it == discardable_handle_map_.end())
return false;
bool locked = client_discardable_manager_.LockHandle(it->second);
if (locked) {
locked_handles_.insert(handle_id);
return true;
}
discardable_handle_map_.erase(it);
return false;
}
bool ClientFontManager::isHandleDeleted(SkDiscardableHandleId handle_id) {
auto it = discardable_handle_map_.find(handle_id);
if (it == discardable_handle_map_.end())
return true;
if (client_discardable_manager_.HandleIsDeleted(it->second)) {
discardable_handle_map_.erase(it);
return true;
}
return false;
}
void ClientFontManager::Serialize() {
// TODO(khushalsagar): May be skia can track the size required so we avoid
// this copy.
std::vector<uint8_t> strike_data;
strike_server_.writeStrikeData(&strike_data);
const uint32_t num_handles_created =
last_allocated_handle_id_ - last_serialized_handle_id_;
if (strike_data.size() == 0u && num_handles_created == 0u &&
locked_handles_.size() == 0u) {
// No font data to serialize.
return;
}
// Size required for serialization.
base::CheckedNumeric<uint32_t> checked_bytes_required = 0;
// Skia data size.
checked_bytes_required += sizeof(uint32_t) + alignof(uint32_t) + 16;
checked_bytes_required += strike_data.size();
// num of handles created + SerializableHandles.
checked_bytes_required +=
sizeof(uint32_t) + alignof(uint32_t) + alignof(SerializableSkiaHandle);
checked_bytes_required +=
base::CheckMul(num_handles_created, sizeof(SerializableSkiaHandle));
// num of handles locked + DiscardableHandleIds.
checked_bytes_required +=
sizeof(uint32_t) + alignof(uint32_t) + alignof(SkDiscardableHandleId);
checked_bytes_required +=
base::CheckMul(locked_handles_.size(), sizeof(SkDiscardableHandleId));
uint32_t bytes_required = 0;
if (!checked_bytes_required.AssignIfValid(&bytes_required)) {
DLOG(FATAL) << "ClientFontManager::Serialize: font buffer overflow";
return;
}
// Allocate memory.
void* memory = client_->MapFontBuffer(bytes_required);
if (!memory) {
// We are likely in a context loss situation if mapped memory allocation
// for font buffer failed.
return;
}
Serializer serializer(reinterpret_cast<char*>(memory), bytes_required);
// Serialize all new handles.
serializer.Write<uint32_t>(&num_handles_created);
for (SkDiscardableHandleId handle_id = last_serialized_handle_id_ + 1;
handle_id <= last_allocated_handle_id_; handle_id++) {
auto it = discardable_handle_map_.find(handle_id);
CHECK(it != discardable_handle_map_.end(), base::NotFatalUntil::M130);
// We must have a valid |client_handle| here since all new handles are
// currently in locked state.
auto client_handle = client_discardable_manager_.GetHandle(it->second);
DCHECK(client_handle.IsValid());
SerializableSkiaHandle handle(handle_id, client_handle.shm_id(),
client_handle.byte_offset());
serializer.Write<SerializableSkiaHandle>(&handle);
}
// Serialize all locked handle ids, so the raster unlocks them when done.
DCHECK(base::IsValueInRangeForNumericType<uint32_t>(locked_handles_.size()));
const uint32_t num_locked_handles = locked_handles_.size();
serializer.Write<uint32_t>(&num_locked_handles);
for (auto handle_id : locked_handles_)
serializer.Write<SkDiscardableHandleId>(&handle_id);
// Serialize skia data.
DCHECK(base::IsValueInRangeForNumericType<uint32_t>(strike_data.size()));
const uint32_t skia_data_size = strike_data.size();
serializer.Write<uint32_t>(&skia_data_size);
serializer.WriteData(strike_data.data(), strike_data.size(), 16);
// Reset all state for what has been serialized.
last_serialized_handle_id_ = last_allocated_handle_id_;
locked_handles_.clear();
return;
}
} // namespace raster
} // namespace gpu