xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrScissorState.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef GrScissorState_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define GrScissorState_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
12*c8dee2aaSAndroid Build Coastguard Worker 
13*c8dee2aaSAndroid Build Coastguard Worker /**
14*c8dee2aaSAndroid Build Coastguard Worker  * The scissor state is stored as the scissor rectangle and the backing store bounds of the render
15*c8dee2aaSAndroid Build Coastguard Worker  * target that the scissor will apply to. If the render target is approximate fit and the padded
16*c8dee2aaSAndroid Build Coastguard Worker  * content should not be modified, the clip should apply the render target context's logical bounds
17*c8dee2aaSAndroid Build Coastguard Worker  * as part of the scissor (e.g. when stenciling). This puts the onus on the render target context
18*c8dee2aaSAndroid Build Coastguard Worker  * to intentionally discard the scissor at its logical bounds when drawing into the padded content
19*c8dee2aaSAndroid Build Coastguard Worker  * is acceptable (e.g. color-only updates).
20*c8dee2aaSAndroid Build Coastguard Worker  */
21*c8dee2aaSAndroid Build Coastguard Worker class GrScissorState {
22*c8dee2aaSAndroid Build Coastguard Worker public:
23*c8dee2aaSAndroid Build Coastguard Worker     // The disabled scissor state for a render target of the given size.
GrScissorState(const SkISize & rtDims)24*c8dee2aaSAndroid Build Coastguard Worker     explicit GrScissorState(const SkISize& rtDims)
25*c8dee2aaSAndroid Build Coastguard Worker             : fRTSize(rtDims)
26*c8dee2aaSAndroid Build Coastguard Worker             , fRect(SkIRect::MakeSize(rtDims)) {}
27*c8dee2aaSAndroid Build Coastguard Worker 
setDisabled()28*c8dee2aaSAndroid Build Coastguard Worker     void setDisabled() { fRect = SkIRect::MakeSize(fRTSize); }
set(const SkIRect & rect)29*c8dee2aaSAndroid Build Coastguard Worker     bool set(const SkIRect& rect) {
30*c8dee2aaSAndroid Build Coastguard Worker         this->setDisabled();
31*c8dee2aaSAndroid Build Coastguard Worker         return this->intersect(rect);
32*c8dee2aaSAndroid Build Coastguard Worker     }
33*c8dee2aaSAndroid Build Coastguard Worker 
intersect(const SkIRect & rect)34*c8dee2aaSAndroid Build Coastguard Worker     [[nodiscard]] bool intersect(const SkIRect& rect) {
35*c8dee2aaSAndroid Build Coastguard Worker         if (!fRect.intersect(rect)) {
36*c8dee2aaSAndroid Build Coastguard Worker             fRect.setEmpty();
37*c8dee2aaSAndroid Build Coastguard Worker             return false;
38*c8dee2aaSAndroid Build Coastguard Worker         } else {
39*c8dee2aaSAndroid Build Coastguard Worker             return true;
40*c8dee2aaSAndroid Build Coastguard Worker         }
41*c8dee2aaSAndroid Build Coastguard Worker     }
42*c8dee2aaSAndroid Build Coastguard Worker 
43*c8dee2aaSAndroid Build Coastguard Worker     // If the scissor was configured for the backing store dimensions and it's acceptable to
44*c8dee2aaSAndroid Build Coastguard Worker     // draw outside the logical dimensions of the target, this will discard the scissor test if
45*c8dee2aaSAndroid Build Coastguard Worker     // the test wouldn't modify the logical dimensions.
relaxTest(const SkISize & logicalDimensions)46*c8dee2aaSAndroid Build Coastguard Worker     bool relaxTest(const SkISize& logicalDimensions) {
47*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(logicalDimensions.fWidth <= fRTSize.fWidth &&
48*c8dee2aaSAndroid Build Coastguard Worker                  logicalDimensions.fHeight <= fRTSize.fHeight);
49*c8dee2aaSAndroid Build Coastguard Worker         if (fRect.fLeft == 0 && fRect.fTop == 0 && fRect.fRight >= logicalDimensions.fWidth &&
50*c8dee2aaSAndroid Build Coastguard Worker             fRect.fBottom >= logicalDimensions.fHeight) {
51*c8dee2aaSAndroid Build Coastguard Worker             this->setDisabled();
52*c8dee2aaSAndroid Build Coastguard Worker             return true;
53*c8dee2aaSAndroid Build Coastguard Worker         } else {
54*c8dee2aaSAndroid Build Coastguard Worker             return false;
55*c8dee2aaSAndroid Build Coastguard Worker         }
56*c8dee2aaSAndroid Build Coastguard Worker     }
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     bool operator==(const GrScissorState& other) const {
59*c8dee2aaSAndroid Build Coastguard Worker         return fRTSize == other.fRTSize && fRect == other.fRect;
60*c8dee2aaSAndroid Build Coastguard Worker     }
61*c8dee2aaSAndroid Build Coastguard Worker     bool operator!=(const GrScissorState& other) const { return !(*this == other); }
62*c8dee2aaSAndroid Build Coastguard Worker 
enabled()63*c8dee2aaSAndroid Build Coastguard Worker     bool enabled() const {
64*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect));
65*c8dee2aaSAndroid Build Coastguard Worker         // This is equivalent to a strict contains check on SkIRect::MakeSize(rtSize) w/o creating
66*c8dee2aaSAndroid Build Coastguard Worker         // the render target bounding rectangle.
67*c8dee2aaSAndroid Build Coastguard Worker         return fRect.fLeft > 0 || fRect.fTop > 0 ||
68*c8dee2aaSAndroid Build Coastguard Worker                fRect.fRight < fRTSize.fWidth || fRect.fBottom < fRTSize.fHeight;
69*c8dee2aaSAndroid Build Coastguard Worker     }
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker     // Will always be equal to or contained in the rt bounds, or empty if scissor rectangles were
72*c8dee2aaSAndroid Build Coastguard Worker     // added that did not intersect with the render target or prior scissor.
rect()73*c8dee2aaSAndroid Build Coastguard Worker     const SkIRect& rect() const {
74*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect));
75*c8dee2aaSAndroid Build Coastguard Worker         return fRect;
76*c8dee2aaSAndroid Build Coastguard Worker     }
77*c8dee2aaSAndroid Build Coastguard Worker 
78*c8dee2aaSAndroid Build Coastguard Worker private:
79*c8dee2aaSAndroid Build Coastguard Worker     // The scissor is considered enabled if the rectangle does not cover the render target
80*c8dee2aaSAndroid Build Coastguard Worker     SkISize fRTSize;
81*c8dee2aaSAndroid Build Coastguard Worker     SkIRect fRect;
82*c8dee2aaSAndroid Build Coastguard Worker };
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker #endif
85