Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
device_buffer_gles.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter 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
6
7#include <cstring>
8#include <memory>
9
12
13namespace impeller {
14
16 std::shared_ptr<ReactorGLES> reactor,
17 std::unique_ptr<Allocation> backing_store)
18 : DeviceBuffer(desc),
19 reactor_(std::move(reactor)),
20 backing_store_(std::move(backing_store)) {}
21
22// |DeviceBuffer|
24 if (handle_.has_value() && !handle_->IsDead()) {
25 reactor_->CollectHandle(*handle_);
26 }
27}
28
29// |DeviceBuffer|
30uint8_t* DeviceBufferGLES::OnGetContents() const {
31 if (!reactor_) {
32 return nullptr;
33 }
34 return backing_store_->GetBuffer();
35}
36
37// |DeviceBuffer|
38bool DeviceBufferGLES::OnCopyHostBuffer(const uint8_t* source,
39 Range source_range,
40 size_t offset) {
41 if (!reactor_) {
42 return false;
43 }
44
45 if (offset + source_range.length >
46 backing_store_->GetLength().GetByteSize()) {
47 return false;
48 }
49
50 std::memmove(backing_store_->GetBuffer() + offset,
51 source + source_range.offset, source_range.length);
52 Flush(Range{offset, source_range.length});
53
54 return true;
55}
56
57std::optional<GLuint> DeviceBufferGLES::GetHandle() const {
58 if (handle_.has_value()) {
59 return reactor_->GetGLHandle(*handle_);
60 } else {
61 return std::nullopt;
62 }
63}
64
65void DeviceBufferGLES::Flush(std::optional<Range> range) const {
66 Lock lock(dirty_range_mutex_);
67 if (!range.has_value()) {
68 dirty_range_ = Range{
69 0, static_cast<size_t>(backing_store_->GetLength().GetByteSize())};
70 } else {
71 if (dirty_range_.has_value()) {
72 dirty_range_ = dirty_range_->Merge(range.value());
73 } else {
74 dirty_range_ = range.value();
75 }
76 }
77}
78
80 switch (type) {
82 return GL_ARRAY_BUFFER;
84 return GL_ELEMENT_ARRAY_BUFFER;
86 return GL_UNIFORM_BUFFER;
87 }
89}
90
92 if (!reactor_) {
93 return false;
94 }
95
96 if (!handle_.has_value()) {
97 handle_ = reactor_->CreateUntrackedHandle(HandleType::kBuffer);
98#ifdef IMPELLER_DEBUG
99 if (handle_.has_value() && label_.has_value()) {
100 reactor_->SetDebugLabel(*handle_, *label_);
101 }
102#endif
103 }
104
105 auto buffer = reactor_->GetGLHandle(*handle_);
106 if (!buffer.has_value()) {
107 return false;
108 }
109
110 const auto target_type = ToTarget(type);
111 const auto& gl = reactor_->GetProcTable();
112
113 gl.BindBuffer(target_type, buffer.value());
114 if (!initialized_) {
115 gl.BufferData(target_type, backing_store_->GetLength().GetByteSize(),
116 nullptr, GL_DYNAMIC_DRAW);
117 initialized_ = true;
118 }
119
120 // Take and clear the dirty range BEFORE uploading. A Flush() from another
121 // thread during the upload then merges into a fresh dirty range that the
122 // next bind uploads, instead of being silently discarded by a clear that
123 // runs after the upload.
124 std::optional<Range> dirty;
125 {
126 Lock lock(dirty_range_mutex_);
127 std::swap(dirty_range_, dirty);
128 }
129 if (dirty.has_value()) {
130 gl.BufferSubData(target_type, dirty->offset, dirty->length,
131 backing_store_->GetBuffer() + dirty->offset);
132 }
133
134 return true;
135}
136
137// |DeviceBuffer|
138bool DeviceBufferGLES::SetLabel(std::string_view label) {
139#ifdef IMPELLER_DEBUG
140 label_ = label;
141 if (handle_.has_value()) {
142 reactor_->SetDebugLabel(*handle_, label);
143 }
144#endif // IMPELLER_DEBUG
145 return true;
146}
147
148// |DeviceBuffer|
149bool DeviceBufferGLES::SetLabel(std::string_view label, Range range) {
150 // Cannot support debug label on the range. Set the label for the entire
151 // range.
152 return SetLabel(label);
153}
154
155const uint8_t* DeviceBufferGLES::GetBufferData() const {
156 return backing_store_->GetBuffer();
157}
158
160 const std::function<void(uint8_t* data, size_t length)>&
161 update_buffer_data) {
162 if (update_buffer_data) {
163 update_buffer_data(backing_store_->GetBuffer(),
164 backing_store_->GetLength().GetByteSize());
165 Flush(Range{
166 0, static_cast<size_t>(backing_store_->GetLength().GetByteSize())});
167 }
168}
169
170} // namespace impeller
void Flush(std::optional< Range > range=std::nullopt) const override
DeviceBufferGLES(DeviceBufferDescriptor desc, std::shared_ptr< ReactorGLES > reactor, std::unique_ptr< Allocation > backing_store)
void UpdateBufferData(const std::function< void(uint8_t *, size_t length)> &update_buffer_data)
bool BindAndUploadDataIfNecessary(BindingType type) const
const uint8_t * GetBufferData() const
std::optional< GLuint > GetHandle() const
#define FML_UNREACHABLE()
Definition logging.h:128
size_t length
static GLenum ToTarget(DeviceBufferGLES::BindingType type)
Definition ref_ptr.h:261
std::shared_ptr< ReactorGLES > reactor
impeller::ShaderType type
constexpr Range Merge(const Range &other)
Create a new range that is a union of this range and other.
Definition range.h:27