// Copyright 2014 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/40285824): Remove this and convert code to safer constructs. #pragma allow_unsafe_buffers #endif #include "components/viz/service/display/draw_polygon.h" #include <stddef.h> #include <cmath> #include <utility> #include <vector> #include "base/ranges/algorithm.h" #include "build/build_config.h" #include "cc/base/math_util.h" #include "components/viz/common/quads/draw_quad.h" namespace { // This threshold controls how "thick" a plane is. If a point's distance is // <= |split_threshold|, then it is considered on the plane for the purpose of // polygon splitting. static const float split_threshold = …; static const float normalized_threshold = …; void PointInterpolate(const gfx::Point3F& from, const gfx::Point3F& to, double delta, gfx::Point3F* out) { … } } // namespace namespace viz { DrawPolygon::DrawPolygon() = default; DrawPolygon::DrawPolygon(const DrawQuad* original, const std::vector<gfx::Point3F>& in_points, const gfx::Vector3dF& normal, int draw_order_index) : … { … } // This takes the original DrawQuad that this polygon should be based on, // a visible content rect to make the 4 corner points from, and a transformation // to move it and its normal into screen space. DrawPolygon::DrawPolygon(const DrawQuad* original_ref, const gfx::RectF& visible_layer_rect, const gfx::Transform& transform, int draw_order_index) : … { … } DrawPolygon::~DrawPolygon() = default; std::unique_ptr<DrawPolygon> DrawPolygon::CreateCopy() { … } // // If this were to be more generally used and expected to be applicable // replacing this with Newell's algorithm (or an improvement thereof) // would be preferable, but usually this is coming in from a rectangle // that has been transformed to screen space and clipped. // Averaging a few near diagonal cross products is pretty good in that case. // void DrawPolygon::ConstructNormal() { … } #if BUILDFLAG(IS_WIN) // // Allows the unittest to invoke this for the more general constructor. // void DrawPolygon::RecomputeNormalForTesting() { ConstructNormal(); } #endif float DrawPolygon::SignedPointDistance(const gfx::Point3F& point) const { … } // This function is separate from ApplyTransform because it is often unnecessary // to transform the normal with the rest of the polygon. // When drawing these polygons, it is necessary to move them back into layer // space before sending them to OpenGL, which requires using ApplyTransform, // but normal information is no longer needed after sorting. void DrawPolygon::ApplyTransformToNormal(const gfx::Transform& transform) { … } void DrawPolygon::ApplyTransform(const gfx::Transform& transform) { … } // TransformToScreenSpace assumes we're moving a layer from its layer space // into 3D screen space, which for sorting purposes requires the normal to // be transformed along with the vertices. void DrawPolygon::TransformToScreenSpace(const gfx::Transform& transform) { … } // In the case of TransformToLayerSpace, we assume that we are giving the // inverse transformation back to the polygon to move it back into layer space // but we can ignore the costly process of applying the inverse to the normal // since we know the normal will just reset to its original state. void DrawPolygon::TransformToLayerSpace( const gfx::Transform& inverse_transform) { … } // Split |polygon| based upon |this|, leaving the results in |front| and |back|. // If |polygon| is not split by |this|, then move it to either |front| or |back| // depending on its orientation relative to |this|. Sets |is_coplanar| to true // if |polygon| is actually coplanar with |this| (in which case whether it is // front facing or back facing is determined by the dot products of normals, and // document order). void DrawPolygon::SplitPolygon(std::unique_ptr<DrawPolygon> polygon, std::unique_ptr<DrawPolygon>* front, std::unique_ptr<DrawPolygon>* back, bool* is_coplanar) const { … } // This algorithm takes the first vertex in the polygon and uses that as a // pivot point to fan out and create quads from the rest of the vertices. // |offset| starts off as the second vertex, and then |op1| and |op2| indicate // offset+1 and offset+2 respectively. // After the first quad is created, the first vertex in the next quad is the // same as all the rest, the pivot point. The second vertex in the next quad is // the old |op2|, the last vertex added to the previous quad. This continues // until all points are exhausted. // The special case here is where there are only 3 points remaining, in which // case we use the same values for vertex 3 and 4 to make a degenerate quad // that represents a triangle. void DrawPolygon::ToQuads2D(std::vector<gfx::QuadF>* quads) const { … } } // namespace viz