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 setDisabled()28 void setDisabled() { fRect = SkIRect::MakeSize(fRTSize); } set(const SkIRect & rect)29 bool set(const SkIRect& rect) { 30 this->setDisabled(); 31 return this->intersect(rect); 32 } 33 intersect(const SkIRect & rect)34 bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& rect) { 35 if (!fRect.intersect(rect)) { 36 fRect.setEmpty(); 37 return false; 38 } else { 39 return true; 40 } 41 } 42 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. relaxTest(const SkISize & logicalDimensions)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 58 bool operator==(const GrScissorState& other) const { 59 return fRTSize == other.fRTSize && fRect == other.fRect; 60 } 61 bool operator!=(const GrScissorState& other) const { return !(*this == other); } 62 enabled()63 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. rect()73 const SkIRect& rect() const { 74 SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect)); 75 return fRect; 76 } 77 78 private: 79 // The scissor is considered enabled if the rectangle does not cover the render target 80 SkISize fRTSize; 81 SkIRect fRect; 82 }; 83 84 #endif 85