| /* |
| * Copyright 2021 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef skgpu_geom_BoundsManager_DEFINED |
| #define skgpu_geom_BoundsManager_DEFINED |
| |
| #include "experimental/graphite/src/DrawOrder.h" |
| #include "experimental/graphite/src/geom/Rect.h" |
| |
| #include "src/core/SkTBlockList.h" |
| |
| #include <cstdint> |
| |
| namespace skgpu { |
| |
| /** |
| * BoundsManager is an acceleration structure for device-space related pixel bounds queries. |
| * The BoundsManager relies on two related ordinal values: the CompressedPaintersOrder of a draw |
| * and the Z/depth value of the draw. The CompressedPaintersOrder enforces a specific submission |
| * order of draws to the GPU but can re-arrange draws out of their original painter's order if the |
| * GREATER depth test and the draw's Z value resolve out-of-order rendering. |
| * |
| * It supports querying the most recent draw intersecting a bounding rect (represented as a |
| * CompressedPaintersOrder value), recording a (bounds, CompressedPaintersOrder, and Z value) tuple, |
| * and querying if a (bounds, Z value) pair is fully occluded by another draw. |
| */ |
| class BoundsManager { |
| public: |
| virtual ~BoundsManager() {} |
| |
| virtual CompressedPaintersOrder getMostRecentDraw(const Rect& bounds) const = 0; |
| |
| virtual bool isOccluded(const Rect& bounds, PaintersDepth z) const = 0; |
| |
| virtual void recordDraw(const Rect& bounds, |
| CompressedPaintersOrder order, |
| PaintersDepth z, |
| bool fullyOpaque=false) = 0; |
| |
| virtual void reset() = 0; |
| }; |
| |
| // TODO: Select one most-effective BoundsManager implementation, make it the only option, and remove |
| // virtual-ness. For now, this seems useful for correctness testing by comparing against trivial |
| // implementations and for identifying how much "smarts" are actually worthwhile. |
| |
| // A BoundsManager that produces exact painter's order and assumes nothing is occluded. |
| class NaiveBoundsManager final : public BoundsManager { |
| public: |
| ~NaiveBoundsManager() override {} |
| |
| CompressedPaintersOrder getMostRecentDraw(const Rect& bounds) const override { |
| return fLatestDraw; |
| } |
| |
| bool isOccluded(const Rect& bounds, PaintersDepth z) const override { return false; } |
| |
| void recordDraw(const Rect& bounds, CompressedPaintersOrder order, PaintersDepth z, |
| bool fullyOpaque=false) override { |
| if (fLatestDraw < order) { |
| fLatestDraw = order; |
| } |
| } |
| |
| void reset() override { |
| fLatestDraw = CompressedPaintersOrder::First(); |
| } |
| |
| private: |
| CompressedPaintersOrder fLatestDraw = CompressedPaintersOrder::First(); |
| }; |
| |
| // A BoundsManager that tracks every draw and can exactly determine all queries |
| // using a brute force search. |
| class BruteForceBoundsManager : public BoundsManager { |
| public: |
| ~BruteForceBoundsManager() override {} |
| |
| CompressedPaintersOrder getMostRecentDraw(const Rect& bounds) const override { |
| CompressedPaintersOrder max = CompressedPaintersOrder::First(); |
| for (const Record& r : fRects.items()) { |
| if (max < r.fOrder && r.fBounds.intersects(bounds)) { |
| max = r.fOrder; |
| } |
| } |
| return max; |
| } |
| |
| bool isOccluded(const Rect& bounds, PaintersDepth z) const override { |
| // Iterate in reverse since the records were likely recorded in increasing Z |
| for (const Record& r : fRects.ritems()) { |
| if (r.fOpaque && z < r.fZ && r.fBounds.contains(bounds)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void recordDraw(const Rect& bounds, CompressedPaintersOrder order, PaintersDepth z, |
| bool fullyOpaque=false) override { |
| fRects.push_back({bounds, order, z, fullyOpaque}); |
| } |
| |
| void reset() override { |
| fRects.reset(); |
| } |
| |
| private: |
| struct Record { |
| Rect fBounds; |
| CompressedPaintersOrder fOrder; |
| PaintersDepth fZ; |
| bool fOpaque; |
| }; |
| |
| SkTBlockList<Record> fRects{16, SkBlockAllocator::GrowthPolicy::kFibonacci}; |
| }; |
| |
| } // namespace skgpu |
| |
| #endif // skgpu_geom_BoundsManager_DEFINED |