Flutter Engine
 
Loading...
Searching...
No Matches
fragment_shader.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
5#include <memory>
6#include <utility>
7
9
14
15namespace flutter {
16
18
19ReusableFragmentShader::ReusableFragmentShader(
21 uint64_t float_count,
22 uint64_t sampler_count)
23 : program_(std::move(program)),
24 uniform_data_(SkData::MakeUninitialized(
25 (float_count + 2 * sampler_count) * sizeof(float))),
26 samplers_(sampler_count),
27 float_count_(float_count) {}
28
29Dart_Handle ReusableFragmentShader::Create(Dart_Handle wrapper,
30 Dart_Handle program,
31 Dart_Handle float_count_handle,
32 Dart_Handle sampler_count_handle) {
33 auto* fragment_program =
35 uint64_t float_count =
37 uint64_t sampler_count =
38 tonic::DartConverter<uint64_t>::FromDart(sampler_count_handle);
39
40 auto res = fml::MakeRefCounted<ReusableFragmentShader>(
41 fml::Ref(fragment_program), float_count, sampler_count);
42 res->AssociateWithDartWrapper(wrapper);
43
44 void* raw_uniform_data =
45 reinterpret_cast<void*>(res->uniform_data_->writable_data());
46 return Dart_NewExternalTypedData(Dart_TypedData_kFloat32, raw_uniform_data,
47 float_count);
48}
49
50bool ReusableFragmentShader::ValidateSamplers() {
51 for (auto i = 0u; i < samplers_.size(); i++) {
52 if (samplers_[i] == nullptr) {
53 return false;
54 }
55 // The samplers should have been checked as they were added, this
56 // is a double-sanity-check.
57 FML_DCHECK(samplers_[i]->isUIThreadSafe());
58 }
59 return true;
60}
61
62void ReusableFragmentShader::SetImageSampler(Dart_Handle index_handle,
63 Dart_Handle image_handle) {
64 uint64_t index = tonic::DartConverter<uint64_t>::FromDart(index_handle);
67 if (index >= samplers_.size()) {
68 Dart_ThrowException(tonic::ToDart("Sampler index out of bounds"));
69 return;
70 }
71 if (!image || !image->image()) {
72 Dart_ThrowException(tonic::ToDart("Image has been disposed"));
73 return;
74 }
75 if (!image->image()->isUIThreadSafe()) {
76 Dart_ThrowException(tonic::ToDart("Image is not thread-safe"));
77 return;
78 }
79
80 // TODO(115794): Once the DlImageSampling enum is replaced, expose the
81 // sampling options as a new default parameter for users.
82 samplers_[index] = DlColorSource::MakeImage(
83 image->image(), DlTileMode::kClamp, DlTileMode::kClamp,
84 DlImageSampling::kNearestNeighbor, nullptr);
85 // This should be true since we already checked the image above, but
86 // we check again for sanity.
87 FML_DCHECK(samplers_[index]->isUIThreadSafe());
88
89 auto* uniform_floats =
90 reinterpret_cast<float*>(uniform_data_->writable_data());
91 uniform_floats[float_count_ + 2 * index] = image->width();
92 uniform_floats[float_count_ + 2 * index + 1] = image->height();
93}
94
95std::shared_ptr<DlImageFilter> ReusableFragmentShader::as_image_filter() const {
96 FML_CHECK(program_);
97
98 // The lifetime of this object is longer than a frame, and the uniforms can be
99 // continually changed on the UI thread. So we take a copy of the uniforms
100 // before handing it to the DisplayList for consumption on the render thread.
101 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
102 uniform_data->resize(uniform_data_->size());
103 memcpy(uniform_data->data(), uniform_data_->bytes(), uniform_data->size());
104
105 return program_->MakeDlImageFilter(std::move(uniform_data), samplers_);
106}
107
108std::shared_ptr<DlColorSource> ReusableFragmentShader::shader(
109 DlImageSampling sampling) {
110 FML_CHECK(program_);
111
112 // The lifetime of this object is longer than a frame, and the uniforms can be
113 // continually changed on the UI thread. So we take a copy of the uniforms
114 // before handing it to the DisplayList for consumption on the render thread.
115 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
116 uniform_data->resize(uniform_data_->size());
117 memcpy(uniform_data->data(), uniform_data_->bytes(), uniform_data->size());
118
119 auto source = program_->MakeDlColorSource(std::move(uniform_data), samplers_);
120 // The samplers should have been checked as they were added, this
121 // is a double-sanity-check.
122 FML_DCHECK(source->isUIThreadSafe());
123 return source;
124}
125
126// Image filters require at least one uniform sampler input to bind
127// the input texture.
128bool ReusableFragmentShader::ValidateImageFilter() {
129 if (samplers_.size() < 1) {
130 return false;
131 }
132 // The first sampler does not need to be set.
133 for (auto i = 1u; i < samplers_.size(); i++) {
134 if (samplers_[i] == nullptr) {
135 return false;
136 }
137 // The samplers should have been checked as they were added, this
138 // is a double-sanity-check.
139 FML_DCHECK(samplers_[i]->isUIThreadSafe());
140 }
141 return true;
142}
143
144void ReusableFragmentShader::Dispose() {
145 uniform_data_.reset();
146 program_ = nullptr;
147 samplers_.clear();
148 ClearDartWrapper();
149}
150
151ReusableFragmentShader::~ReusableFragmentShader() = default;
152
153} // namespace flutter
#define IMPLEMENT_WRAPPERTYPEINFO(LibraryName, ClassName)
FlutterVulkanImage * image
#define FML_CHECK(condition)
Definition logging.h:104
#define FML_DCHECK(condition)
Definition logging.h:122
RefPtr< T > Ref(T *ptr)
Definition ref_ptr.h:242
Definition ref_ptr.h:261
Dart_Handle ToDart(const T &object)
FlutterVulkanImageHandle image
Definition embedder.h:931