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#pragma once
6
7#include <cstdint>
8#include <functional>
9#include <memory>
10#include <string>
11#include <type_traits>
12
13#include "flutter/fml/hash_combine.h"
14#include "flutter/fml/logging.h"
15#include "flutter/fml/macros.h"
16#include "impeller/geometry/color.h"
17#include "impeller/geometry/rect.h"
18#include "impeller/geometry/scalar.h"
19
20namespace impeller {
21
22class Texture;
23
24//------------------------------------------------------------------------------
25/// @brief Specified where the allocation resides and how it is used.
26///
27enum class StorageMode {
28 //----------------------------------------------------------------------------
29 /// Allocations can be mapped onto the hosts address space and also be used by
30 /// the device.
31 ///
32 kHostVisible,
33 //----------------------------------------------------------------------------
34 /// Allocations can only be used by the device. This location is optimal for
35 /// use by the device. If the host needs to access these allocations, the
36 /// transfer queue must be used to transfer this allocation onto the a host
37 /// visible buffer.
38 ///
39 kDevicePrivate,
40 //----------------------------------------------------------------------------
41 /// Used by the device for temporary render targets. These allocations cannot
42 /// be transferred from and to other allocations using the transfer queue.
43 /// Render pass cannot initialize the contents of these buffers using load and
44 /// store actions.
45 ///
46 /// These allocations reside in tile memory which has higher bandwidth, lower
47 /// latency and lower power consumption. The total device memory usage is
48 /// also lower as a separate allocation does not need to be created in
49 /// device memory. Prefer using these allocations for intermediates like depth
50 /// and stencil buffers.
51 ///
52 kDeviceTransient,
53};
54
55constexpr const char* StorageModeToString(StorageMode mode) {
56 switch (mode) {
57 case StorageMode::kHostVisible:
58 return "HostVisible";
59 case StorageMode::kDevicePrivate:
60 return "DevicePrivate";
61 case StorageMode::kDeviceTransient:
62 return "DeviceTransient";
63 }
64 FML_UNREACHABLE();
65}
66
67//------------------------------------------------------------------------------
68/// @brief The Pixel formats supported by Impeller. The naming convention
69/// denotes the usage of the component, the bit width of that
70/// component, and then one or more qualifiers to its
71/// interpretation.
72///
73/// For instance, `kR8G8B8A8UNormIntSRGB` is a 32 bits-per-pixel
74/// format ordered in RGBA with 8 bits per component with each
75/// component expressed as an unsigned normalized integer and a
76/// conversion from sRGB to linear color space.
77///
78/// Key:
79/// R -> Red Component
80/// G -> Green Component
81/// B -> Blue Component
82/// D -> Depth Component
83/// S -> Stencil Component
84/// U -> Unsigned (Lack of this denotes a signed component)
85/// Norm -> Normalized
86/// SRGB -> sRGB to linear interpretation
87///
88/// While the effective bit width of the pixel can be determined by
89/// adding up the widths of each component, only the non-esoteric
90/// formats are tightly packed. Do not assume tight packing for the
91/// esoteric formats and use blit passes to convert to a
92/// non-esoteric pass.
93///
94enum class PixelFormat {
95 kUnknown,
96 kA8UNormInt,
97 kR8UNormInt,
98 kR8G8UNormInt,
99 kR8G8B8A8UNormInt,
100 kR8G8B8A8UNormIntSRGB,
101 kB8G8R8A8UNormInt,
102 kB8G8R8A8UNormIntSRGB,
103 kR32G32B32A32Float,
104 kR16G16B16A16Float,
105 kB10G10R10XR,
106 kB10G10R10XRSRGB,
107 kB10G10R10A10XR,
108 // Depth and stencil formats.
109 kS8UInt,
110 kD32FloatS8UInt,
111};
112
113constexpr const char* PixelFormatToString(PixelFormat format) {
114 switch (format) {
115 case PixelFormat::kUnknown:
116 return "Unknown";
117 case PixelFormat::kA8UNormInt:
118 return "A8UNormInt";
119 case PixelFormat::kR8UNormInt:
120 return "R8UNormInt";
121 case PixelFormat::kR8G8UNormInt:
122 return "R8G8UNormInt";
123 case PixelFormat::kR8G8B8A8UNormInt:
124 return "R8G8B8A8UNormInt";
125 case PixelFormat::kR8G8B8A8UNormIntSRGB:
126 return "R8G8B8A8UNormIntSRGB";
127 case PixelFormat::kB8G8R8A8UNormInt:
128 return "B8G8R8A8UNormInt";
129 case PixelFormat::kB8G8R8A8UNormIntSRGB:
130 return "B8G8R8A8UNormIntSRGB";
131 case PixelFormat::kR32G32B32A32Float:
132 return "R32G32B32A32Float";
133 case PixelFormat::kR16G16B16A16Float:
134 return "R16G16B16A16Float";
135 case PixelFormat::kB10G10R10XR:
136 return "B10G10R10XR";
137 case PixelFormat::kB10G10R10XRSRGB:
138 return "B10G10R10XRSRGB";
139 case PixelFormat::kB10G10R10A10XR:
140 return "B10G10R10A10XR";
141 case PixelFormat::kS8UInt:
142 return "S8UInt";
143 case PixelFormat::kD32FloatS8UInt:
144 return "D32FloatS8UInt";
145 }
146 FML_UNREACHABLE();
147}
148
149enum class BlendFactor {
150 kZero,
151 kOne,
152 kSourceColor,
153 kOneMinusSourceColor,
154 kSourceAlpha,
155 kOneMinusSourceAlpha,
156 kDestinationColor,
157 kOneMinusDestinationColor,
158 kDestinationAlpha,
159 kOneMinusDestinationAlpha,
160 kSourceAlphaSaturated,
161 kBlendColor,
162 kOneMinusBlendColor,
163 kBlendAlpha,
164 kOneMinusBlendAlpha,
165};
166
167enum class BlendOperation {
168 kAdd,
169 kSubtract,
170 kReverseSubtract,
171};
172
173enum class LoadAction {
174 kDontCare,
175 kLoad,
176 kClear,
177};
178
179enum class StoreAction {
180 kDontCare,
181 kStore,
182 kMultisampleResolve,
183 kStoreAndMultisampleResolve,
184};
185
186constexpr const char* LoadActionToString(LoadAction action) {
187 switch (action) {
188 case LoadAction::kDontCare:
189 return "DontCare";
190 case LoadAction::kLoad:
191 return "Load";
192 case LoadAction::kClear:
193 return "Clear";
194 }
195}
196
197constexpr const char* StoreActionToString(StoreAction action) {
198 switch (action) {
199 case StoreAction::kDontCare:
200 return "DontCare";
201 case StoreAction::kStore:
202 return "Store";
203 case StoreAction::kMultisampleResolve:
204 return "MultisampleResolve";
205 case StoreAction::kStoreAndMultisampleResolve:
206 return "StoreAndMultisampleResolve";
207 }
208}
209
210constexpr bool CanClearAttachment(LoadAction action) {
211 switch (action) {
212 case LoadAction::kLoad:
213 return false;
214 case LoadAction::kDontCare:
215 case LoadAction::kClear:
216 return true;
217 }
218 FML_UNREACHABLE();
219}
220
221constexpr bool CanDiscardAttachmentWhenDone(StoreAction action) {
222 switch (action) {
223 case StoreAction::kStore:
224 case StoreAction::kStoreAndMultisampleResolve:
225 return false;
226 case StoreAction::kDontCare:
227 case StoreAction::kMultisampleResolve:
228 return true;
229 }
230 FML_UNREACHABLE();
231}
232
233enum class TextureType {
234 kTexture2D,
235 kTexture2DMultisample,
236 kTextureCube,
237};
238
239constexpr const char* TextureTypeToString(TextureType type) {
240 switch (type) {
241 case TextureType::kTexture2D:
242 return "Texture2D";
243 case TextureType::kTexture2DMultisample:
244 return "Texture2DMultisample";
245 case TextureType::kTextureCube:
246 return "TextureCube";
247 }
248 FML_UNREACHABLE();
249}
250
251constexpr bool IsMultisampleCapable(TextureType type) {
252 switch (type) {
253 case TextureType::kTexture2D:
254 case TextureType::kTextureCube:
255 return false;
256 case TextureType::kTexture2DMultisample:
257 return true;
258 }
259 return false;
260}
261
262enum class SampleCount {
263 kCount1 = 1,
264 kCount4 = 4,
265};
266
267using TextureUsageMask = uint64_t;
268
269enum class TextureUsage : TextureUsageMask {
270 kUnknown = 0,
271 kShaderRead = 1 << 0,
272 kShaderWrite = 1 << 1,
273 kRenderTarget = 1 << 2,
274};
275
276constexpr bool TextureUsageIsRenderTarget(TextureUsageMask mask) {
277 return static_cast<TextureUsageMask>(TextureUsage::kRenderTarget) & mask;
278}
279
280constexpr const char* TextureUsageToString(TextureUsage usage) {
281 switch (usage) {
282 case TextureUsage::kUnknown:
283 return "Unknown";
284 case TextureUsage::kShaderRead:
285 return "ShaderRead";
286 case TextureUsage::kShaderWrite:
287 return "ShaderWrite";
288 case TextureUsage::kRenderTarget:
289 return "RenderTarget";
290 }
291 FML_UNREACHABLE();
292}
293
294std::string TextureUsageMaskToString(TextureUsageMask mask);
295
296enum class TextureIntent {
297 kUploadFromHost,
298 kRenderToTexture,
299};
300
301enum class CullMode {
302 kNone,
303 kFrontFace,
304 kBackFace,
305};
306
307enum class IndexType {
308 kUnknown,
309 k16bit,
310 k32bit,
311 /// Does not use the index buffer.
312 kNone,
313};
314
315enum class PrimitiveType {
316 kTriangle,
317 kTriangleStrip,
318 kLine,
319 kLineStrip,
320 kPoint,
321 // Triangle fans are implementation dependent and need extra extensions
322 // checks. Hence, they are not supported here.
323};
324
325enum class PolygonMode {
326 kFill,
327 kLine,
328};
329
330struct DepthRange {
331 Scalar z_near = 0.0;
332 Scalar z_far = 1.0;
333
334 constexpr bool operator==(const DepthRange& other) const {
335 return z_near == other.z_near && z_far == other.z_far;
336 }
337};
338
339struct Viewport {
340 Rect rect;
341 DepthRange depth_range;
342
343 constexpr bool operator==(const Viewport& other) const {
344 return rect == other.rect && depth_range == other.depth_range;
345 }
346};
347
348enum class MinMagFilter {
349 /// Select nearest to the sample point. Most widely supported.
350 kNearest,
351 /// Select two points and linearly interpolate between them. Some formats
352 /// may not support this.
353 kLinear,
354};
355
356enum class MipFilter {
357 /// Sample from the nearest mip level.
358 kNearest,
359 /// Sample from the two nearest mip levels and linearly interpolate between
360 /// them.
361 kLinear,
362};
363
364enum class SamplerAddressMode {
365 kClampToEdge,
366 kRepeat,
367 kMirror,
368 // More modes are almost always supported but they are usually behind
369 // extensions checks. The ones current in these structs are safe (always
370 // supported) defaults.
371
372 /// @brief decal sampling mode is only supported on devices that pass
373 /// the Capabilities.SupportsDecalTileMode check.
374 kDecal,
375};
376
377enum class ColorWriteMask : uint64_t {
378 kNone = 0,
379 kRed = 1 << 0,
380 kGreen = 1 << 1,
381 kBlue = 1 << 2,
382 kAlpha = 1 << 3,
383 kAll = kRed | kGreen | kBlue | kAlpha,
384};
385
386constexpr size_t BytesPerPixelForPixelFormat(PixelFormat format) {
387 switch (format) {
388 case PixelFormat::kUnknown:
389 return 0u;
390 case PixelFormat::kA8UNormInt:
391 case PixelFormat::kR8UNormInt:
392 case PixelFormat::kS8UInt:
393 return 1u;
394 case PixelFormat::kR8G8UNormInt:
395 return 2u;
396 case PixelFormat::kR8G8B8A8UNormInt:
397 case PixelFormat::kR8G8B8A8UNormIntSRGB:
398 case PixelFormat::kB8G8R8A8UNormInt:
399 case PixelFormat::kB8G8R8A8UNormIntSRGB:
400 case PixelFormat::kB10G10R10XRSRGB:
401 case PixelFormat::kB10G10R10XR:
402 return 4u;
403 case PixelFormat::kD32FloatS8UInt:
404 return 5u;
405 case PixelFormat::kR16G16B16A16Float:
406 case PixelFormat::kB10G10R10A10XR:
407 return 8u;
408 case PixelFormat::kR32G32B32A32Float:
409 return 16u;
410 }
411 return 0u;
412}
413
414//------------------------------------------------------------------------------
415/// @brief Describe the color attachment that will be used with this
416/// pipeline.
417///
418/// Blending at specific color attachments follows the pseudo-code:
419/// ```
420/// if (blending_enabled) {
421/// final_color.rgb = (src_color_blend_factor * new_color.rgb)
422/// <color_blend_op>
423/// (dst_color_blend_factor * old_color.rgb);
424/// final_color.a = (src_alpha_blend_factor * new_color.a)
425/// <alpha_blend_op>
426/// (dst_alpha_blend_factor * old_color.a);
427/// } else {
428/// final_color = new_color;
429/// }
430/// // IMPORTANT: The write mask is applied irrespective of whether
431/// // blending_enabled is set.
432/// final_color = final_color & write_mask;
433/// ```
434///
435/// The default blend mode is 1 - source alpha.
436struct ColorAttachmentDescriptor {
437 PixelFormat format = PixelFormat::kUnknown;
438 bool blending_enabled = false;
439
440 BlendFactor src_color_blend_factor = BlendFactor::kSourceAlpha;
441 BlendOperation color_blend_op = BlendOperation::kAdd;
442 BlendFactor dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
443
444 BlendFactor src_alpha_blend_factor = BlendFactor::kSourceAlpha;
445 BlendOperation alpha_blend_op = BlendOperation::kAdd;
446 BlendFactor dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
447
448 std::underlying_type_t<ColorWriteMask> write_mask =
449 static_cast<uint64_t>(ColorWriteMask::kAll);
450
451 constexpr bool operator==(const ColorAttachmentDescriptor& o) const {
452 return format == o.format && //
453 blending_enabled == o.blending_enabled && //
454 src_color_blend_factor == o.src_color_blend_factor && //
455 color_blend_op == o.color_blend_op && //
456 dst_color_blend_factor == o.dst_color_blend_factor && //
457 src_alpha_blend_factor == o.src_alpha_blend_factor && //
458 alpha_blend_op == o.alpha_blend_op && //
459 dst_alpha_blend_factor == o.dst_alpha_blend_factor && //
460 write_mask == o.write_mask;
461 }
462
463 constexpr size_t Hash() const {
464 return fml::HashCombine(args: format, args: blending_enabled, args: src_color_blend_factor,
465 args: color_blend_op, args: dst_color_blend_factor,
466 args: src_alpha_blend_factor, args: alpha_blend_op,
467 args: dst_alpha_blend_factor, args: write_mask);
468 }
469};
470
471enum class CompareFunction {
472 /// Comparison test never passes.
473 kNever,
474 /// Comparison test passes always passes.
475 kAlways,
476 /// Comparison test passes if new_value < current_value.
477 kLess,
478 /// Comparison test passes if new_value == current_value.
479 kEqual,
480 /// Comparison test passes if new_value <= current_value.
481 kLessEqual,
482 /// Comparison test passes if new_value > current_value.
483 kGreater,
484 /// Comparison test passes if new_value != current_value.
485 kNotEqual,
486 /// Comparison test passes if new_value >= current_value.
487 kGreaterEqual,
488};
489
490enum class StencilOperation {
491 /// Don't modify the current stencil value.
492 kKeep,
493 /// Reset the stencil value to zero.
494 kZero,
495 /// Reset the stencil value to the reference value.
496 kSetToReferenceValue,
497 /// Increment the current stencil value by 1. Clamp it to the maximum.
498 kIncrementClamp,
499 /// Decrement the current stencil value by 1. Clamp it to zero.
500 kDecrementClamp,
501 /// Perform a logical bitwise invert on the current stencil value.
502 kInvert,
503 /// Increment the current stencil value by 1. If at maximum, set to zero.
504 kIncrementWrap,
505 /// Decrement the current stencil value by 1. If at zero, set to maximum.
506 kDecrementWrap,
507};
508
509struct DepthAttachmentDescriptor {
510 //----------------------------------------------------------------------------
511 /// Indicates how to compare the value with that in the depth buffer.
512 ///
513 CompareFunction depth_compare = CompareFunction::kAlways;
514 //----------------------------------------------------------------------------
515 /// Indicates when writes must be performed to the depth buffer.
516 ///
517 bool depth_write_enabled = false;
518
519 constexpr bool operator==(const DepthAttachmentDescriptor& o) const {
520 return depth_compare == o.depth_compare &&
521 depth_write_enabled == o.depth_write_enabled;
522 }
523
524 constexpr size_t GetHash() const {
525 return fml::HashCombine(args: depth_compare, args: depth_write_enabled);
526 }
527};
528
529struct StencilAttachmentDescriptor {
530 //----------------------------------------------------------------------------
531 /// Indicates the operation to perform between the reference value and the
532 /// value in the stencil buffer. Both values have the read_mask applied to
533 /// them before performing this operation.
534 ///
535 CompareFunction stencil_compare = CompareFunction::kAlways;
536 //----------------------------------------------------------------------------
537 /// Indicates what to do when the stencil test has failed.
538 ///
539 StencilOperation stencil_failure = StencilOperation::kKeep;
540 //----------------------------------------------------------------------------
541 /// Indicates what to do when the stencil test passes but the depth test
542 /// fails.
543 ///
544 StencilOperation depth_failure = StencilOperation::kKeep;
545 //----------------------------------------------------------------------------
546 /// Indicates what to do when both the stencil and depth tests pass.
547 ///
548 StencilOperation depth_stencil_pass = StencilOperation::kKeep;
549
550 //----------------------------------------------------------------------------
551 /// The mask applied to the reference and stencil buffer values before
552 /// performing the stencil_compare operation.
553 ///
554 uint32_t read_mask = ~0;
555 //----------------------------------------------------------------------------
556 /// The mask applied to the new stencil value before it is written into the
557 /// stencil buffer.
558 ///
559 uint32_t write_mask = ~0;
560
561 constexpr bool operator==(const StencilAttachmentDescriptor& o) const {
562 return stencil_compare == o.stencil_compare &&
563 stencil_failure == o.stencil_failure &&
564 depth_failure == o.depth_failure &&
565 depth_stencil_pass == o.depth_stencil_pass &&
566 read_mask == o.read_mask && write_mask == o.write_mask;
567 }
568
569 constexpr size_t GetHash() const {
570 return fml::HashCombine(args: stencil_compare, args: stencil_failure, args: depth_failure,
571 args: depth_stencil_pass, args: read_mask, args: write_mask);
572 }
573};
574
575struct Attachment {
576 std::shared_ptr<Texture> texture;
577 std::shared_ptr<Texture> resolve_texture;
578 LoadAction load_action = LoadAction::kDontCare;
579 StoreAction store_action = StoreAction::kStore;
580
581 bool IsValid() const;
582};
583
584struct ColorAttachment : public Attachment {
585 Color clear_color = Color::BlackTransparent();
586};
587
588struct DepthAttachment : public Attachment {
589 double clear_depth = 0.0;
590};
591
592struct StencilAttachment : public Attachment {
593 uint32_t clear_stencil = 0;
594};
595
596std::string AttachmentToString(const Attachment& attachment);
597
598std::string ColorAttachmentToString(const ColorAttachment& color);
599
600std::string DepthAttachmentToString(const DepthAttachment& depth);
601
602std::string StencilAttachmentToString(const StencilAttachment& stencil);
603
604} // namespace impeller
605
606namespace std {
607
608template <>
609struct hash<impeller::DepthAttachmentDescriptor> {
610 constexpr std::size_t operator()(
611 const impeller::DepthAttachmentDescriptor& des) const {
612 return des.GetHash();
613 }
614};
615
616template <>
617struct hash<impeller::StencilAttachmentDescriptor> {
618 constexpr std::size_t operator()(
619 const impeller::StencilAttachmentDescriptor& des) const {
620 return des.GetHash();
621 }
622};
623
624} // namespace std
625

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com

source code of flutter_engine/flutter/impeller/core/formats.h