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