blob: 13f9e653670fa511f1588b629b3d8d5e2cfdf62f [file] [log] [blame]
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrScissorState_DEFINED
#define GrScissorState_DEFINED
#include "include/core/SkRect.h"
/**
* The scissor state is stored as the scissor rectangle and the backing store bounds of the render
* target that the scissor will apply to. If the render target is approximate fit and the padded
* content should not be modified, the clip should apply the render target context's logical bounds
* as part of the scissor (e.g. when stenciling). This puts the onus on the render target context
* to intentionally discard the scissor at its logical bounds when drawing into the padded content
* is acceptable (e.g. color-only updates).
*/
class GrScissorState {
public:
// The disabled scissor state for a render target of the given size.
explicit GrScissorState(const SkISize& rtDims)
: fRTSize(rtDims)
, fRect(SkIRect::MakeSize(rtDims)) {}
void setDisabled() { fRect = SkIRect::MakeSize(fRTSize); }
bool set(const SkIRect& rect) {
this->setDisabled();
return this->intersect(rect);
}
[[nodiscard]] bool intersect(const SkIRect& rect) {
if (!fRect.intersect(rect)) {
fRect.setEmpty();
return false;
} else {
return true;
}
}
// If the scissor was configured for the backing store dimensions and it's acceptable to
// draw outside the logical dimensions of the target, this will discard the scissor test if
// the test wouldn't modify the logical dimensions.
bool relaxTest(const SkISize& logicalDimensions) {
SkASSERT(logicalDimensions.fWidth <= fRTSize.fWidth &&
logicalDimensions.fHeight <= fRTSize.fHeight);
if (fRect.fLeft == 0 && fRect.fTop == 0 && fRect.fRight >= logicalDimensions.fWidth &&
fRect.fBottom >= logicalDimensions.fHeight) {
this->setDisabled();
return true;
} else {
return false;
}
}
bool operator==(const GrScissorState& other) const {
return fRTSize == other.fRTSize && fRect == other.fRect;
}
bool operator!=(const GrScissorState& other) const { return !(*this == other); }
bool enabled() const {
SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect));
// This is equivalent to a strict contains check on SkIRect::MakeSize(rtSize) w/o creating
// the render target bounding rectangle.
return fRect.fLeft > 0 || fRect.fTop > 0 ||
fRect.fRight < fRTSize.fWidth || fRect.fBottom < fRTSize.fHeight;
}
// Will always be equal to or contained in the rt bounds, or empty if scissor rectangles were
// added that did not intersect with the render target or prior scissor.
const SkIRect& rect() const {
SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect));
return fRect;
}
private:
// The scissor is considered enabled if the rectangle does not cover the render target
SkISize fRTSize;
SkIRect fRect;
};
#endif