blob: cc1cea25781e5a43b9f1e2830517b863ed2dd38a [file] [log] [blame]
csmartdaltonbf4a8f92016-09-06 10:01:06 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrScissorState_DEFINED
9#define GrScissorState_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkRect.h"
Brian Salomond818ebf2018-07-02 14:08:49 +000012
Michael Ludwigd1d997e2020-06-04 15:52:44 -040013/**
14 * The scissor state is stored as the scissor rectangle and the backing store bounds of the render
15 * target that the scissor will apply to. If the render target is approximate fit and the padded
16 * content should not be modified, the clip should apply the render target context's logical bounds
17 * as part of the scissor (e.g. when stenciling). This puts the onus on the render target context
18 * to intentionally discard the scissor at its logical bounds when drawing into the padded content
19 * is acceptable (e.g. color-only updates).
20 */
csmartdaltonbf4a8f92016-09-06 10:01:06 -070021class GrScissorState {
22public:
Michael Ludwigd1d997e2020-06-04 15:52:44 -040023 // The disabled scissor state for a render target of the given size.
24 explicit GrScissorState(const SkISize& rtDims)
25 : fRTSize(rtDims)
26 , fRect(SkIRect::MakeSize(rtDims)) {}
27
28 void setDisabled() { fRect = SkIRect::MakeSize(fRTSize); }
29 bool set(const SkIRect& rect) {
30 this->setDisabled();
31 return this->intersect(rect);
32 }
33
csmartdaltonbf4a8f92016-09-06 10:01:06 -070034 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& rect) {
Michael Ludwigd1d997e2020-06-04 15:52:44 -040035 if (!fRect.intersect(rect)) {
36 fRect.setEmpty();
37 return false;
38 } else {
csmartdaltonbf4a8f92016-09-06 10:01:06 -070039 return true;
40 }
csmartdaltonbf4a8f92016-09-06 10:01:06 -070041 }
Michael Ludwigd1d997e2020-06-04 15:52:44 -040042
43 // If the scissor was configured for the backing store dimensions and it's acceptable to
44 // draw outside the logical dimensions of the target, this will discard the scissor test if
45 // the test wouldn't modify the logical dimensions.
46 bool relaxTest(const SkISize& logicalDimensions) {
47 SkASSERT(logicalDimensions.fWidth <= fRTSize.fWidth &&
48 logicalDimensions.fHeight <= fRTSize.fHeight);
49 if (fRect.fLeft == 0 && fRect.fTop == 0 && fRect.fRight >= logicalDimensions.fWidth &&
50 fRect.fBottom >= logicalDimensions.fHeight) {
51 this->setDisabled();
52 return true;
53 } else {
54 return false;
55 }
56 }
57
csmartdaltonbf4a8f92016-09-06 10:01:06 -070058 bool operator==(const GrScissorState& other) const {
Michael Ludwigd1d997e2020-06-04 15:52:44 -040059 return fRTSize == other.fRTSize && fRect == other.fRect;
csmartdaltonbf4a8f92016-09-06 10:01:06 -070060 }
61 bool operator!=(const GrScissorState& other) const { return !(*this == other); }
62
Michael Ludwigd1d997e2020-06-04 15:52:44 -040063 bool enabled() const {
64 SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect));
65 // This is equivalent to a strict contains check on SkIRect::MakeSize(rtSize) w/o creating
66 // the render target bounding rectangle.
67 return fRect.fLeft > 0 || fRect.fTop > 0 ||
68 fRect.fRight < fRTSize.fWidth || fRect.fBottom < fRTSize.fHeight;
69 }
70
71 // Will always be equal to or contained in the rt bounds, or empty if scissor rectangles were
72 // added that did not intersect with the render target or prior scissor.
Robert Phillipsff2f3802019-11-18 16:36:54 -050073 const SkIRect& rect() const {
Michael Ludwigd1d997e2020-06-04 15:52:44 -040074 SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect));
Robert Phillipsff2f3802019-11-18 16:36:54 -050075 return fRect;
76 }
csmartdaltonbf4a8f92016-09-06 10:01:06 -070077
78private:
Michael Ludwigd1d997e2020-06-04 15:52:44 -040079 // The scissor is considered enabled if the rectangle does not cover the render target
80 SkISize fRTSize;
csmartdaltonbf4a8f92016-09-06 10:01:06 -070081 SkIRect fRect;
82};
83
84#endif