2011-03-03 13:54:13 +00:00
|
|
|
|
2011-07-28 14:26:00 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2011 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
2011-03-03 13:54:13 +00:00
|
|
|
*/
|
|
|
|
|
2011-07-28 14:26:00 +00:00
|
|
|
|
2011-03-03 13:54:13 +00:00
|
|
|
#ifndef GrStencil_DEFINED
|
|
|
|
#define GrStencil_DEFINED
|
|
|
|
|
|
|
|
#include "GrTypes.h"
|
2012-04-25 15:23:36 +00:00
|
|
|
#include "SkRegion.h"
|
|
|
|
|
2011-03-03 13:54:13 +00:00
|
|
|
/**
|
|
|
|
* Gr uses the stencil buffer to implement complex clipping inside the
|
|
|
|
* GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer
|
|
|
|
* bits available for other uses by external code (clients). Client code can
|
|
|
|
* modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits
|
2011-08-01 15:51:05 +00:00
|
|
|
* provided by clients that overlap the bits used to implement clipping.
|
2011-03-03 13:54:13 +00:00
|
|
|
*
|
|
|
|
* When code outside the GrDrawTarget class uses the stencil buffer the contract
|
|
|
|
* is as follows:
|
|
|
|
*
|
2011-08-01 15:51:05 +00:00
|
|
|
* > Normal stencil funcs allow the client to pass / fail regardless of the
|
|
|
|
* reserved clip bits.
|
|
|
|
* > Additional functions allow a test against the clip along with a limited
|
|
|
|
* set of tests against the client bits.
|
2011-03-03 13:54:13 +00:00
|
|
|
* > Client can assume all client bits are zero initially.
|
|
|
|
* > Client must ensure that after all its passes are finished it has only
|
|
|
|
* written to the color buffer in the region inside the clip. Furthermore, it
|
|
|
|
* must zero all client bits that were modifed (both inside and outside the
|
|
|
|
* clip).
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines which pixels pass / fail the stencil test.
|
|
|
|
* Stencil test passes if (ref & mask) FUNC (stencil & mask) is true
|
|
|
|
*/
|
|
|
|
enum GrStencilFunc {
|
|
|
|
kAlways_StencilFunc = 0,
|
|
|
|
kNever_StencilFunc,
|
|
|
|
kGreater_StencilFunc,
|
|
|
|
kGEqual_StencilFunc,
|
|
|
|
kLess_StencilFunc,
|
|
|
|
kLEqual_StencilFunc,
|
|
|
|
kEqual_StencilFunc,
|
|
|
|
kNotEqual_StencilFunc,
|
|
|
|
|
|
|
|
// Gr stores the current clip in the
|
|
|
|
// stencil buffer in the high bits that
|
|
|
|
// are not directly accessible modifiable
|
|
|
|
// via the GrDrawTarget interface. The below
|
|
|
|
// stencil funcs test against the current
|
|
|
|
// clip in addition to the GrDrawTarget
|
|
|
|
// client's stencil bits.
|
|
|
|
|
|
|
|
// pass if inside the clip
|
|
|
|
kAlwaysIfInClip_StencilFunc,
|
|
|
|
kEqualIfInClip_StencilFunc,
|
|
|
|
kLessIfInClip_StencilFunc,
|
|
|
|
kLEqualIfInClip_StencilFunc,
|
|
|
|
kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0
|
|
|
|
|
|
|
|
// counts
|
|
|
|
kStencilFuncCount,
|
|
|
|
kClipStencilFuncCount = kNonZeroIfInClip_StencilFunc -
|
|
|
|
kAlwaysIfInClip_StencilFunc + 1,
|
|
|
|
kBasicStencilFuncCount = kStencilFuncCount - kClipStencilFuncCount
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Operations to perform based on whether stencil test passed failed.
|
|
|
|
*/
|
|
|
|
enum GrStencilOp {
|
|
|
|
kKeep_StencilOp = 0, // preserve existing stencil value
|
|
|
|
kReplace_StencilOp, // replace with reference value from stencl test
|
|
|
|
kIncWrap_StencilOp, // increment and wrap at max
|
|
|
|
kIncClamp_StencilOp, // increment and clamp at max
|
|
|
|
kDecWrap_StencilOp, // decrement and wrap at 0
|
|
|
|
kDecClamp_StencilOp, // decrement and clamp at 0
|
|
|
|
kZero_StencilOp, // zero stencil bits
|
|
|
|
kInvert_StencilOp, // invert stencil bits
|
|
|
|
|
|
|
|
kStencilOpCount
|
|
|
|
};
|
|
|
|
|
2012-02-16 22:03:26 +00:00
|
|
|
enum GrStencilFlags {
|
|
|
|
kIsDisabled_StencilFlag = 0x1,
|
|
|
|
kNotDisabled_StencilFlag = 0x2,
|
|
|
|
kDoesWrite_StencilFlag = 0x4,
|
|
|
|
kDoesNotWrite_StencilFlag = 0x8,
|
|
|
|
};
|
|
|
|
|
2011-03-03 13:54:13 +00:00
|
|
|
/**
|
2011-12-15 19:47:46 +00:00
|
|
|
* 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.)
|
2011-03-03 13:54:13 +00:00
|
|
|
*/
|
2011-12-15 19:47:46 +00:00
|
|
|
struct GrStencilSettingsStruct {
|
2012-06-21 19:58:20 +00:00
|
|
|
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
|
2012-01-03 19:39:31 +00:00
|
|
|
mutable uint32_t fFlags;
|
2011-12-15 19:47:46 +00:00
|
|
|
};
|
2012-01-03 19:39:31 +00:00
|
|
|
// 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
|
2012-06-21 19:58:20 +00:00
|
|
|
2*sizeof(uint16_t) + // func masks
|
|
|
|
2*sizeof(uint16_t) + // ref values
|
|
|
|
2*sizeof(uint16_t) + // write masks
|
2012-01-03 19:39:31 +00:00
|
|
|
sizeof(uint32_t)); // flags
|
2011-12-15 19:47:46 +00:00
|
|
|
|
2012-02-16 22:03:26 +00:00
|
|
|
// 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))
|
|
|
|
|
2011-12-15 19:47:46 +00:00
|
|
|
/**
|
|
|
|
* Class representing stencil state.
|
|
|
|
*/
|
|
|
|
class GrStencilSettings : private GrStencilSettingsStruct {
|
2011-03-03 13:54:13 +00:00
|
|
|
|
2011-12-15 19:47:46 +00:00
|
|
|
public:
|
2012-06-21 19:58:20 +00:00
|
|
|
enum Face {
|
|
|
|
kFront_Face = 0,
|
|
|
|
kBack_Face = 1,
|
|
|
|
};
|
|
|
|
|
2012-01-03 19:39:31 +00:00
|
|
|
GrStencilSettings() {
|
|
|
|
fPad0 = fPad1 = 0;
|
|
|
|
this->setDisabled();
|
2011-03-03 13:54:13 +00:00
|
|
|
}
|
2012-06-21 19:58:20 +00:00
|
|
|
|
|
|
|
GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[f]); }
|
|
|
|
GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[f]); }
|
|
|
|
GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[f]); }
|
|
|
|
uint16_t funcMask(Face f) const { return fFuncMasks[f]; }
|
|
|
|
uint16_t funcRef(Face f) const { return fFuncRefs[f]; }
|
|
|
|
uint16_t writeMask(Face f) const { return fWriteMasks[f]; }
|
|
|
|
|
|
|
|
void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;}
|
|
|
|
void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;}
|
|
|
|
void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;}
|
|
|
|
void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; }
|
|
|
|
void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; }
|
|
|
|
void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = writeMask; }
|
|
|
|
|
|
|
|
void copyFrontSettingsToBack() {
|
|
|
|
fPassOps[kBack_Face] = fPassOps[kFront_Face];
|
|
|
|
fFailOps[kBack_Face] = fFailOps[kFront_Face];
|
|
|
|
fFuncs[kBack_Face] = fFuncs[kFront_Face];
|
|
|
|
fFuncMasks[kBack_Face] = fFuncMasks[kFront_Face];
|
|
|
|
fFuncRefs[kBack_Face] = fFuncRefs[kFront_Face];
|
|
|
|
fWriteMasks[kBack_Face] = fWriteMasks[kFront_Face];
|
|
|
|
fFlags = 0;
|
|
|
|
}
|
2011-12-15 19:47:46 +00:00
|
|
|
|
2011-03-03 13:54:13 +00:00
|
|
|
void setSame(GrStencilOp passOp,
|
|
|
|
GrStencilOp failOp,
|
|
|
|
GrStencilFunc func,
|
2011-11-09 16:39:17 +00:00
|
|
|
unsigned short funcMask,
|
|
|
|
unsigned short funcRef,
|
|
|
|
unsigned short writeMask) {
|
2012-06-21 19:58:20 +00:00
|
|
|
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;
|
2012-01-03 19:39:31 +00:00
|
|
|
fFlags = 0;
|
2011-03-03 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setDisabled() {
|
2011-12-15 19:47:46 +00:00
|
|
|
memset(this, 0, sizeof(*this));
|
|
|
|
GR_STATIC_ASSERT(0 == kKeep_StencilOp);
|
|
|
|
GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
|
2012-02-16 22:03:26 +00:00
|
|
|
fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag;
|
2011-03-03 13:54:13 +00:00
|
|
|
}
|
2012-01-03 19:39:31 +00:00
|
|
|
|
2012-06-22 12:23:29 +00:00
|
|
|
bool isTwoSided() const {
|
|
|
|
return fPassOps[kFront_Face] != fPassOps[kBack_Face] ||
|
|
|
|
fFailOps[kFront_Face] != fFailOps[kBack_Face] ||
|
|
|
|
fFuncs[kFront_Face] != fFuncs[kBack_Face] ||
|
|
|
|
fFuncMasks[kFront_Face] != fFuncMasks[kBack_Face] ||
|
|
|
|
fFuncRefs[kFront_Face] != fFuncRefs[kBack_Face] ||
|
|
|
|
fWriteMasks[kFront_Face] != fWriteMasks[kBack_Face];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool usesWrapOp() const {
|
|
|
|
return kIncWrap_StencilOp == fPassOps[kFront_Face] ||
|
|
|
|
kDecWrap_StencilOp == fPassOps[kFront_Face] ||
|
|
|
|
kIncWrap_StencilOp == fPassOps[kBack_Face] ||
|
|
|
|
kDecWrap_StencilOp == fPassOps[kBack_Face] ||
|
|
|
|
kIncWrap_StencilOp == fFailOps[kFront_Face] ||
|
|
|
|
kDecWrap_StencilOp == fFailOps[kFront_Face] ||
|
|
|
|
kIncWrap_StencilOp == fFailOps[kBack_Face] ||
|
|
|
|
kDecWrap_StencilOp == fFailOps[kBack_Face];
|
|
|
|
}
|
|
|
|
|
2011-03-03 13:54:13 +00:00
|
|
|
bool isDisabled() const {
|
2012-02-16 22:03:26 +00:00
|
|
|
if (fFlags & kIsDisabled_StencilFlag) {
|
2012-01-03 19:39:31 +00:00
|
|
|
return true;
|
|
|
|
}
|
2012-02-16 22:03:26 +00:00
|
|
|
if (fFlags & kNotDisabled_StencilFlag) {
|
2012-01-03 19:39:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-02-16 22:03:26 +00:00
|
|
|
bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED(
|
2012-06-21 19:58:20 +00:00
|
|
|
fPassOps[kFront_Face], fPassOps[kBack_Face],
|
|
|
|
fFailOps[kFront_Face], fFailOps[kBack_Face],
|
|
|
|
fFuncs[kFront_Face], fFuncs[kBack_Face]);
|
2012-02-16 22:03:26 +00:00
|
|
|
fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
|
2012-01-03 19:39:31 +00:00
|
|
|
return disabled;
|
2011-03-03 13:54:13 +00:00
|
|
|
}
|
2012-01-03 19:39:31 +00:00
|
|
|
|
2011-10-12 14:54:26 +00:00
|
|
|
bool doesWrite() const {
|
2012-02-16 22:03:26 +00:00
|
|
|
if (fFlags & kDoesWrite_StencilFlag) {
|
2012-01-03 19:39:31 +00:00
|
|
|
return true;
|
|
|
|
}
|
2012-02-16 22:03:26 +00:00
|
|
|
if (fFlags & kDoesNotWrite_StencilFlag) {
|
2012-01-03 19:39:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-02-16 22:03:26 +00:00
|
|
|
bool writes = GR_STENCIL_SETTINGS_DOES_WRITE(
|
2012-06-21 19:58:20 +00:00
|
|
|
fPassOps[kFront_Face], fPassOps[kBack_Face],
|
|
|
|
fFailOps[kFront_Face], fFailOps[kBack_Face],
|
|
|
|
fFuncs[kFront_Face], fFuncs[kBack_Face]);
|
2012-02-16 22:03:26 +00:00
|
|
|
fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
|
2012-01-03 19:39:31 +00:00
|
|
|
return writes;
|
2011-10-12 14:54:26 +00:00
|
|
|
}
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2011-03-03 13:54:13 +00:00
|
|
|
void invalidate() {
|
2012-01-03 19:39:31 +00:00
|
|
|
// write an illegal value to the first member
|
2012-06-21 19:58:20 +00:00
|
|
|
fPassOps[0] = (GrStencilOp)(uint8_t)-1;
|
2012-01-03 19:39:31 +00:00
|
|
|
fFlags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator == (const GrStencilSettings& s) const {
|
|
|
|
static const size_t gCompareSize = sizeof(GrStencilSettings) -
|
|
|
|
sizeof(fFlags);
|
2013-08-17 00:02:59 +00:00
|
|
|
SkASSERT((const char*)&fFlags + sizeof(fFlags) ==
|
2012-01-03 19:39:31 +00:00
|
|
|
(const char*)this + sizeof(GrStencilSettings));
|
|
|
|
if (this->isDisabled() & s.isDisabled()) { // using & not &&
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return 0 == memcmp(this, &s, gCompareSize);
|
|
|
|
}
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2012-01-03 19:39:31 +00:00
|
|
|
bool operator != (const GrStencilSettings& s) const {
|
|
|
|
return !(*this == s);
|
|
|
|
}
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2012-01-03 19:39:31 +00:00
|
|
|
GrStencilSettings& operator =(const GrStencilSettings& s) {
|
|
|
|
memcpy(this, &s, sizeof(GrStencilSettings));
|
|
|
|
return *this;
|
2011-03-03 13:54:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2012-04-16 16:33:13 +00:00
|
|
|
friend class GrClipMaskManager;
|
|
|
|
|
2011-03-03 13:54:13 +00:00
|
|
|
enum {
|
2012-08-23 18:14:13 +00:00
|
|
|
kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
|
2011-03-03 13:54:13 +00:00
|
|
|
// element to the stencil buffer.
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given a thing to draw into the stencil clip, a fill type, and a set op
|
|
|
|
* this function determines:
|
|
|
|
* 1. Whether the thing can be draw directly to the stencil clip or
|
|
|
|
* needs to be drawn to the client portion of the stencil first.
|
|
|
|
* 2. How many passes are needed.
|
|
|
|
* 3. What those passes are.
|
2012-08-23 18:14:13 +00:00
|
|
|
* 4. The fill rule that should actually be used to render (will
|
2011-03-03 13:54:13 +00:00
|
|
|
* always be non-inverted).
|
|
|
|
*
|
2012-08-23 18:14:13 +00:00
|
|
|
* @param op the set op to combine this element with the
|
2011-03-03 13:54:13 +00:00
|
|
|
* existing clip
|
|
|
|
* @param stencilClipMask mask with just the stencil bit used for clipping
|
|
|
|
* enabled.
|
2011-03-04 20:29:08 +00:00
|
|
|
* @param invertedFill is this path inverted
|
2012-08-23 18:14:13 +00:00
|
|
|
* @param numPasses out: the number of passes needed to add the
|
2011-03-03 13:54:13 +00:00
|
|
|
* element to the clip.
|
|
|
|
* @param settings out: the stencil settings to use for each pass
|
|
|
|
*
|
|
|
|
* @return true if the clip element's geometry can be drawn directly to the
|
|
|
|
* stencil clip bit. Will only be true if canBeDirect is true.
|
|
|
|
* numPasses will be 1 if return value is true.
|
|
|
|
*/
|
2012-08-23 18:14:13 +00:00
|
|
|
static bool GetClipPasses(SkRegion::Op op,
|
2011-03-03 13:54:13 +00:00
|
|
|
bool canBeDirect,
|
|
|
|
unsigned int stencilClipMask,
|
2011-03-04 20:29:08 +00:00
|
|
|
bool invertedFill,
|
2011-03-03 13:54:13 +00:00
|
|
|
int* numPasses,
|
|
|
|
GrStencilSettings settings[kMaxStencilClipPasses]);
|
|
|
|
};
|
|
|
|
|
2011-12-15 19:47:46 +00:00
|
|
|
GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
|
|
|
|
|
2012-02-16 22:03:26 +00:00
|
|
|
#define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \
|
2011-12-15 19:47:46 +00:00
|
|
|
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) \
|
2012-02-16 22:03:26 +00:00
|
|
|
static const GrStencilSettingsStruct STRUCT_NAME = { \
|
2012-06-21 19:58:20 +00:00
|
|
|
{(FRONT_PASS_OP), (BACK_PASS_OP) }, \
|
|
|
|
{(FRONT_FAIL_OP), (BACK_FAIL_OP) }, \
|
|
|
|
{(FRONT_FUNC), (BACK_FUNC) }, \
|
2012-01-03 19:39:31 +00:00
|
|
|
(0), (0), \
|
2012-06-21 19:58:20 +00:00
|
|
|
{(FRONT_MASK), (BACK_MASK) }, \
|
|
|
|
{(FRONT_REF), (BACK_REF) }, \
|
|
|
|
{(FRONT_WRITE_MASK), (BACK_WRITE_MASK)}, \
|
2012-02-16 22:03:26 +00:00
|
|
|
GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
|
|
|
|
FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP, \
|
|
|
|
FRONT_FUNC, BACK_FUNC) \
|
|
|
|
};
|
|
|
|
|
|
|
|
#define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR) \
|
|
|
|
reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR)
|
|
|
|
|
|
|
|
#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)) \
|
2011-12-15 19:47:46 +00:00
|
|
|
static const GrStencilSettings& NAME = \
|
2012-02-16 22:03:26 +00:00
|
|
|
*GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT));
|
|
|
|
|
2011-12-15 19:47:46 +00:00
|
|
|
|
|
|
|
#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))
|
2012-02-16 22:03:26 +00:00
|
|
|
|
|
|
|
#endif
|