Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | Private Member Functions | List of all members
impeller::ExperimentalCanvas Class Reference

#include <experimental_canvas.h>

Inheritance diagram for impeller::ExperimentalCanvas:
impeller::Canvas

Classes

struct  SaveLayerState
 

Public Member Functions

 ExperimentalCanvas (ContentContext &renderer, RenderTarget &render_target)
 
 ExperimentalCanvas (ContentContext &renderer, RenderTarget &render_target, Rect cull_rect)
 
 ExperimentalCanvas (ContentContext &renderer, RenderTarget &render_target, IRect cull_rect)
 
 ~ExperimentalCanvas () override=default
 
void Save (uint32_t total_content_depth) override
 
void SaveLayer (const Paint &paint, std::optional< Rect > bounds, const std::shared_ptr< ImageFilter > &backdrop_filter, ContentBoundsPromise bounds_promise, uint32_t total_content_depth) override
 
bool Restore () override
 
void EndReplay ()
 
void DrawTextFrame (const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint) override
 
- Public Member Functions inherited from impeller::Canvas
 Canvas ()
 
 Canvas (Rect cull_rect)
 
 Canvas (IRect cull_rect)
 
virtual ~Canvas ()
 
size_t GetSaveCount () const
 
void RestoreToCount (size_t count)
 
const MatrixGetCurrentTransform () const
 
const std::optional< RectGetCurrentLocalCullingBounds () const
 
void ResetTransform ()
 
void Transform (const Matrix &transform)
 
void Concat (const Matrix &transform)
 
void PreConcat (const Matrix &transform)
 
void Translate (const Vector3 &offset)
 
void Scale (const Vector2 &scale)
 
void Scale (const Vector3 &scale)
 
void Skew (Scalar sx, Scalar sy)
 
void Rotate (Radians radians)
 
void DrawPath (const Path &path, const Paint &paint)
 
void DrawPaint (const Paint &paint)
 
void DrawLine (const Point &p0, const Point &p1, const Paint &paint)
 
void DrawRect (const Rect &rect, const Paint &paint)
 
void DrawOval (const Rect &rect, const Paint &paint)
 
void DrawRRect (const Rect &rect, const Size &corner_radii, const Paint &paint)
 
void DrawCircle (const Point &center, Scalar radius, const Paint &paint)
 
void DrawPoints (std::vector< Point > points, Scalar radius, const Paint &paint, PointStyle point_style)
 
void DrawImage (const std::shared_ptr< Image > &image, Point offset, const Paint &paint, SamplerDescriptor sampler={})
 
void DrawImageRect (const std::shared_ptr< Image > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
 
void ClipPath (const Path &path, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
 
void ClipRect (const Rect &rect, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
 
void ClipOval (const Rect &bounds, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
 
void ClipRRect (const Rect &rect, const Size &corner_radii, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
 
void DrawVertices (const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
 
void DrawAtlas (const std::shared_ptr< Image > &atlas, std::vector< Matrix > transforms, std::vector< Rect > texture_coordinates, std::vector< Color > colors, BlendMode blend_mode, SamplerDescriptor sampler, std::optional< Rect > cull_rect, const Paint &paint)
 
Picture EndRecordingAsPicture ()
 

Private Member Functions

void AddRenderEntityToCurrentPass (Entity entity, bool reuse_depth) override
 
void AddClipEntityToCurrentPass (Entity entity) override
 

Additional Inherited Members

- Public Attributes inherited from impeller::Canvas
struct impeller::Canvas::DebugOptions debug_options
 
- Static Public Attributes inherited from impeller::Canvas
static constexpr uint32_t kMaxDepth = 1 << 24
 
- Protected Member Functions inherited from impeller::Canvas
size_t GetClipHeight () const
 
void Initialize (std::optional< Rect > cull_rect)
 
void Reset ()
 
- Protected Attributes inherited from impeller::Canvas
std::deque< CanvasStackEntrytransform_stack_
 
std::optional< Rectinitial_cull_rect_
 
uint64_t current_depth_ = 0u
 

Detailed Description

Definition at line 20 of file experimental_canvas.h.

Constructor & Destructor Documentation

◆ ExperimentalCanvas() [1/3]

impeller::ExperimentalCanvas::ExperimentalCanvas ( ContentContext renderer,
RenderTarget render_target 
)

Definition at line 88 of file experimental_canvas.cc.

90 : Canvas(), renderer_(renderer), render_target_(render_target) {
91 SetupRenderPass();
92}

◆ ExperimentalCanvas() [2/3]

impeller::ExperimentalCanvas::ExperimentalCanvas ( ContentContext renderer,
RenderTarget render_target,
Rect  cull_rect 
)

Definition at line 94 of file experimental_canvas.cc.

97 : Canvas(cull_rect), renderer_(renderer), render_target_(render_target) {
98 SetupRenderPass();
99}

◆ ExperimentalCanvas() [3/3]

impeller::ExperimentalCanvas::ExperimentalCanvas ( ContentContext renderer,
RenderTarget render_target,
IRect  cull_rect 
)

Definition at line 101 of file experimental_canvas.cc.

104 : Canvas(cull_rect), renderer_(renderer), render_target_(render_target) {
105 SetupRenderPass();
106}

◆ ~ExperimentalCanvas()

impeller::ExperimentalCanvas::~ExperimentalCanvas ( )
overridedefault

Member Function Documentation

◆ AddClipEntityToCurrentPass()

void impeller::ExperimentalCanvas::AddClipEntityToCurrentPass ( Entity  entity)
overrideprivatevirtual

Reimplemented from impeller::Canvas.

Definition at line 313 of file experimental_canvas.cc.

313 {
314 auto transform = entity.GetTransform();
315 entity.SetTransform(
316 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) * transform);
317 // Ideally the clip depth would be greater than the current rendering
318 // depth because any rendering calls that follow this clip operation will
319 // pre-increment the depth and then be rendering above our clip depth,
320 // but that case will be caught by the CHECK in AddRenderEntity above.
321 // In practice we sometimes have a clip set with no rendering after it
322 // and in such cases the current depth will equal the clip depth.
323 // Eventually the DisplayList should optimize these out, but it is hard
324 // to know if a clip will actually be used in advance of storing it in
325 // the DisplayList buffer.
326 // See https://github.com/flutter/flutter/issues/147021
327 FML_CHECK(current_depth_ <= transform_stack_.back().clip_depth)
328 << current_depth_ << " <=? " << transform_stack_.back().clip_depth;
329 entity.SetClipDepth(transform_stack_.back().clip_depth);
330 entity.Render(renderer_, *render_passes_.back());
331}
std::deque< CanvasStackEntry > transform_stack_
Definition canvas.h:187
uint64_t current_depth_
Definition canvas.h:189
#define FML_CHECK(condition)
Definition logging.h:85
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95

◆ AddRenderEntityToCurrentPass()

void impeller::ExperimentalCanvas::AddRenderEntityToCurrentPass ( Entity  entity,
bool  reuse_depth 
)
overrideprivatevirtual

Reimplemented from impeller::Canvas.

Definition at line 286 of file experimental_canvas.cc.

287 {
288 auto transform = entity.GetTransform();
289 entity.SetTransform(
290 Matrix::MakeTranslation(Vector3(-GetGlobalPassPosition())) * transform);
291 if (!reuse_depth) {
293 }
294 // We can render at a depth up to and including the depth of the currently
295 // active clips and we will still be clipped out, but we cannot render at
296 // a depth that is greater than the current clips or we will not be clipped.
297 FML_CHECK(current_depth_ <= transform_stack_.back().clip_depth)
298 << current_depth_ << " <=? " << transform_stack_.back().clip_depth;
299 entity.SetClipDepth(current_depth_);
300
301 if (entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
303 ApplyFramebufferBlend(entity);
304 } else {
305 VALIDATION_LOG << "Emulated advanced blends are currently unsupported.";
306 return;
307 }
308 }
309
310 entity.Render(renderer_, *render_passes_.back());
311}
virtual bool SupportsFramebufferFetch() const =0
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
const Capabilities & GetDeviceCapabilities() const
static constexpr BlendMode kLastPipelineBlendMode
Definition entity.h:23
static void ApplyFramebufferBlend(Entity &entity)
#define VALIDATION_LOG
Definition validation.h:73

◆ DrawTextFrame()

void impeller::ExperimentalCanvas::DrawTextFrame ( const std::shared_ptr< TextFrame > &  text_frame,
Point  position,
const Paint paint 
)
overridevirtual

Reimplemented from impeller::Canvas.

Definition at line 257 of file experimental_canvas.cc.

260 {
261 Entity entity;
262 entity.SetClipDepth(GetClipHeight());
263 entity.SetBlendMode(paint.blend_mode);
264
265 auto text_contents = std::make_shared<TextContents>();
266 text_contents->SetTextFrame(text_frame);
267 text_contents->SetColor(paint.color);
268 text_contents->SetForceTextColor(paint.mask_blur_descriptor.has_value());
269 text_contents->SetScale(GetCurrentTransform().GetMaxBasisLengthXY());
270
271 entity.SetTransform(GetCurrentTransform() *
272 Matrix::MakeTranslation(position));
273
274 // TODO(bdero): This mask blur application is a hack. It will always wind up
275 // doing a gaussian blur that affects the color source itself
276 // instead of just the mask. The color filter text support
277 // needs to be reworked in order to interact correctly with
278 // mask filters.
279 // https://github.com/flutter/flutter/issues/133297
280 entity.SetContents(
281 paint.WithFilters(paint.WithMaskBlur(std::move(text_contents), true)));
282
283 AddRenderEntityToCurrentPass(std::move(entity), false);
284}
const Matrix & GetCurrentTransform() const
Definition canvas.cc:296
size_t GetClipHeight() const
Definition canvas.cc:823
void AddRenderEntityToCurrentPass(Entity entity, bool reuse_depth) override
const Paint & paint

◆ EndReplay()

void impeller::ExperimentalCanvas::EndReplay ( )
inline

Definition at line 44 of file experimental_canvas.h.

44 {
45 FML_DCHECK(inline_pass_contexts_.size() == 1u);
46 inline_pass_contexts_.back()->EndPass();
47 render_passes_.clear();
48 inline_pass_contexts_.clear();
49 renderer_.GetRenderTargetCache()->End();
50
51 Reset();
53 }
void Initialize(std::optional< Rect > cull_rect)
Definition canvas.cc:164
std::optional< Rect > initial_cull_rect_
Definition canvas.h:188
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
#define FML_DCHECK(condition)
Definition logging.h:103

◆ Restore()

bool impeller::ExperimentalCanvas::Restore ( )
overridevirtual

Reimplemented from impeller::Canvas.

Definition at line 194 of file experimental_canvas.cc.

194 {
195 FML_DCHECK(transform_stack_.size() > 0);
196 if (transform_stack_.size() == 1) {
197 return false;
198 }
199
200 // This check is important to make sure we didn't exceed the depth
201 // that the clips were rendered at while rendering any of the
202 // rendering ops. It is OK for the current depth to equal the
203 // outgoing clip depth because that means the clipping would have
204 // been successful up through the last rendering op, but it cannot
205 // be greater.
206 // Also, we bump the current rendering depth to the outgoing clip
207 // depth so that future rendering operations are not clipped by
208 // any of the pixels set by the expiring clips. It is OK for the
209 // estimates used to determine the clip depth in save/saveLayer
210 // to be overly conservative, but we need to jump the depth to
211 // the clip depth so that the next rendering op will get a
212 // larger depth (it will pre-increment the current_depth_ value).
213 FML_CHECK(current_depth_ <= transform_stack_.back().clip_depth)
214 << current_depth_ << " <=? " << transform_stack_.back().clip_depth;
215 current_depth_ = transform_stack_.back().clip_depth;
216
217 if (transform_stack_.back().rendering_mode ==
219 auto inline_pass = std::move(inline_pass_contexts_.back());
220
221 SaveLayerState save_layer_state = save_layer_state_.back();
222 save_layer_state_.pop_back();
223
224 std::shared_ptr<Contents> contents =
225 PaintPassDelegate(save_layer_state.paint)
226 .CreateContentsForSubpassTarget(inline_pass->GetTexture(),
227 transform_stack_.back().transform);
228
229 inline_pass->EndPass();
230 render_passes_.pop_back();
231 inline_pass_contexts_.pop_back();
232
233 Entity element_entity;
234 element_entity.SetClipDepth(++current_depth_);
235 element_entity.SetContents(std::move(contents));
236 element_entity.SetBlendMode(save_layer_state.paint.blend_mode);
237 element_entity.SetTransform(Matrix::MakeTranslation(
238 Vector3(save_layer_state.coverage.GetOrigin())));
239
240 if (element_entity.GetBlendMode() > Entity::kLastPipelineBlendMode) {
242 ApplyFramebufferBlend(element_entity);
243 } else {
244 VALIDATION_LOG << "Emulated advanced blends are currently unsupported.";
245 element_entity.SetBlendMode(BlendMode::kSourceOver);
246 }
247 }
248
249 element_entity.Render(renderer_, *render_passes_.back());
250 }
251
252 transform_stack_.pop_back();
253
254 return true;
255}

◆ Save()

void impeller::ExperimentalCanvas::Save ( uint32_t  total_content_depth)
overridevirtual

Reimplemented from impeller::Canvas.

Definition at line 142 of file experimental_canvas.cc.

142 {
143 auto entry = CanvasStackEntry{};
144 entry.transform = transform_stack_.back().transform;
145 entry.cull_rect = transform_stack_.back().cull_rect;
146 entry.clip_depth = current_depth_ + total_content_depth;
147 FML_CHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
148 << entry.clip_depth << " <=? " << transform_stack_.back().clip_depth
149 << " after allocating " << total_content_depth;
150 entry.clip_height = transform_stack_.back().clip_height;
151 entry.rendering_mode = Entity::RenderingMode::kDirect;
152 transform_stack_.emplace_back(entry);
153}

◆ SaveLayer()

void impeller::ExperimentalCanvas::SaveLayer ( const Paint paint,
std::optional< Rect bounds,
const std::shared_ptr< ImageFilter > &  backdrop_filter,
ContentBoundsPromise  bounds_promise,
uint32_t  total_content_depth 
)
overridevirtual

Reimplemented from impeller::Canvas.

Definition at line 155 of file experimental_canvas.cc.

160 {
161 // Can we always guarantee that we get a bounds? Does a lack of bounds
162 // indicate something?
163 if (!bounds.has_value()) {
164 bounds = Rect::MakeSize(render_target_.GetRenderTargetSize());
165 }
166 Rect subpass_coverage = bounds->TransformBounds(GetCurrentTransform());
167 auto target =
168 CreateRenderTarget(renderer_,
169 ISize::MakeWH(subpass_coverage.GetSize().width,
170 subpass_coverage.GetSize().height),
172 entity_pass_targets_.push_back(std::move(target));
173 save_layer_state_.push_back(SaveLayerState{paint, subpass_coverage});
174
175 CanvasStackEntry entry;
176 entry.transform = transform_stack_.back().transform;
177 entry.cull_rect = transform_stack_.back().cull_rect;
178 entry.clip_depth = current_depth_ + total_content_depth;
179 FML_CHECK(entry.clip_depth <= transform_stack_.back().clip_depth)
180 << entry.clip_depth << " <=? " << transform_stack_.back().clip_depth
181 << " after allocating " << total_content_depth;
182 entry.clip_height = transform_stack_.back().clip_height;
183 entry.rendering_mode = Entity::RenderingMode::kSubpass;
184 transform_stack_.emplace_back(entry);
185
186 auto inline_pass = std::make_unique<InlinePassContext>(
187 renderer_, *entity_pass_targets_.back(), 0);
188 inline_pass_contexts_.emplace_back(std::move(inline_pass));
189
190 auto result = inline_pass_contexts_.back()->GetRenderPass(0u);
191 render_passes_.push_back(result.pass);
192}
ISize GetRenderTargetSize() const
GAsyncResult * result
uint32_t * target
Optional< SkRect > bounds
Definition SkRecords.h:189
static std::unique_ptr< EntityPassTarget > CreateRenderTarget(ContentContext &renderer, ISize size, int mip_count, const Color &clear_color)
TRect< Scalar > Rect
Definition rect.h:746
static constexpr Color BlackTransparent()
Definition color.h:262
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:146
static constexpr TSize MakeWH(Type width, Type height)
Definition size.h:34

The documentation for this class was generated from the following files: