1 /* 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 11 #include "include/core/SkRect.h" 12 13 /** 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 */ 21 class GrScissorState { 22 public: 23 // The disabled scissor state for a render target of the given size. GrScissorState(const SkISize & rtDims)24 explicit GrScissorState(const SkISize& rtDims) 25 : fRTSize(rtDims) 26 , fRect(SkIRect::MakeSize(rtDims)) {} 27 #ifdef SK_ENABLE_STENCIL_CULLING_OHOS GrScissorState(const SkISize & rtDims,const SkIRect & stencilRect)28 GrScissorState(const SkISize& rtDims, const SkIRect& stencilRect) 29 : fRTSize(rtDims) 30 , fRect(SkIRect::MakeSize(rtDims)) 31 , fStencilRect(stencilRect) {} 32 #endif 33 setDisabled()34 void setDisabled() { fRect = SkIRect::MakeSize(fRTSize); } set(const SkIRect & rect)35 bool set(const SkIRect& rect) { 36 this->setDisabled(); 37 return this->intersect(rect); 38 } 39 intersect(const SkIRect & rect)40 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& rect) { 41 if (!fRect.intersect(rect)) { 42 fRect.setEmpty(); 43 return false; 44 } else { 45 return true; 46 } 47 } 48 49 // If the scissor was configured for the backing store dimensions and it's acceptable to 50 // draw outside the logical dimensions of the target, this will discard the scissor test if 51 // the test wouldn't modify the logical dimensions. relaxTest(const SkISize & logicalDimensions)52 bool relaxTest(const SkISize& logicalDimensions) { 53 SkASSERT(logicalDimensions.fWidth <= fRTSize.fWidth && 54 logicalDimensions.fHeight <= fRTSize.fHeight); 55 if (fRect.fLeft == 0 && fRect.fTop == 0 && fRect.fRight >= logicalDimensions.fWidth && 56 fRect.fBottom >= logicalDimensions.fHeight) { 57 this->setDisabled(); 58 return true; 59 } else { 60 return false; 61 } 62 } 63 64 bool operator==(const GrScissorState& other) const { 65 return fRTSize == other.fRTSize && fRect == other.fRect; 66 } 67 bool operator!=(const GrScissorState& other) const { return !(*this == other); } 68 enabled()69 bool enabled() const { 70 SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect)); 71 // This is equivalent to a strict contains check on SkIRect::MakeSize(rtSize) w/o creating 72 // the render target bounding rectangle. 73 return fRect.fLeft > 0 || fRect.fTop > 0 || 74 fRect.fRight < fRTSize.fWidth || fRect.fBottom < fRTSize.fHeight; 75 } 76 77 // Will always be equal to or contained in the rt bounds, or empty if scissor rectangles were 78 // added that did not intersect with the render target or prior scissor. rect()79 const SkIRect& rect() const { 80 SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect)); 81 return fRect; 82 } 83 #ifdef SK_ENABLE_STENCIL_CULLING_OHOS stencilRect()84 const SkIRect& stencilRect() const { 85 return fStencilRect; 86 } 87 #endif 88 89 private: 90 // The scissor is considered enabled if the rectangle does not cover the render target 91 SkISize fRTSize; 92 SkIRect fRect; 93 #ifdef SK_ENABLE_STENCIL_CULLING_OHOS 94 SkIRect fStencilRect; 95 #endif 96 }; 97 98 #endif 99