Use constexpr constructors of GrStencilSettings rather than hacky macro system.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1933053002

Review-Url: https://codereview.chromium.org/1933053002
This commit is contained in:
bsalomon 2016-04-29 08:44:16 -07:00 committed by Commit bot
parent b4d46f03db
commit 3de75da6d2
11 changed files with 249 additions and 296 deletions

View File

@ -675,13 +675,13 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
// draw directly into the result with the stencil set to make the pixels affected
// by the clip shape be non-zero.
GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0xffff,
0xffff)
static constexpr GrStencilSettings kStencilInElement(
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0xffff,
0xffff);
if (!stencil_element(dc.get(), &maskSpaceIBounds, kStencilInElement,
translate, element)) {
texture->resourcePriv().removeUniqueKey();
@ -689,13 +689,13 @@ GrTexture* GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
}
// Draw to the exterior pixels (those with a zero stencil value).
GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement,
kZero_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
static constexpr GrStencilSettings kDrawOutsideElement(
kZero_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, kDrawOutsideElement,
op, !invert, false,
translate,
@ -830,22 +830,22 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
// draw the element to the client stencil bits if necessary
if (!canDrawDirectToClip) {
GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil,
kIncClamp_StencilOp,
kIncClamp_StencilOp,
kAlways_StencilFunc,
0xffff,
0x0000,
0xffff);
static constexpr GrStencilSettings kDrawToStencil(
kIncClamp_StencilOp,
kIncClamp_StencilOp,
kAlways_StencilFunc,
0xffff,
0x0000,
0xffff);
if (Element::kRect_Type == element->getType()) {
*pipelineBuilder.stencil() = gDrawToStencil;
*pipelineBuilder.stencil() = kDrawToStencil;
draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE, viewMatrix,
element->getRect());
} else {
if (!clipPath.isEmpty()) {
if (canRenderDirectToStencil) {
*pipelineBuilder.stencil() = gDrawToStencil;
*pipelineBuilder.stencil() = kDrawToStencil;
GrPathRenderer::DrawPathArgs args;
args.fTarget = fDrawTarget;
@ -911,7 +911,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
// mapping of clip-respecting stencil funcs to normal stencil funcs
// mapping depends on whether stencil-clipping is in effect.
static const GrStencilFunc
gSpecialToBasicStencilFunc[2][kClipStencilFuncCount] = {
gSpecialToBasicStencilFunc[2][kClipStencilFuncCnt] = {
{// Stencil-Clipping is DISABLED, we are effectively always inside the clip
// In the Clip Funcs
kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc
@ -944,22 +944,6 @@ static const GrStencilFunc
}
};
namespace {
// Sets the settings to clip against the stencil buffer clip while ignoring the
// client bits.
const GrStencilSettings& basic_apply_stencil_clip_settings() {
// stencil settings to use when clip is in stencil
GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
kKeep_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
0x0000,
0x0000,
0x0000);
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
}
}
void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipelineBuilder,
GrPipelineBuilder::AutoRestoreStencil* ars) {
// We make two copies of the StencilSettings here (except in the early
@ -975,7 +959,14 @@ void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipel
// enable it in order to respect a stencil clip.
if (pipelineBuilder.getStencil().isDisabled()) {
if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) {
settings = basic_apply_stencil_clip_settings();
static constexpr GrStencilSettings kBasicApplyClipSettings(
kKeep_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
0x0000,
0x0000,
0x0000);
settings = kBasicApplyClipSettings;
} else {
return;
}
@ -1021,11 +1012,11 @@ void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
uint16_t funcMask = settings->funcMask(face);
uint16_t funcRef = settings->funcRef(face);
SkASSERT((unsigned) func < kStencilFuncCount);
SkASSERT((unsigned) func < kStencilFuncCnt);
writeMask &= userBits;
if (func >= kBasicStencilFuncCount) {
if (func >= kBasicStencilFuncCnt) {
int respectClip = kRespectClip_StencilClipMode == mode;
if (respectClip) {
switch (func) {
@ -1052,8 +1043,8 @@ void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
}
const GrStencilFunc* table =
gSpecialToBasicStencilFunc[respectClip];
func = table[func - kBasicStencilFuncCount];
SkASSERT(func >= 0 && func < kBasicStencilFuncCount);
func = table[func - kBasicStencilFuncCnt];
SkASSERT(func >= 0 && func < kBasicStencilFuncCnt);
} else {
funcMask &= userBits;
funcRef &= userBits;

View File

@ -269,36 +269,31 @@ void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
this->recordBatch(batch);
}
static const GrStencilSettings& winding_path_stencil_settings() {
GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
kIncClamp_StencilOp,
kIncClamp_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xFFFF, 0xFFFF, 0xFFFF);
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
}
static const GrStencilSettings& even_odd_path_stencil_settings() {
GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
kInvert_StencilOp,
kInvert_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xFFFF, 0xFFFF, 0xFFFF);
return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
}
void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,
const GrStencilAttachment* sb,
GrStencilSettings* outStencilSettings) {
static constexpr GrStencilSettings kWindingStencilSettings(
kIncClamp_StencilOp,
kIncClamp_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xFFFF, 0xFFFF, 0xFFFF
);
static constexpr GrStencilSettings kEvenODdStencilSettings(
kInvert_StencilOp,
kInvert_StencilOp,
kAlwaysIfInClip_StencilFunc,
0xFFFF, 0xFFFF, 0xFFFF
);
switch (fill) {
default:
SkFAIL("Unexpected path fill.");
case GrPathRendering::kWinding_FillType:
*outStencilSettings = winding_path_stencil_settings();
*outStencilSettings = kWindingStencilSettings;
break;
case GrPathRendering::kEvenOdd_FillType:
*outStencilSettings = even_odd_path_stencil_settings();
*outStencilSettings = kEvenODdStencilSettings;
break;
}
fClipMaskManager->adjustPathStencilParams(sb, outStencilSettings);

View File

@ -265,13 +265,13 @@ private:
* kStencilOnly in onGetStencilSupport().
*/
virtual void onStencilPath(const StencilPathArgs& args) {
GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil,
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0xffff,
0xffff);
static constexpr GrStencilSettings kIncrementStencil(
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0xffff,
0xffff);
args.fPipelineBuilder->setStencil(kIncrementStencil);
args.fPipelineBuilder->setDisableColorXPFactory();
DrawPathArgs drawArgs;

View File

@ -22,7 +22,7 @@
// Replace
// set the ref to be the clip bit, but mask it out for the test
GR_STATIC_CONST_SAME_STENCIL(gUserToClipReplace,
static constexpr GrStencilSettings gUserToClipReplace(
kReplace_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
@ -30,7 +30,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipReplace,
0x0000, // set clip bit
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipReplace,
static constexpr GrStencilSettings gInvUserToClipReplace(
kReplace_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
@ -40,7 +40,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipReplace,
///////
// Intersect
GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect,
static constexpr GrStencilSettings gUserToClipIsect(
kReplace_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
@ -48,7 +48,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipIsect,
0x0000, // set clip bit
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect,
static constexpr GrStencilSettings gInvUserToClipIsect(
kReplace_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
@ -58,7 +58,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipIsect,
///////
// Difference
GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff,
static constexpr GrStencilSettings gUserToClipDiff(
kReplace_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
@ -66,7 +66,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipDiff,
0x0000, // set clip bit
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff,
static constexpr GrStencilSettings gInvUserToClipDiff(
kReplace_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
@ -78,7 +78,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipDiff,
// Union
// first pass makes all the passing cases >= just clip bit set.
GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0,
static constexpr GrStencilSettings gUserToClipUnionPass0(
kReplace_StencilOp,
kKeep_StencilOp,
kLEqual_StencilFunc,
@ -87,7 +87,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass0,
0xffff);
// second pass allows anything greater than just clip bit set to pass
GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1,
static constexpr GrStencilSettings gUserToClipUnionPass1(
kReplace_StencilOp,
kZero_StencilOp,
kLEqual_StencilFunc,
@ -97,7 +97,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipUnionPass1,
// first pass finds zeros in the user bits and if found sets
// the clip bit to 1
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass0,
static constexpr GrStencilSettings gInvUserToClipUnionPass0(
kReplace_StencilOp,
kKeep_StencilOp,
kEqual_StencilFunc,
@ -107,7 +107,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass0,
);
// second pass zeros the user bits
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1,
static constexpr GrStencilSettings gInvUserToClipUnionPass1(
kZero_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
@ -118,7 +118,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipUnionPass1,
///////
// Xor
GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
static constexpr GrStencilSettings gUserToClipXorPass0(
kInvert_StencilOp,
kKeep_StencilOp,
kEqual_StencilFunc,
@ -126,7 +126,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass0,
0x0000,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
static constexpr GrStencilSettings gUserToClipXorPass1(
kReplace_StencilOp,
kZero_StencilOp,
kGreater_StencilFunc,
@ -134,7 +134,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipXorPass1,
0x0000, // set clip bit
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
static constexpr GrStencilSettings gInvUserToClipXorPass0(
kInvert_StencilOp,
kKeep_StencilOp,
kEqual_StencilFunc,
@ -142,7 +142,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass0,
0x0000,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1,
static constexpr GrStencilSettings gInvUserToClipXorPass1(
kReplace_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
@ -152,7 +152,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipXorPass1,
///////
// Reverse Diff
GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass0,
static constexpr GrStencilSettings gUserToClipRDiffPass0(
kInvert_StencilOp,
kZero_StencilOp,
kLess_StencilFunc,
@ -160,7 +160,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass0,
0x0000, // set clip bit
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass1,
static constexpr GrStencilSettings gUserToClipRDiffPass1(
kReplace_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
@ -170,7 +170,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUserToClipRDiffPass1,
// We are looking for stencil values that are all zero. The first pass sets the
// clip bit if the stencil is all zeros. The second pass clears the user bits.
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass0,
static constexpr GrStencilSettings gInvUserToClipRDiffPass0(
kInvert_StencilOp,
kZero_StencilOp,
kEqual_StencilFunc,
@ -179,7 +179,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass0,
0x0000 // set clip bit
);
GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass1,
static constexpr GrStencilSettings gInvUserToClipRDiffPass1(
kZero_StencilOp,
kZero_StencilOp,
kAlways_StencilFunc,
@ -197,7 +197,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvUserToClipRDiffPass1,
// this one only works if used right after stencil clip was cleared.
// Our clip mask creation code doesn't allow midstream replace ops.
GR_STATIC_CONST_SAME_STENCIL(gReplaceClip,
static constexpr GrStencilSettings gReplaceClip(
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
@ -206,7 +206,7 @@ GR_STATIC_CONST_SAME_STENCIL(gReplaceClip,
0x0000 // set clipBit
);
GR_STATIC_CONST_SAME_STENCIL(gUnionClip,
static constexpr GrStencilSettings gUnionClip(
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
@ -215,7 +215,7 @@ GR_STATIC_CONST_SAME_STENCIL(gUnionClip,
0x0000 // set clip bit
);
GR_STATIC_CONST_SAME_STENCIL(gXorClip,
static constexpr GrStencilSettings gXorClip(
kInvert_StencilOp,
kInvert_StencilOp,
kAlways_StencilFunc,
@ -224,7 +224,7 @@ GR_STATIC_CONST_SAME_STENCIL(gXorClip,
0x0000 // set clip bit
);
GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
static constexpr GrStencilSettings gDiffClip(
kZero_StencilOp,
kZero_StencilOp,
kAlways_StencilFunc,

View File

@ -64,13 +64,14 @@ enum GrStencilFunc {
kLEqualIfInClip_StencilFunc,
kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0
// counts
kStencilFuncCount,
kClipStencilFuncCount = kNonZeroIfInClip_StencilFunc -
kAlwaysIfInClip_StencilFunc + 1,
kBasicStencilFuncCount = kStencilFuncCount - kClipStencilFuncCount
kLast_StencilFunc = kNonZeroIfInClip_StencilFunc
};
static const int kStencilFuncCnt = kLast_StencilFunc + 1;
static const int kClipStencilFuncCnt =
kNonZeroIfInClip_StencilFunc - kAlwaysIfInClip_StencilFunc + 1;
static const int kBasicStencilFuncCnt = kStencilFuncCnt - kClipStencilFuncCnt;
/**
* Operations to perform based on whether stencil test passed failed.
*/
@ -83,98 +84,60 @@ enum GrStencilOp {
kDecClamp_StencilOp, // decrement and clamp at 0
kZero_StencilOp, // zero stencil bits
kInvert_StencilOp, // invert stencil bits
kStencilOpCount
kLast_StencilOp = kInvert_StencilOp
};
enum GrStencilFlags {
kIsDisabled_StencilFlag = 0x1,
kNotDisabled_StencilFlag = 0x2,
kDoesWrite_StencilFlag = 0x4,
kDoesNotWrite_StencilFlag = 0x8,
};
/**
* GrStencilState needs to be a class with accessors and setters so that it
* can maintain flags related to its current state. However, we also want to
* be able to declare pre-made stencil settings at compile time (without
* inserting static initializer code). So all the data members are in this
* struct. A macro defined after the class can be used to jam an instance of
* this struct that is created from an initializer list into a
* GrStencilSettings. (We hang our heads in shame.)
*/
struct GrStencilSettingsStruct {
uint8_t fPassOps[2]; // op to perform when faces pass (GrStencilOp)
uint8_t fFailOps[2]; // op to perform when faces fail (GrStencilOp)
uint8_t fFuncs[2]; // test function for faces (GrStencilFunc)
uint8_t fPad0;
uint8_t fPad1;
uint16_t fFuncMasks[2]; // mask for face tests
uint16_t fFuncRefs[2]; // reference values for face tests
uint16_t fWriteMasks[2]; // stencil write masks
mutable uint32_t fFlags;
};
// We rely on this being packed and aligned (memcmp'ed and memcpy'ed)
GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) % 4 == 0);
GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) ==
4*sizeof(uint8_t) + // ops
2*sizeof(uint8_t) + // funcs
2*sizeof(uint8_t) + // pads
2*sizeof(uint16_t) + // func masks
2*sizeof(uint16_t) + // ref values
2*sizeof(uint16_t) + // write masks
sizeof(uint32_t)); // flags
// This macro is used to compute the GrStencilSettingsStructs flags
// associated to disabling. It is used both to define constant structure
// initializers and inside GrStencilSettings::isDisabled()
//
#define GR_STENCIL_SETTINGS_IS_DISABLED( \
FRONT_PASS_OP, BACK_PASS_OP, \
FRONT_FAIL_OP, BACK_FAIL_OP, \
FRONT_FUNC, BACK_FUNC) \
((FRONT_PASS_OP) == kKeep_StencilOp && \
(BACK_PASS_OP) == kKeep_StencilOp && \
(FRONT_FAIL_OP) == kKeep_StencilOp && \
(BACK_FAIL_OP) == kKeep_StencilOp && \
(FRONT_FUNC) == kAlways_StencilFunc && \
(BACK_FUNC) == kAlways_StencilFunc)
#define GR_STENCIL_SETTINGS_DOES_WRITE( \
FRONT_PASS_OP, BACK_PASS_OP, \
FRONT_FAIL_OP, BACK_FAIL_OP, \
FRONT_FUNC, BACK_FUNC) \
(!(((FRONT_FUNC) == kNever_StencilFunc || \
(FRONT_PASS_OP) == kKeep_StencilOp) && \
((BACK_FUNC) == kNever_StencilFunc || \
(BACK_PASS_OP) == kKeep_StencilOp) && \
((FRONT_FUNC) == kAlways_StencilFunc || \
(FRONT_FAIL_OP) == kKeep_StencilOp) && \
((BACK_FUNC) == kAlways_StencilFunc || \
(BACK_FAIL_OP) == kKeep_StencilOp)))
#define GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
FRONT_PASS_OP, BACK_PASS_OP, \
FRONT_FAIL_OP, BACK_FAIL_OP, \
FRONT_FUNC, BACK_FUNC) \
((GR_STENCIL_SETTINGS_IS_DISABLED(FRONT_PASS_OP,BACK_PASS_OP, \
FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \
kIsDisabled_StencilFlag : kNotDisabled_StencilFlag) | \
(GR_STENCIL_SETTINGS_DOES_WRITE(FRONT_PASS_OP,BACK_PASS_OP, \
FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \
kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag))
static const int kStencilOpCnt = kLast_StencilOp + 1;
/**
* Class representing stencil state.
*/
class GrStencilSettings : private GrStencilSettingsStruct {
class GrStencilSettings {
public:
enum Face {
kFront_Face = 0,
kBack_Face = 1,
};
constexpr GrStencilSettings(GrStencilOp passOp,
GrStencilOp failOp,
GrStencilFunc func,
unsigned short funcMask,
unsigned short funcRef,
unsigned short writeMask)
: fPassOps{(uint8_t)passOp, (uint8_t)passOp}
, fFailOps{(uint8_t)failOp, (uint8_t)failOp}
, fFuncs{(uint8_t)func, (uint8_t)func}
, fPad0(0)
, fPad1(0)
, fFuncMasks{funcMask, funcMask}
, fFuncRefs{funcRef, funcRef}
, fWriteMasks{writeMask, writeMask}
, fFlags(ComputeFlags(passOp, passOp,
failOp, failOp,
func, func,
writeMask, writeMask)) {
}
constexpr GrStencilSettings(GrStencilOp frontPassOp, GrStencilOp backPassOp,
GrStencilOp frontFailOp, GrStencilOp backFailOp,
GrStencilFunc frontFunc, GrStencilFunc backFunc,
uint16_t frontFuncMask, uint16_t backFuncMask,
uint16_t frontFuncRef, uint16_t backFuncRef,
uint16_t frontWriteMask, uint16_t backWriteMask)
: fPassOps{(uint8_t)frontPassOp, (uint8_t)backPassOp}
, fFailOps{(uint8_t)frontFailOp, (uint8_t)backFailOp}
, fFuncs{(uint8_t)frontFunc, (uint8_t)backFunc}
, fPad0(0)
, fPad1(0)
, fFuncMasks{frontFuncMask, backFuncMask}
, fFuncRefs{frontFuncRef, backFuncRef}
, fWriteMasks{frontWriteMask, backWriteMask}
, fFlags(ComputeFlags(frontPassOp, backPassOp,
frontFailOp, backFailOp,
frontFunc, backFunc,
frontWriteMask, backWriteMask)) {
}
GrStencilSettings() {
fPad0 = fPad1 = 0;
this->setDisabled();
@ -204,21 +167,6 @@ public:
fFlags = 0;
}
void setSame(GrStencilOp passOp,
GrStencilOp failOp,
GrStencilFunc func,
unsigned short funcMask,
unsigned short funcRef,
unsigned short writeMask) {
fPassOps[kFront_Face] = fPassOps[kBack_Face] = passOp;
fFailOps[kFront_Face] = fFailOps[kBack_Face] = failOp;
fFuncs[kFront_Face] = fFuncs[kBack_Face] = func;
fFuncMasks[kFront_Face] = fFuncMasks[kBack_Face] = funcMask;
fFuncRefs[kFront_Face] = fFuncRefs[kBack_Face] = funcRef;
fWriteMasks[kFront_Face] = fWriteMasks[kBack_Face] = writeMask;
fFlags = 0;
}
void setDisabled() {
memset(this, 0, sizeof(*this));
GR_STATIC_ASSERT(0 == kKeep_StencilOp);
@ -253,10 +201,7 @@ public:
if (fFlags & kNotDisabled_StencilFlag) {
return false;
}
bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED(
fPassOps[kFront_Face], fPassOps[kBack_Face],
fFailOps[kFront_Face], fFailOps[kBack_Face],
fFuncs[kFront_Face], fFuncs[kBack_Face]);
bool disabled = this->computeIsDisabled();
fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
return disabled;
}
@ -268,27 +213,22 @@ public:
if (fFlags & kDoesNotWrite_StencilFlag) {
return false;
}
bool writes = GR_STENCIL_SETTINGS_DOES_WRITE(
fPassOps[kFront_Face], fPassOps[kBack_Face],
fFailOps[kFront_Face], fFailOps[kBack_Face],
fFuncs[kFront_Face], fFuncs[kBack_Face]);
bool writes = this->computeDoesWrite();
fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
return writes;
}
void invalidate() {
// write an illegal value to the first member
fPassOps[0] = kStencilOpCount;
fPassOps[0] = kStencilOpCnt;
fFlags = 0;
}
bool isValid() const {
return fPassOps[0] < kStencilOpCount;
}
bool isValid() const { return fPassOps[0] < kStencilOpCnt; }
void genKey(GrProcessorKeyBuilder* b) const;
bool operator == (const GrStencilSettings& s) const {
bool operator==(const GrStencilSettings& s) const {
static const size_t gCompareSize = sizeof(GrStencilSettings) -
sizeof(fFlags);
SkASSERT((const char*)&fFlags + sizeof(fFlags) ==
@ -299,11 +239,11 @@ public:
return 0 == memcmp(this, &s, gCompareSize);
}
bool operator != (const GrStencilSettings& s) const {
bool operator!=(const GrStencilSettings& s) const {
return !(*this == s);
}
GrStencilSettings& operator =(const GrStencilSettings& s) {
GrStencilSettings& operator=(const GrStencilSettings& s) {
memcpy(this, &s, sizeof(GrStencilSettings));
return *this;
}
@ -345,58 +285,85 @@ private:
bool invertedFill,
int* numPasses,
GrStencilSettings settings[kMaxStencilClipPasses]);
};
GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
constexpr static bool IsDisabled(GrStencilOp frontPassOp, GrStencilOp backPassOp,
GrStencilOp frontFailOp, GrStencilOp backFailOp,
GrStencilFunc frontFunc, GrStencilFunc backFunc) {
return (((frontPassOp == kKeep_StencilOp && frontFailOp == kKeep_StencilOp)) &&
((backPassOp == kKeep_StencilOp && backFailOp == kKeep_StencilOp)) &&
frontFunc == kAlways_StencilFunc &&
backFunc == kAlways_StencilFunc);
}
#define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \
FRONT_PASS_OP, BACK_PASS_OP, \
FRONT_FAIL_OP, BACK_FAIL_OP, \
FRONT_FUNC, BACK_FUNC, \
FRONT_MASK, BACK_MASK, \
FRONT_REF, BACK_REF, \
FRONT_WRITE_MASK, BACK_WRITE_MASK) \
static const GrStencilSettingsStruct STRUCT_NAME = { \
{(FRONT_PASS_OP), (BACK_PASS_OP) }, \
{(FRONT_FAIL_OP), (BACK_FAIL_OP) }, \
{(FRONT_FUNC), (BACK_FUNC) }, \
(0), (0), \
{(FRONT_MASK), (BACK_MASK) }, \
{(FRONT_REF), (BACK_REF) }, \
{(FRONT_WRITE_MASK), (BACK_WRITE_MASK)}, \
GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP, \
FRONT_FUNC, BACK_FUNC) \
constexpr static bool DoesWrite(GrStencilOp frontPassOp, GrStencilOp backPassOp,
GrStencilOp frontFailOp, GrStencilOp backFailOp,
GrStencilFunc frontFunc, GrStencilFunc backFunc,
uint16_t frontWriteMask, uint16_t backWriteMask) {
return (0 != (frontWriteMask | backWriteMask)) &&
// Can we write due to a front face passing the stencil test?
((frontFunc != kNever_StencilFunc && frontPassOp != kKeep_StencilOp) ||
// Can we write due to a back face passing the stencil test?
(backFunc != kNever_StencilFunc && backPassOp != kKeep_StencilOp) ||
// Can we write due to a front face failing the stencil test?
(frontFunc != kAlways_StencilFunc && frontFailOp != kKeep_StencilOp) ||
// Can we write due to a back face failing the stencil test?
(backFunc != kAlways_StencilFunc && backFailOp != kKeep_StencilOp));
}
constexpr static uint32_t ComputeFlags(GrStencilOp frontPassOp, GrStencilOp backPassOp,
GrStencilOp frontFailOp, GrStencilOp backFailOp,
GrStencilFunc frontFunc, GrStencilFunc backFunc,
uint16_t frontWriteMask, uint16_t backWriteMask) {
return (IsDisabled(frontPassOp, backPassOp, frontFailOp, backFailOp,
frontFunc, backFunc)
? kIsDisabled_StencilFlag
: kNotDisabled_StencilFlag) |
(DoesWrite(frontPassOp, backPassOp, frontFailOp, backFailOp,
frontFunc, backFunc, frontWriteMask, backWriteMask)
? kDoesWrite_StencilFlag
: kDoesNotWrite_StencilFlag);
}
bool computeIsDisabled() const {
return IsDisabled((GrStencilOp) fPassOps[kFront_Face], (GrStencilOp) fPassOps[kBack_Face],
(GrStencilOp) fFailOps[kFront_Face], (GrStencilOp) fFailOps[kBack_Face],
(GrStencilFunc) fFuncs[kFront_Face], (GrStencilFunc) fFuncs[kBack_Face]);
}
bool computeDoesWrite() const {
return DoesWrite((GrStencilOp)fPassOps[kFront_Face], (GrStencilOp)fPassOps[kBack_Face],
(GrStencilOp)fFailOps[kFront_Face], (GrStencilOp)fFailOps[kBack_Face],
(GrStencilFunc)fFuncs[kFront_Face], (GrStencilFunc)fFuncs[kBack_Face],
fWriteMasks[kFront_Face], fWriteMasks[kBack_Face]);
}
enum GrStencilFlags {
kIsDisabled_StencilFlag = 0x1,
kNotDisabled_StencilFlag = 0x2,
kDoesWrite_StencilFlag = 0x4,
kDoesNotWrite_StencilFlag = 0x8,
};
#define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR) \
reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR)
uint8_t fPassOps[2]; // op to perform when faces pass (GrStencilOp)
uint8_t fFailOps[2]; // op to perform when faces fail (GrStencilOp)
uint8_t fFuncs[2]; // test function for faces (GrStencilFunc)
uint8_t fPad0;
uint8_t fPad1;
uint16_t fFuncMasks[2]; // mask for face tests
uint16_t fFuncRefs[2]; // reference values for face tests
uint16_t fWriteMasks[2]; // stencil write masks
mutable uint32_t fFlags;
#define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME, \
PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP), \
(FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), \
(WRITE_MASK),(WRITE_MASK))
};
#define GR_STATIC_CONST_STENCIL(NAME, \
FRONT_PASS_OP, BACK_PASS_OP, \
FRONT_FAIL_OP, BACK_FAIL_OP, \
FRONT_FUNC, BACK_FUNC, \
FRONT_MASK, BACK_MASK, \
FRONT_REF, BACK_REF, \
FRONT_WRITE_MASK, BACK_WRITE_MASK) \
GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT, \
(FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP), \
(FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK), \
(FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK)) \
static const GrStencilSettings& NAME = \
*GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT));
#define GR_STATIC_CONST_SAME_STENCIL(NAME, \
PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP), \
(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK), \
(WRITE_MASK))
// We rely on this being packed and aligned (memcmp'ed and memcpy'ed)
GR_STATIC_ASSERT(sizeof(GrStencilSettings) % 4 == 0);
GR_STATIC_ASSERT(sizeof(GrStencilSettings) ==
4*sizeof(uint8_t) + // ops
2*sizeof(uint8_t) + // funcs
2*sizeof(uint8_t) + // pads
2*sizeof(uint16_t) + // func masks
2*sizeof(uint16_t) + // ref values
2*sizeof(uint16_t) + // write masks
sizeof(uint32_t)); // flags
#endif

View File

@ -35,7 +35,7 @@ GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
////// Even/Odd
GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
static constexpr GrStencilSettings gEOStencilPass(
kInvert_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
@ -44,7 +44,7 @@ GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
0xffff);
// ok not to check clip b/c stencil pass only wrote inside clip
GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
static constexpr GrStencilSettings gEOColorPass(
kZero_StencilOp,
kZero_StencilOp,
kNotEqual_StencilFunc,
@ -53,7 +53,7 @@ GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
0xffff);
// have to check clip b/c outside clip will always be zero.
GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
static constexpr GrStencilSettings gInvEOColorPass(
kZero_StencilOp,
kZero_StencilOp,
kEqualIfInClip_StencilFunc,
@ -67,7 +67,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
// when we don't have wrap incr and decr we use the stencil test to simulate
// them.
GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
static constexpr GrStencilSettings gWindStencilSeparateWithWrap(
kIncWrap_StencilOp, kDecWrap_StencilOp,
kKeep_StencilOp, kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
@ -79,7 +79,7 @@ GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
// if dec'ing zero invert to make all ones.
// we can't avoid touching the stencil on both passing and
// failing, so we can't resctrict ourselves to the clip.
GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
static constexpr GrStencilSettings gWindStencilSeparateNoWrap(
kInvert_StencilOp, kInvert_StencilOp,
kIncClamp_StencilOp, kDecClamp_StencilOp,
kEqual_StencilFunc, kEqual_StencilFunc,
@ -91,7 +91,7 @@ GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
// stencil. First we draw the front faces and inc, then we draw the back faces
// and dec. These are same as the above two split into the incrementing and
// decrementing passes.
GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
static constexpr GrStencilSettings gWindSingleStencilWithWrapInc(
kIncWrap_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
@ -99,7 +99,7 @@ GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
0xffff,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
static constexpr GrStencilSettings gWindSingleStencilWithWrapDec(
kDecWrap_StencilOp,
kKeep_StencilOp,
kAlwaysIfInClip_StencilFunc,
@ -107,7 +107,7 @@ GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
0xffff,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
static constexpr GrStencilSettings gWindSingleStencilNoWrapInc(
kInvert_StencilOp,
kIncClamp_StencilOp,
kEqual_StencilFunc,
@ -115,7 +115,7 @@ GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
0xffff,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
static constexpr GrStencilSettings gWindSingleStencilNoWrapDec(
kInvert_StencilOp,
kDecClamp_StencilOp,
kEqual_StencilFunc,
@ -125,7 +125,7 @@ GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
// Color passes are the same whether we use the two-sided stencil or two passes
GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
static constexpr GrStencilSettings gWindColorPass(
kZero_StencilOp,
kZero_StencilOp,
kNonZeroIfInClip_StencilFunc,
@ -133,7 +133,7 @@ GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
0x0000,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
static constexpr GrStencilSettings gInvWindColorPass(
kZero_StencilOp,
kZero_StencilOp,
kEqualIfInClip_StencilFunc,
@ -145,7 +145,7 @@ GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
// Sometimes the default path renderer can draw a path directly to the stencil
// buffer without having to first resolve the interior / exterior.
GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
static constexpr GrStencilSettings gDirectToStencil(
kZero_StencilOp,
kIncClamp_StencilOp,
kAlwaysIfInClip_StencilFunc,

View File

@ -88,7 +88,7 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, path, *args.fStroke));
if (path.isInverseFillType()) {
GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
static constexpr GrStencilSettings kInvertedStencilPass(
kKeep_StencilOp,
kZero_StencilOp,
// We know our rect will hit pixels outside the clip and the user bits will be 0
@ -131,7 +131,7 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
&invert));
args.fTarget->drawBatch(*pipelineBuilder, batch);
} else {
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
static constexpr GrStencilSettings kStencilPass(
kZero_StencilOp,
kKeep_StencilOp,
kNotEqual_StencilFunc,

View File

@ -2904,7 +2904,7 @@ GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
GR_GL_ZERO, // kZero_StencilOp
GR_GL_INVERT, // kInvert_StencilOp
};
GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kStencilOpCount);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kStencilOpCnt);
GR_STATIC_ASSERT(0 == kKeep_StencilOp);
GR_STATIC_ASSERT(1 == kReplace_StencilOp);
GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
@ -2913,7 +2913,7 @@ GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
GR_STATIC_ASSERT(5 == kDecClamp_StencilOp);
GR_STATIC_ASSERT(6 == kZero_StencilOp);
GR_STATIC_ASSERT(7 == kInvert_StencilOp);
SkASSERT((unsigned) op < kStencilOpCount);
SkASSERT((unsigned) op < kStencilOpCnt);
return gTable[op];
}

View File

@ -343,7 +343,7 @@ GrGLenum GrToGLStencilFunc(GrStencilFunc basicFunc) {
GR_GL_EQUAL, // kEqual_StencilFunc,
GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
};
GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCnt);
GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
GR_STATIC_ASSERT(1 == kNever_StencilFunc);
GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
@ -352,7 +352,7 @@ GrGLenum GrToGLStencilFunc(GrStencilFunc basicFunc) {
GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
SkASSERT((unsigned) basicFunc < kBasicStencilFuncCount);
SkASSERT((unsigned) basicFunc < kBasicStencilFuncCnt);
return gTable[basicFunc];
}

View File

@ -585,13 +585,13 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
if (fInstanceData->count()) {
pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.isAntiAlias());
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
kZero_StencilOp,
kKeep_StencilOp,
kNotEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
static constexpr GrStencilSettings kStencilPass(
kZero_StencilOp,
kKeep_StencilOp,
kNotEqual_StencilFunc,
0xffff,
0x0000,
0xffff);
*pipelineBuilder->stencil() = kStencilPass;

View File

@ -277,20 +277,20 @@ static void set_random_state(GrPipelineBuilder* pipelineBuilder, SkRandom* rando
// right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()'
static void set_random_stencil(GrPipelineBuilder* pipelineBuilder, SkRandom* random) {
GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil,
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0xffff,
0xffff);
GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil,
kKeep_StencilOp,
kKeep_StencilOp,
kNever_StencilFunc,
0xffff,
0xffff,
0xffff);
static constexpr GrStencilSettings kDoesWriteStencil(
kReplace_StencilOp,
kReplace_StencilOp,
kAlways_StencilFunc,
0xffff,
0xffff,
0xffff);
static constexpr GrStencilSettings kDoesNotWriteStencil(
kKeep_StencilOp,
kKeep_StencilOp,
kNever_StencilFunc,
0xffff,
0xffff,
0xffff);
if (random->nextBool()) {
pipelineBuilder->setStencil(kDoesWriteStencil);