| // Copyright 2013 The Flutter Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "impeller/renderer/pipeline_descriptor.h" | 
 |  | 
 | #include "impeller/core/formats.h" | 
 | #include "impeller/renderer/shader_function.h" | 
 | #include "impeller/renderer/shader_library.h" | 
 | #include "impeller/renderer/vertex_descriptor.h" | 
 |  | 
 | namespace impeller { | 
 |  | 
 | PipelineDescriptor::PipelineDescriptor() = default; | 
 |  | 
 | PipelineDescriptor::~PipelineDescriptor() = default; | 
 |  | 
 | // Comparable<PipelineDescriptor> | 
 | std::size_t PipelineDescriptor::GetHash() const { | 
 |   auto seed = fml::HashCombine(); | 
 |   fml::HashCombineSeed(seed, label_); | 
 |   fml::HashCombineSeed(seed, sample_count_); | 
 |   for (const auto& entry : entrypoints_) { | 
 |     fml::HashCombineSeed(seed, entry.first); | 
 |     if (auto second = entry.second) { | 
 |       fml::HashCombineSeed(seed, second->GetHash()); | 
 |     } | 
 |   } | 
 |   for (const auto& des : color_attachment_descriptors_) { | 
 |     fml::HashCombineSeed(seed, des.first); | 
 |     fml::HashCombineSeed(seed, des.second.Hash()); | 
 |   } | 
 |   if (vertex_descriptor_) { | 
 |     fml::HashCombineSeed(seed, vertex_descriptor_->GetHash()); | 
 |   } | 
 |   fml::HashCombineSeed(seed, depth_pixel_format_); | 
 |   fml::HashCombineSeed(seed, stencil_pixel_format_); | 
 |   fml::HashCombineSeed(seed, depth_attachment_descriptor_); | 
 |   fml::HashCombineSeed(seed, front_stencil_attachment_descriptor_); | 
 |   fml::HashCombineSeed(seed, back_stencil_attachment_descriptor_); | 
 |   fml::HashCombineSeed(seed, winding_order_); | 
 |   fml::HashCombineSeed(seed, cull_mode_); | 
 |   fml::HashCombineSeed(seed, primitive_type_); | 
 |   fml::HashCombineSeed(seed, polygon_mode_); | 
 |   return seed; | 
 | } | 
 |  | 
 | // Comparable<PipelineDescriptor> | 
 | bool PipelineDescriptor::IsEqual(const PipelineDescriptor& other) const { | 
 |   return label_ == other.label_ && sample_count_ == other.sample_count_ && | 
 |          DeepCompareMap(entrypoints_, other.entrypoints_) && | 
 |          color_attachment_descriptors_ == other.color_attachment_descriptors_ && | 
 |          DeepComparePointer(vertex_descriptor_, other.vertex_descriptor_) && | 
 |          stencil_pixel_format_ == other.stencil_pixel_format_ && | 
 |          depth_pixel_format_ == other.depth_pixel_format_ && | 
 |          depth_attachment_descriptor_ == other.depth_attachment_descriptor_ && | 
 |          front_stencil_attachment_descriptor_ == | 
 |              other.front_stencil_attachment_descriptor_ && | 
 |          back_stencil_attachment_descriptor_ == | 
 |              other.back_stencil_attachment_descriptor_ && | 
 |          winding_order_ == other.winding_order_ && | 
 |          cull_mode_ == other.cull_mode_ && | 
 |          primitive_type_ == other.primitive_type_ && | 
 |          polygon_mode_ == other.polygon_mode_; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetLabel(std::string label) { | 
 |   label_ = std::move(label); | 
 |   return *this; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetSampleCount(SampleCount samples) { | 
 |   sample_count_ = samples; | 
 |   return *this; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::AddStageEntrypoint( | 
 |     std::shared_ptr<const ShaderFunction> function) { | 
 |   if (!function) { | 
 |     return *this; | 
 |   } | 
 |  | 
 |   if (function->GetStage() == ShaderStage::kUnknown) { | 
 |     return *this; | 
 |   } | 
 |  | 
 |   entrypoints_[function->GetStage()] = std::move(function); | 
 |  | 
 |   return *this; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetVertexDescriptor( | 
 |     std::shared_ptr<VertexDescriptor> vertex_descriptor) { | 
 |   vertex_descriptor_ = std::move(vertex_descriptor); | 
 |   return *this; | 
 | } | 
 |  | 
 | size_t PipelineDescriptor::GetMaxColorAttacmentBindIndex() const { | 
 |   size_t max = 0; | 
 |   for (const auto& color : color_attachment_descriptors_) { | 
 |     max = std::max(color.first, max); | 
 |   } | 
 |   return max; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetColorAttachmentDescriptor( | 
 |     size_t index, | 
 |     ColorAttachmentDescriptor desc) { | 
 |   color_attachment_descriptors_[index] = desc; | 
 |   return *this; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetColorAttachmentDescriptors( | 
 |     std::map<size_t /* index */, ColorAttachmentDescriptor> descriptors) { | 
 |   color_attachment_descriptors_ = std::move(descriptors); | 
 |   return *this; | 
 | } | 
 |  | 
 | const ColorAttachmentDescriptor* | 
 | PipelineDescriptor::GetColorAttachmentDescriptor(size_t index) const { | 
 |   auto found = color_attachment_descriptors_.find(index); | 
 |   return found == color_attachment_descriptors_.end() ? nullptr | 
 |                                                       : &found->second; | 
 | } | 
 |  | 
 | const ColorAttachmentDescriptor* | 
 | PipelineDescriptor::GetLegacyCompatibleColorAttachment() const { | 
 |   // Legacy renderers may only render to a single color attachment at index 0u. | 
 |   if (color_attachment_descriptors_.size() != 1u) { | 
 |     return nullptr; | 
 |   } | 
 |   return GetColorAttachmentDescriptor(0u); | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetDepthPixelFormat( | 
 |     PixelFormat format) { | 
 |   depth_pixel_format_ = format; | 
 |   return *this; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetStencilPixelFormat( | 
 |     PixelFormat format) { | 
 |   stencil_pixel_format_ = format; | 
 |   return *this; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetDepthStencilAttachmentDescriptor( | 
 |     std::optional<DepthAttachmentDescriptor> desc) { | 
 |   depth_attachment_descriptor_ = desc; | 
 |   return *this; | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetStencilAttachmentDescriptors( | 
 |     std::optional<StencilAttachmentDescriptor> front_and_back) { | 
 |   return SetStencilAttachmentDescriptors(front_and_back, front_and_back); | 
 | } | 
 |  | 
 | PipelineDescriptor& PipelineDescriptor::SetStencilAttachmentDescriptors( | 
 |     std::optional<StencilAttachmentDescriptor> front, | 
 |     std::optional<StencilAttachmentDescriptor> back) { | 
 |   front_stencil_attachment_descriptor_ = front; | 
 |   back_stencil_attachment_descriptor_ = back; | 
 |   return *this; | 
 | } | 
 |  | 
 | void PipelineDescriptor::ClearStencilAttachments() { | 
 |   back_stencil_attachment_descriptor_.reset(); | 
 |   front_stencil_attachment_descriptor_.reset(); | 
 |   SetStencilPixelFormat(impeller::PixelFormat::kUnknown); | 
 | } | 
 |  | 
 | void PipelineDescriptor::ClearDepthAttachment() { | 
 |   depth_attachment_descriptor_.reset(); | 
 |   SetDepthPixelFormat(impeller::PixelFormat::kUnknown); | 
 | } | 
 |  | 
 | void PipelineDescriptor::ClearColorAttachment(size_t index) { | 
 |   if (color_attachment_descriptors_.find(index) == | 
 |       color_attachment_descriptors_.end()) { | 
 |     return; | 
 |   } | 
 |  | 
 |   color_attachment_descriptors_.erase(index); | 
 | } | 
 |  | 
 | void PipelineDescriptor::ResetAttachments() { | 
 |   color_attachment_descriptors_.clear(); | 
 |   depth_attachment_descriptor_.reset(); | 
 |   front_stencil_attachment_descriptor_.reset(); | 
 |   back_stencil_attachment_descriptor_.reset(); | 
 | } | 
 |  | 
 | PixelFormat PipelineDescriptor::GetStencilPixelFormat() const { | 
 |   return stencil_pixel_format_; | 
 | } | 
 |  | 
 | std::optional<StencilAttachmentDescriptor> | 
 | PipelineDescriptor::GetFrontStencilAttachmentDescriptor() const { | 
 |   return front_stencil_attachment_descriptor_; | 
 | } | 
 |  | 
 | std::optional<DepthAttachmentDescriptor> | 
 | PipelineDescriptor::GetDepthStencilAttachmentDescriptor() const { | 
 |   return depth_attachment_descriptor_; | 
 | } | 
 |  | 
 | const std::map<size_t /* index */, ColorAttachmentDescriptor>& | 
 | PipelineDescriptor::GetColorAttachmentDescriptors() const { | 
 |   return color_attachment_descriptors_; | 
 | } | 
 |  | 
 | const std::shared_ptr<VertexDescriptor>& | 
 | PipelineDescriptor::GetVertexDescriptor() const { | 
 |   return vertex_descriptor_; | 
 | } | 
 |  | 
 | const std::map<ShaderStage, std::shared_ptr<const ShaderFunction>>& | 
 | PipelineDescriptor::GetStageEntrypoints() const { | 
 |   return entrypoints_; | 
 | } | 
 |  | 
 | std::shared_ptr<const ShaderFunction> PipelineDescriptor::GetEntrypointForStage( | 
 |     ShaderStage stage) const { | 
 |   if (auto found = entrypoints_.find(stage); found != entrypoints_.end()) { | 
 |     return found->second; | 
 |   } | 
 |   return nullptr; | 
 | } | 
 |  | 
 | const std::string& PipelineDescriptor::GetLabel() const { | 
 |   return label_; | 
 | } | 
 |  | 
 | PixelFormat PipelineDescriptor::GetDepthPixelFormat() const { | 
 |   return depth_pixel_format_; | 
 | } | 
 |  | 
 | std::optional<StencilAttachmentDescriptor> | 
 | PipelineDescriptor::GetBackStencilAttachmentDescriptor() const { | 
 |   return back_stencil_attachment_descriptor_; | 
 | } | 
 |  | 
 | bool PipelineDescriptor::HasStencilAttachmentDescriptors() const { | 
 |   return front_stencil_attachment_descriptor_.has_value() || | 
 |          back_stencil_attachment_descriptor_.has_value(); | 
 | } | 
 |  | 
 | void PipelineDescriptor::SetCullMode(CullMode mode) { | 
 |   cull_mode_ = mode; | 
 | } | 
 |  | 
 | CullMode PipelineDescriptor::GetCullMode() const { | 
 |   return cull_mode_; | 
 | } | 
 |  | 
 | void PipelineDescriptor::SetWindingOrder(WindingOrder order) { | 
 |   winding_order_ = order; | 
 | } | 
 |  | 
 | WindingOrder PipelineDescriptor::GetWindingOrder() const { | 
 |   return winding_order_; | 
 | } | 
 |  | 
 | void PipelineDescriptor::SetPrimitiveType(PrimitiveType type) { | 
 |   primitive_type_ = type; | 
 | } | 
 |  | 
 | PrimitiveType PipelineDescriptor::GetPrimitiveType() const { | 
 |   return primitive_type_; | 
 | } | 
 |  | 
 | void PipelineDescriptor::SetPolygonMode(PolygonMode mode) { | 
 |   polygon_mode_ = mode; | 
 | } | 
 |  | 
 | PolygonMode PipelineDescriptor::GetPolygonMode() const { | 
 |   return polygon_mode_; | 
 | } | 
 |  | 
 | }  // namespace impeller |