зеркало из https://github.com/mozilla/moz-skia.git
Make GrClipMaskManager configure the stencil and scissor on GrGpu
Review URL: http://codereview.appspot.com/6308096/ git-svn-id: http://skia.googlecode.com/svn/trunk@4288 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
8f7e1dac5c
Коммит
a320194e42
|
@ -195,6 +195,7 @@
|
|||
'../include/gpu/GrResource.h',
|
||||
'../include/gpu/GrSamplerState.h',
|
||||
'../include/gpu/GrScalar.h',
|
||||
'../include/gpu/GrTemplates.h',
|
||||
'../include/gpu/GrTextContext.h',
|
||||
'../include/gpu/GrTexture.h',
|
||||
'../include/gpu/GrTypes.h',
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
#include "GrClipIterator.h"
|
||||
#include "GrRect.h"
|
||||
#include "GrTemplates.h"
|
||||
|
||||
#include "SkPath.h"
|
||||
#include "SkTArray.h"
|
||||
|
@ -78,6 +77,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: This word "empty" is confusing. It means that the clip has no
|
||||
// elements (it is the infinite plane) not that it has no area.
|
||||
bool isEmpty() const { return 0 == fList.count(); }
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,36 +25,37 @@ template <typename Dst, typename Src> Dst GrTCast(Src src) {
|
|||
}
|
||||
|
||||
/**
|
||||
* saves value of T* in and restores in destructor
|
||||
* takes a T*, saves the value it points to, in and restores the value in the
|
||||
* destructor
|
||||
* e.g.:
|
||||
* {
|
||||
* GrAutoTPtrValueRestore<int*> autoCountRestore;
|
||||
* GrAutoTRestore<int*> autoCountRestore;
|
||||
* if (useExtra) {
|
||||
* autoCountRestore.save(&fCount);
|
||||
* autoCountRestore.reset(&fCount);
|
||||
* fCount += fExtraCount;
|
||||
* }
|
||||
* ...
|
||||
* } // fCount is restored
|
||||
*/
|
||||
template <typename T> class GrAutoTPtrValueRestore : public GrNoncopyable {
|
||||
template <typename T> class GrAutoTRestore : public GrNoncopyable {
|
||||
public:
|
||||
GrAutoTPtrValueRestore() : fPtr(NULL), fVal() {}
|
||||
GrAutoTRestore() : fPtr(NULL), fVal() {}
|
||||
|
||||
GrAutoTPtrValueRestore(T* ptr) {
|
||||
GrAutoTRestore(T* ptr) {
|
||||
fPtr = ptr;
|
||||
if (NULL != ptr) {
|
||||
fVal = *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
~GrAutoTPtrValueRestore() {
|
||||
~GrAutoTRestore() {
|
||||
if (NULL != fPtr) {
|
||||
*fPtr = fVal;
|
||||
}
|
||||
}
|
||||
|
||||
// restores previously saved value (if any) and saves value for passed T*
|
||||
void save(T* ptr) {
|
||||
void reset(T* ptr) {
|
||||
if (NULL != fPtr) {
|
||||
*fPtr = fVal;
|
||||
}
|
||||
|
|
|
@ -23,15 +23,6 @@
|
|||
//#define GR_SW_CLIP 1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ScissoringSettings::setupScissoring(GrGpu* gpu) {
|
||||
if (!fEnableScissoring) {
|
||||
gpu->disableScissor();
|
||||
return;
|
||||
}
|
||||
|
||||
gpu->enableScissoring(fScissorRect);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// set up the draw state to enable the aa clipping mask. Besides setting up the
|
||||
// sampler matrix this also alters the vertex layout
|
||||
|
@ -113,37 +104,50 @@ bool GrClipMaskManager::useSWOnlyPath(const GrClip& clipIn) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// sort out what kind of clip mask needs to be created: alpha, stencil,
|
||||
// scissor, or entirely software
|
||||
bool GrClipMaskManager::createClipMask(const GrClip& clipIn,
|
||||
ScissoringSettings* scissorSettings) {
|
||||
|
||||
GrAssert(scissorSettings);
|
||||
|
||||
scissorSettings->fEnableScissoring = false;
|
||||
|
||||
bool GrClipMaskManager::setupClipping(const GrClip& clipIn) {
|
||||
fCurrClipMaskType = kNone_ClipMaskType;
|
||||
|
||||
|
||||
GrDrawState* drawState = fGpu->drawState();
|
||||
if (!drawState->isClipState()) {
|
||||
if (!drawState->isClipState() || clipIn.isEmpty()) {
|
||||
fGpu->disableScissor();
|
||||
this->setGpuStencil();
|
||||
return true;
|
||||
}
|
||||
|
||||
GrRenderTarget* rt = drawState->getRenderTarget();
|
||||
|
||||
// GrDrawTarget should have filtered this for us
|
||||
GrAssert(NULL != rt);
|
||||
|
||||
GrIRect bounds;
|
||||
GrIRect rtRect;
|
||||
rtRect.setLTRB(0, 0, rt->width(), rt->height());
|
||||
if (clipIn.hasConservativeBounds()) {
|
||||
GrRect softBounds = clipIn.getConservativeBounds();
|
||||
softBounds.roundOut(&bounds);
|
||||
if (!bounds.intersect(rtRect)) {
|
||||
bounds.setEmpty();
|
||||
}
|
||||
if (bounds.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
bounds = rtRect;
|
||||
}
|
||||
|
||||
#if GR_SW_CLIP
|
||||
// If MSAA is enabled we can do everything in the stencil buffer.
|
||||
// Otherwise check if we should just create the entire clip mask
|
||||
// in software (this will only happen if the clip mask is anti-aliased
|
||||
// and too complex for the gpu to handle in its entirety)
|
||||
if (0 == rt->numSamples() && useSWOnlyPath(gpu, clipIn)) {
|
||||
if (0 == rt->numSamples() && this->useSWOnlyPath(clipIn)) {
|
||||
// The clip geometry is complex enough that it will be more
|
||||
// efficient to create it entirely in software
|
||||
GrTexture* result = NULL;
|
||||
GrIRect bound;
|
||||
if (this->createSoftwareClipMask(fGpu, clipIn, &result, &bound)) {
|
||||
if (this->createSoftwareClipMask(clipIn, &result, &bound)) {
|
||||
setup_drawstate_aaclip(fGpu, result, bound);
|
||||
fGpu->disableScissor();
|
||||
this->setGpuStencil();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -162,8 +166,10 @@ bool GrClipMaskManager::createClipMask(const GrClip& clipIn,
|
|||
// path does (see scissorSettings below)
|
||||
GrTexture* result = NULL;
|
||||
GrIRect bound;
|
||||
if (this->createAlphaClipMask(fGpu, clipIn, &result, &bound)) {
|
||||
if (this->createAlphaClipMask(clipIn, &result, &bound)) {
|
||||
setup_drawstate_aaclip(fGpu, result, bound);
|
||||
fGpu->disableScissor();
|
||||
this->setGpuStencil();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -181,36 +187,27 @@ bool GrClipMaskManager::createClipMask(const GrClip& clipIn,
|
|||
// AA cache.
|
||||
fAACache.reset();
|
||||
|
||||
GrRect bounds;
|
||||
GrRect rtRect;
|
||||
rtRect.setLTRB(0, 0,
|
||||
GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
|
||||
if (clipIn.hasConservativeBounds()) {
|
||||
bounds = clipIn.getConservativeBounds();
|
||||
if (!bounds.intersect(rtRect)) {
|
||||
bounds.setEmpty();
|
||||
}
|
||||
} else {
|
||||
bounds = rtRect;
|
||||
// If the clip is a rectangle then just set the scissor. Otherwise, create
|
||||
// a stencil mask.
|
||||
if (clipIn.isRect()) {
|
||||
fGpu->enableScissor(bounds);
|
||||
this->setGpuStencil();
|
||||
return true;
|
||||
}
|
||||
|
||||
bounds.roundOut(&scissorSettings->fScissorRect);
|
||||
if (scissorSettings->fScissorRect.isEmpty()) {
|
||||
scissorSettings->fScissorRect.setLTRB(0,0,0,0);
|
||||
// TODO: I think we can do an early exit here - after refactoring try:
|
||||
// set fEnableScissoring to true but leave fClipMaskInStencil false
|
||||
// and return - everything is going to be scissored away anyway!
|
||||
}
|
||||
scissorSettings->fEnableScissoring = true;
|
||||
|
||||
// use the stencil clip if we can't represent the clip as a rectangle.
|
||||
bool useStencil = !clipIn.isRect() && !clipIn.isEmpty() &&
|
||||
!bounds.isEmpty();
|
||||
|
||||
if (useStencil) {
|
||||
return this->createStencilClipMask(clipIn, bounds, scissorSettings);
|
||||
this->createStencilClipMask(clipIn, bounds);
|
||||
}
|
||||
|
||||
// This must occur after createStencilClipMask. That function may change
|
||||
// the scissor. Also, it only guarantees that the stencil mask is correct
|
||||
// within the bounds it was passed, so we must use both stencil and scissor
|
||||
// test to the bounds for the final draw.
|
||||
fGpu->enableScissor(bounds);
|
||||
this->setGpuStencil();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -663,8 +660,7 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClip& clipIn,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Create a 1-bit clip mask in the stencil buffer
|
||||
bool GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
|
||||
const GrRect& bounds,
|
||||
ScissoringSettings* scissorSettings) {
|
||||
const GrIRect& bounds) {
|
||||
|
||||
GrAssert(kNone_ClipMaskType == fCurrClipMaskType);
|
||||
|
||||
|
@ -696,7 +692,6 @@ bool GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
|
|||
drawState->setRenderTarget(rt);
|
||||
GrDrawTarget::AutoGeometryPush agp(fGpu);
|
||||
|
||||
fGpu->disableScissor();
|
||||
#if !VISUALIZE_COMPLEX_CLIP
|
||||
drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
|
||||
#endif
|
||||
|
@ -716,7 +711,7 @@ bool GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
|
|||
&clearToInside,
|
||||
&startOp);
|
||||
|
||||
fGpu->clearStencilClip(scissorSettings->fScissorRect, clearToInside);
|
||||
fGpu->clearStencilClip(bounds, clearToInside);
|
||||
|
||||
// walk through each clip element and perform its set op
|
||||
// with the existing clip.
|
||||
|
@ -814,7 +809,12 @@ bool GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
|
|||
}
|
||||
} else {
|
||||
SET_RANDOM_COLOR
|
||||
fGpu->drawSimpleRect(bounds, NULL, 0);
|
||||
GrRect rect = GrRect::MakeLTRB(
|
||||
SkIntToScalar(bounds.fLeft),
|
||||
SkIntToScalar(bounds.fTop),
|
||||
SkIntToScalar(bounds.fRight),
|
||||
SkIntToScalar(bounds.fBottom));
|
||||
fGpu->drawSimpleRect(rect, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -863,60 +863,162 @@ static const GrStencilFunc
|
|||
}
|
||||
};
|
||||
|
||||
GrStencilFunc GrClipMaskManager::adjustStencilParams(GrStencilFunc func,
|
||||
StencilClipMode mode,
|
||||
unsigned int stencilBitCnt,
|
||||
unsigned int* ref,
|
||||
unsigned int* mask,
|
||||
unsigned int* writeMask) {
|
||||
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::setGpuStencil() {
|
||||
// We make two copies of the StencilSettings here (except in the early
|
||||
// exit scenario. One copy from draw state to the stack var. Then another
|
||||
// from the stack var to the gpu. We could make this class hold a ptr to
|
||||
// GrGpu's fStencilSettings and eliminate the stack copy here.
|
||||
|
||||
const GrDrawState& drawState = fGpu->getDrawState();
|
||||
|
||||
// use stencil for clipping if clipping is enabled and the clip
|
||||
// has been written into the stencil.
|
||||
GrClipMaskManager::StencilClipMode clipMode;
|
||||
if (this->isClipInStencil() && drawState.isClipState()) {
|
||||
clipMode = GrClipMaskManager::kRespectClip_StencilClipMode;
|
||||
// We can't be modifying the clip and respecting it at the same time.
|
||||
GrAssert(!drawState.isStateFlagEnabled(
|
||||
GrGpu::kModifyStencilClip_StateBit));
|
||||
} else if (drawState.isStateFlagEnabled(
|
||||
GrGpu::kModifyStencilClip_StateBit)) {
|
||||
clipMode = GrClipMaskManager::kModifyClip_StencilClipMode;
|
||||
} else {
|
||||
clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode;
|
||||
}
|
||||
|
||||
GrStencilSettings settings;
|
||||
// The GrGpu client may not be using the stencil buffer but we may need to
|
||||
// enable it in order to respect a stencil clip.
|
||||
if (drawState.getStencil().isDisabled()) {
|
||||
if (GrClipMaskManager::kRespectClip_StencilClipMode == clipMode) {
|
||||
settings = basic_apply_stencil_clip_settings();
|
||||
} else {
|
||||
fGpu->disableStencil();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
settings = drawState.getStencil();
|
||||
}
|
||||
|
||||
// TODO: dynamically attach a stencil buffer
|
||||
int stencilBits = 0;
|
||||
GrStencilBuffer* stencilBuffer =
|
||||
drawState.getRenderTarget()->getStencilBuffer();
|
||||
if (NULL != stencilBuffer) {
|
||||
stencilBits = stencilBuffer->bits();
|
||||
}
|
||||
|
||||
#if GR_DEBUG
|
||||
if (!fGpu->getCaps().fStencilWrapOpsSupport) {
|
||||
GrAssert(settings.frontPassOp() != kIncWrap_StencilOp);
|
||||
GrAssert(settings.frontPassOp() != kDecWrap_StencilOp);
|
||||
GrAssert(settings.frontFailOp() != kIncWrap_StencilOp);
|
||||
GrAssert(settings.backFailOp() != kDecWrap_StencilOp);
|
||||
GrAssert(settings.backPassOp() != kIncWrap_StencilOp);
|
||||
GrAssert(settings.backPassOp() != kDecWrap_StencilOp);
|
||||
GrAssert(settings.backFailOp() != kIncWrap_StencilOp);
|
||||
GrAssert(settings.frontFailOp() != kDecWrap_StencilOp);
|
||||
}
|
||||
#endif
|
||||
this->adjustStencilParams(&settings, clipMode, stencilBits);
|
||||
fGpu->setStencilSettings(settings);
|
||||
}
|
||||
|
||||
void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
|
||||
StencilClipMode mode,
|
||||
int stencilBitCnt) {
|
||||
GrAssert(stencilBitCnt > 0);
|
||||
GrAssert((unsigned) func < kStencilFuncCount);
|
||||
|
||||
if (kModifyClip_StencilClipMode == mode) {
|
||||
// We assume that this class is the client/draw-caller of the GrGpu and
|
||||
// has already setup the correct values
|
||||
return func;
|
||||
// We assume that this clip manager itself is drawing to the GrGpu and
|
||||
// has already setup the correct values.
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int clipBit = (1 << (stencilBitCnt - 1));
|
||||
unsigned int userBits = clipBit - 1;
|
||||
|
||||
*writeMask &= userBits;
|
||||
GrStencilSettings::Face face = GrStencilSettings::kFront_Face;
|
||||
bool twoSided = fGpu->getCaps().fTwoSidedStencilSupport;
|
||||
|
||||
if (func >= kBasicStencilFuncCount) {
|
||||
int respectClip = kRespectClip_StencilClipMode == mode;
|
||||
if (respectClip) {
|
||||
// The GrGpu class should have checked this
|
||||
GrAssert(this->isClipInStencil());
|
||||
switch (func) {
|
||||
case kAlwaysIfInClip_StencilFunc:
|
||||
*mask = clipBit;
|
||||
*ref = clipBit;
|
||||
break;
|
||||
case kEqualIfInClip_StencilFunc:
|
||||
case kLessIfInClip_StencilFunc:
|
||||
case kLEqualIfInClip_StencilFunc:
|
||||
*mask = (*mask & userBits) | clipBit;
|
||||
*ref = (*ref & userBits) | clipBit;
|
||||
break;
|
||||
case kNonZeroIfInClip_StencilFunc:
|
||||
*mask = (*mask & userBits) | clipBit;
|
||||
*ref = clipBit;
|
||||
break;
|
||||
default:
|
||||
GrCrash("Unknown stencil func");
|
||||
bool finished = false;
|
||||
while (!finished) {
|
||||
GrStencilFunc func = settings->func(face);
|
||||
uint16_t writeMask = settings->writeMask(face);
|
||||
uint16_t funcMask = settings->funcMask(face);
|
||||
uint16_t funcRef = settings->funcRef(face);
|
||||
|
||||
GrAssert((unsigned) func < kStencilFuncCount);
|
||||
|
||||
writeMask &= userBits;
|
||||
|
||||
if (func >= kBasicStencilFuncCount) {
|
||||
int respectClip = kRespectClip_StencilClipMode == mode;
|
||||
if (respectClip) {
|
||||
// The GrGpu class should have checked this
|
||||
GrAssert(this->isClipInStencil());
|
||||
switch (func) {
|
||||
case kAlwaysIfInClip_StencilFunc:
|
||||
funcMask = clipBit;
|
||||
funcRef = clipBit;
|
||||
break;
|
||||
case kEqualIfInClip_StencilFunc:
|
||||
case kLessIfInClip_StencilFunc:
|
||||
case kLEqualIfInClip_StencilFunc:
|
||||
funcMask = (funcMask & userBits) | clipBit;
|
||||
funcRef = (funcRef & userBits) | clipBit;
|
||||
break;
|
||||
case kNonZeroIfInClip_StencilFunc:
|
||||
funcMask = (funcMask & userBits) | clipBit;
|
||||
funcRef = clipBit;
|
||||
break;
|
||||
default:
|
||||
GrCrash("Unknown stencil func");
|
||||
}
|
||||
} else {
|
||||
funcMask &= userBits;
|
||||
funcRef &= userBits;
|
||||
}
|
||||
const GrStencilFunc* table =
|
||||
gSpecialToBasicStencilFunc[respectClip];
|
||||
func = table[func - kBasicStencilFuncCount];
|
||||
GrAssert(func >= 0 && func < kBasicStencilFuncCount);
|
||||
} else {
|
||||
*mask &= userBits;
|
||||
*ref &= userBits;
|
||||
funcMask &= userBits;
|
||||
funcRef &= userBits;
|
||||
}
|
||||
|
||||
settings->setFunc(face, func);
|
||||
settings->setWriteMask(face, writeMask);
|
||||
settings->setFuncMask(face, funcMask);
|
||||
settings->setFuncRef(face, funcRef);
|
||||
|
||||
if (GrStencilSettings::kFront_Face == face) {
|
||||
face = GrStencilSettings::kBack_Face;
|
||||
finished = !twoSided;
|
||||
} else {
|
||||
finished = true;
|
||||
}
|
||||
const GrStencilFunc* table = gSpecialToBasicStencilFunc[respectClip];
|
||||
func = table[func - kBasicStencilFuncCount];
|
||||
GrAssert(func >= 0 && func < kBasicStencilFuncCount);
|
||||
} else {
|
||||
*mask &= userBits;
|
||||
*ref &= userBits;
|
||||
}
|
||||
return func;
|
||||
if (!twoSided) {
|
||||
settings->copyFrontSettingsToBack();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -27,19 +27,6 @@ class SkPath;
|
|||
class GrTexture;
|
||||
class GrDrawState;
|
||||
|
||||
/**
|
||||
* Scissoring needs special handling during stencil clip mask creation
|
||||
* since the creation process re-entrantly invokes setupClipAndFlushState.
|
||||
* During this process the call stack is used to keep
|
||||
* track of (and apply to the GPU) the current scissor settings.
|
||||
*/
|
||||
struct ScissoringSettings {
|
||||
bool fEnableScissoring;
|
||||
GrIRect fScissorRect;
|
||||
|
||||
void setupScissoring(GrGpu* gpu);
|
||||
};
|
||||
|
||||
/**
|
||||
* The stencil buffer stores the last clip path - providing a single entry
|
||||
* "cache". This class provides similar functionality for AA clip paths
|
||||
|
@ -288,8 +275,12 @@ public:
|
|||
, fCurrClipMaskType(kNone_ClipMaskType) {
|
||||
}
|
||||
|
||||
bool createClipMask(const GrClip& clip,
|
||||
ScissoringSettings* scissorSettings);
|
||||
/**
|
||||
* Creates a clip mask if necessary as a stencil buffer or alpha texture
|
||||
* and sets the GrGpu's scissor and stencil state. If the return is false
|
||||
* then the draw can be skipped.
|
||||
*/
|
||||
bool setupClipping(const GrClip& clip);
|
||||
|
||||
void releaseResources();
|
||||
|
||||
|
@ -325,6 +316,7 @@ public:
|
|||
return fAACache.getContext();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Informs the helper function adjustStencilParams() about how the stencil
|
||||
* buffer clip is being used.
|
||||
|
@ -339,21 +331,6 @@ public:
|
|||
kIgnoreClip_StencilClipMode,
|
||||
};
|
||||
|
||||
/**
|
||||
* The stencil func, mask, and reference value are specified by GrGpu's
|
||||
* caller but the actual values passed to the API may have to be adjusted
|
||||
* due to the stencil buffer simultaneously being used for clipping. This
|
||||
* function should be called even when clipping is disabled in order to
|
||||
* prevent the clip from being accidentally overwritten.
|
||||
*/
|
||||
GrStencilFunc adjustStencilParams(GrStencilFunc,
|
||||
StencilClipMode mode,
|
||||
unsigned int stencilBitCnt,
|
||||
unsigned int* ref,
|
||||
unsigned int* mask,
|
||||
unsigned int* writeMask);
|
||||
|
||||
private:
|
||||
GrGpu* fGpu;
|
||||
|
||||
/**
|
||||
|
@ -369,9 +346,8 @@ private:
|
|||
|
||||
GrClipMaskCache fAACache; // cache for the AA path
|
||||
|
||||
bool createStencilClipMask(const GrClip& clip,
|
||||
const GrRect& bounds,
|
||||
ScissoringSettings* scissorSettings);
|
||||
bool createStencilClipMask(const GrClip& clip,
|
||||
const GrIRect& bounds);
|
||||
bool createAlphaClipMask(const GrClip& clipIn,
|
||||
GrTexture** result,
|
||||
GrIRect *resultBounds);
|
||||
|
@ -396,6 +372,21 @@ private:
|
|||
void setupCache(const GrClip& clip,
|
||||
const GrIRect& bounds);
|
||||
|
||||
/**
|
||||
* Called prior to return control back the GrGpu in setupClipping. It
|
||||
* updates the GrGpu with stencil settings that account stencil-based
|
||||
* clipping.
|
||||
*/
|
||||
void setGpuStencil();
|
||||
|
||||
/**
|
||||
* Adjusts the stencil settings to account for interaction with stencil
|
||||
* clipping.
|
||||
*/
|
||||
void adjustStencilParams(GrStencilSettings* settings,
|
||||
StencilClipMode mode,
|
||||
int stencilBitCnt);
|
||||
|
||||
typedef GrNoncopyable INHERITED;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "GrIndexBuffer.h"
|
||||
#include "GrMatrix.h"
|
||||
#include "GrRefCnt.h"
|
||||
#include "GrTemplates.h"
|
||||
|
||||
#include "SkXfermode.h"
|
||||
#include "SkTLazy.h"
|
||||
|
|
|
@ -351,34 +351,16 @@ const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const GrStencilSettings* GrGpu::GetClipStencilSettings(void) {
|
||||
// stencil settings to use when clip is in stencil
|
||||
GR_STATIC_CONST_SAME_STENCIL_STRUCT(sClipStencilSettings,
|
||||
kKeep_StencilOp,
|
||||
kKeep_StencilOp,
|
||||
kAlwaysIfInClip_StencilFunc,
|
||||
0x0000,
|
||||
0x0000,
|
||||
0x0000);
|
||||
return GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&sClipStencilSettings);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrGpu::setupClipAndFlushState(DrawType type) {
|
||||
|
||||
ScissoringSettings scissoringSettings;
|
||||
|
||||
if (!fClipMaskManager.createClipMask(fClip, &scissoringSettings)) {
|
||||
if (!fClipMaskManager.setupClipping(fClip)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must flush the scissor after graphics state
|
||||
if (!this->flushGraphicsState(type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scissoringSettings.setupScissoring(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -323,8 +323,29 @@ public:
|
|||
return fConfigRenderSupport[config];
|
||||
}
|
||||
|
||||
virtual void enableScissoring(const GrIRect& rect) = 0;
|
||||
virtual void disableScissor() = 0;
|
||||
/**
|
||||
* These methods are called by the clip manager's setupClipping function
|
||||
* which (called as part of GrGpu's implementation of onDraw* and
|
||||
* onStencilPath member functions.) The GrGpu subclass should flush the
|
||||
* stencil state to the 3D API in its implementation of flushGraphicsState.
|
||||
*/
|
||||
void enableScissor(const GrIRect& rect) {
|
||||
fScissorState.fEnabled = true;
|
||||
fScissorState.fRect = rect;
|
||||
}
|
||||
void disableScissor() { fScissorState.fEnabled = false; }
|
||||
|
||||
/**
|
||||
* Like the scissor methods above this is called by setupClipping and
|
||||
* should be flushed by the GrGpu subclass in flushGraphicsState. These
|
||||
* stencil settings should be used in place of those on the GrDrawState.
|
||||
* They have been adjusted to account for any interactions between the
|
||||
* GrDrawState's stencil settings and stencil clipping.
|
||||
*/
|
||||
void setStencilSettings(const GrStencilSettings& settings) {
|
||||
fStencilSettings = settings;
|
||||
}
|
||||
void disableStencil() { fStencilSettings.setDisabled(); }
|
||||
|
||||
// GrGpu subclass sets clip bit in the stencil buffer. The subclass is
|
||||
// free to clear the remaining bits to zero if masked clears are more
|
||||
|
@ -385,10 +406,6 @@ protected:
|
|||
unsigned int* ref,
|
||||
unsigned int* mask);
|
||||
|
||||
// stencil settings to clip drawing when stencil clipping is in effect
|
||||
// and the client isn't using the stencil test.
|
||||
static const GrStencilSettings* GetClipStencilSettings();
|
||||
|
||||
GrClipMaskManager fClipMaskManager;
|
||||
|
||||
struct GeometryPoolState {
|
||||
|
@ -402,6 +419,15 @@ protected:
|
|||
return fGeomPoolStateStack.back();
|
||||
}
|
||||
|
||||
// The state of the scissor is controlled by the clip manager
|
||||
struct ScissorState {
|
||||
bool fEnabled;
|
||||
GrIRect fRect;
|
||||
} fScissorState;
|
||||
|
||||
// The final stencil settings to use as determined by the clip manager.
|
||||
GrStencilSettings fStencilSettings;
|
||||
|
||||
// Derived classes need access to this so they can fill it out in their
|
||||
// constructors
|
||||
bool fConfigRenderSupport[kGrPixelConfigCount];
|
||||
|
|
|
@ -220,12 +220,13 @@ GR_STATIC_CONST_SAME_STENCIL(gDiffClip,
|
|||
0x0000 // set clip bit
|
||||
);
|
||||
|
||||
bool GrStencilSettings::GetClipPasses(SkRegion::Op op,
|
||||
bool canBeDirect,
|
||||
unsigned int stencilClipMask,
|
||||
bool invertedFill,
|
||||
int* numPasses,
|
||||
GrStencilSettings settings[kMaxStencilClipPasses]) {
|
||||
bool GrStencilSettings::GetClipPasses(
|
||||
SkRegion::Op op,
|
||||
bool canBeDirect,
|
||||
unsigned int stencilClipMask,
|
||||
bool invertedFill,
|
||||
int* numPasses,
|
||||
GrStencilSettings settings[kMaxStencilClipPasses]) {
|
||||
if (canBeDirect && !invertedFill) {
|
||||
*numPasses = 0;
|
||||
switch (op) {
|
||||
|
@ -249,10 +250,12 @@ bool GrStencilSettings::GetClipPasses(SkRegion::Op op,
|
|||
break;
|
||||
}
|
||||
if (1 == *numPasses) {
|
||||
settings[0].fFrontFuncRef |= stencilClipMask;
|
||||
settings[0].fFrontWriteMask |= stencilClipMask;
|
||||
settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
|
||||
settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
|
||||
settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fFuncRefs[kBack_Face] =
|
||||
settings[0].fFuncRefs[kFront_Face];
|
||||
settings[0].fWriteMasks[kBack_Face] =
|
||||
settings[0].fWriteMasks[kFront_Face];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -262,90 +265,111 @@ bool GrStencilSettings::GetClipPasses(SkRegion::Op op,
|
|||
// pass to select either the zeros or nonzeros.
|
||||
case SkRegion::kReplace_Op:
|
||||
*numPasses= 1;
|
||||
settings[0] = invertedFill ? gInvUserToClipReplace : gUserToClipReplace;
|
||||
settings[0].fFrontFuncMask &= ~stencilClipMask;
|
||||
settings[0].fFrontFuncRef |= stencilClipMask;
|
||||
settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
|
||||
settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
|
||||
settings[0] = invertedFill ? gInvUserToClipReplace :
|
||||
gUserToClipReplace;
|
||||
settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
|
||||
settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fFuncMasks[kBack_Face] =
|
||||
settings[0].fFuncMasks[kFront_Face];
|
||||
settings[0].fFuncRefs[kBack_Face] =
|
||||
settings[0].fFuncRefs[kFront_Face];
|
||||
break;
|
||||
case SkRegion::kIntersect_Op:
|
||||
*numPasses = 1;
|
||||
settings[0] = invertedFill ? gInvUserToClipIsect : gUserToClipIsect;
|
||||
settings[0].fFrontFuncRef = stencilClipMask;
|
||||
settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
|
||||
settings[0].fFuncRefs[kFront_Face] = stencilClipMask;
|
||||
settings[0].fFuncRefs[kBack_Face] =
|
||||
settings[0].fFuncRefs[kFront_Face];
|
||||
break;
|
||||
case SkRegion::kUnion_Op:
|
||||
*numPasses = 2;
|
||||
if (invertedFill) {
|
||||
settings[0] = gInvUserToClipUnionPass0;
|
||||
settings[0].fFrontFuncMask &= ~stencilClipMask;
|
||||
settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
|
||||
settings[0].fFrontFuncRef |= stencilClipMask;
|
||||
settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
|
||||
settings[0].fFrontWriteMask |= stencilClipMask;
|
||||
settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
|
||||
settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
|
||||
settings[0].fFuncMasks[kBack_Face] =
|
||||
settings[0].fFuncMasks[kFront_Face];
|
||||
settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fFuncRefs[kBack_Face] =
|
||||
settings[0].fFuncRefs[kFront_Face];
|
||||
settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fWriteMasks[kBack_Face] =
|
||||
settings[0].fWriteMasks[kFront_Face];
|
||||
|
||||
settings[1] = gInvUserToClipUnionPass1;
|
||||
settings[1].fFrontWriteMask &= ~stencilClipMask;
|
||||
settings[1].fBackWriteMask &= settings[1].fFrontWriteMask;
|
||||
settings[1].fWriteMasks[kFront_Face] &= ~stencilClipMask;
|
||||
settings[1].fWriteMasks[kBack_Face] &=
|
||||
settings[1].fWriteMasks[kFront_Face];
|
||||
|
||||
} else {
|
||||
settings[0] = gUserToClipUnionPass0;
|
||||
settings[0].fFrontFuncMask &= ~stencilClipMask;
|
||||
settings[0].fFrontFuncRef |= stencilClipMask;
|
||||
settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
|
||||
settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
|
||||
settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
|
||||
settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fFuncMasks[kBack_Face] =
|
||||
settings[0].fFuncMasks[kFront_Face];
|
||||
settings[0].fFuncRefs[kBack_Face] =
|
||||
settings[0].fFuncRefs[kFront_Face];
|
||||
|
||||
settings[1] = gUserToClipUnionPass1;
|
||||
settings[1].fFrontFuncRef |= stencilClipMask;
|
||||
settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
|
||||
settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[1].fFuncRefs[kBack_Face] =
|
||||
settings[1].fFuncRefs[kFront_Face];
|
||||
}
|
||||
break;
|
||||
case SkRegion::kXOR_Op:
|
||||
*numPasses = 2;
|
||||
if (invertedFill) {
|
||||
settings[0] = gInvUserToClipXorPass0;
|
||||
settings[0].fFrontFuncMask &= ~stencilClipMask;
|
||||
settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
|
||||
settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
|
||||
settings[0].fFuncMasks[kBack_Face] =
|
||||
settings[0].fFuncMasks[kFront_Face];
|
||||
|
||||
settings[1] = gInvUserToClipXorPass1;
|
||||
settings[1].fFrontFuncRef |= stencilClipMask;
|
||||
settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
|
||||
settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[1].fFuncRefs[kBack_Face] =
|
||||
settings[1].fFuncRefs[kFront_Face];
|
||||
} else {
|
||||
settings[0] = gUserToClipXorPass0;
|
||||
settings[0].fFrontFuncMask &= ~stencilClipMask;
|
||||
settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
|
||||
settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
|
||||
settings[0].fFuncMasks[kBack_Face] =
|
||||
settings[0].fFuncMasks[kFront_Face];
|
||||
|
||||
settings[1] = gUserToClipXorPass1;
|
||||
settings[1].fFrontFuncRef |= stencilClipMask;
|
||||
settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
|
||||
settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[1].fFuncRefs[kBack_Face] =
|
||||
settings[1].fFuncRefs[kFront_Face];
|
||||
}
|
||||
break;
|
||||
case SkRegion::kDifference_Op:
|
||||
*numPasses = 1;
|
||||
settings[0] = invertedFill ? gInvUserToClipDiff : gUserToClipDiff;
|
||||
settings[0].fFrontFuncRef |= stencilClipMask;
|
||||
settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
|
||||
settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fFuncRefs[kBack_Face] =
|
||||
settings[0].fFuncRefs[kFront_Face];
|
||||
break;
|
||||
case SkRegion::kReverseDifference_Op:
|
||||
if (invertedFill) {
|
||||
*numPasses = 1;
|
||||
settings[0] = gInvUserToClipRDiff;
|
||||
settings[0].fFrontWriteMask |= stencilClipMask;
|
||||
settings[0].fBackWriteMask = settings[0].fFrontWriteMask;
|
||||
settings[0].fWriteMasks[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fWriteMasks[kBack_Face] =
|
||||
settings[0].fWriteMasks[kFront_Face];
|
||||
} else {
|
||||
*numPasses = 2;
|
||||
settings[0] = gUserToClipRDiffPass0;
|
||||
settings[0].fFrontFuncMask &= ~stencilClipMask;
|
||||
settings[0].fBackFuncMask = settings[0].fFrontFuncMask;
|
||||
settings[0].fFrontFuncRef |= stencilClipMask;
|
||||
settings[0].fBackFuncRef = settings[0].fFrontFuncRef;
|
||||
settings[0].fFuncMasks[kFront_Face] &= ~stencilClipMask;
|
||||
settings[0].fFuncMasks[kBack_Face] =
|
||||
settings[0].fFuncMasks[kFront_Face];
|
||||
settings[0].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[0].fFuncRefs[kBack_Face] =
|
||||
settings[0].fFuncRefs[kFront_Face];
|
||||
|
||||
settings[1] = gUserToClipRDiffPass1;
|
||||
settings[1].fFrontFuncMask |= stencilClipMask;
|
||||
settings[1].fFrontFuncRef |= stencilClipMask;
|
||||
settings[1].fBackFuncMask = settings[1].fFrontFuncMask;
|
||||
settings[1].fBackFuncRef = settings[1].fFrontFuncRef;
|
||||
settings[1].fFuncMasks[kFront_Face] |= stencilClipMask;
|
||||
settings[1].fFuncRefs[kFront_Face] |= stencilClipMask;
|
||||
settings[1].fFuncMasks[kBack_Face] =
|
||||
settings[1].fFuncMasks[kFront_Face];
|
||||
settings[1].fFuncRefs[kBack_Face] =
|
||||
settings[1].fFuncRefs[kFront_Face];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -103,20 +103,14 @@ enum GrStencilFlags {
|
|||
* GrStencilSettings. (We hang our heads in shame.)
|
||||
*/
|
||||
struct GrStencilSettingsStruct {
|
||||
GrStencilOp fFrontPassOp : 8; // op to perform when front faces pass
|
||||
GrStencilOp fBackPassOp : 8; // op to perform when back faces pass
|
||||
GrStencilOp fFrontFailOp : 8; // op to perform when front faces fail
|
||||
GrStencilOp fBackFailOp : 8; // op to perform when back faces fail
|
||||
GrStencilFunc fFrontFunc : 8; // test function for front faces
|
||||
GrStencilFunc fBackFunc : 8; // test function for back faces
|
||||
int fPad0 : 8;
|
||||
int fPad1 : 8;
|
||||
unsigned short fFrontFuncMask; // mask for front face test
|
||||
unsigned short fBackFuncMask; // mask for back face test
|
||||
unsigned short fFrontFuncRef; // reference value for front face test
|
||||
unsigned short fBackFuncRef; // reference value for back face test
|
||||
unsigned short fFrontWriteMask; // stencil write mask for front faces
|
||||
unsigned short fBackWriteMask; // stencil write mask for back faces
|
||||
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)
|
||||
|
@ -125,9 +119,9 @@ GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) ==
|
|||
4*sizeof(uint8_t) + // ops
|
||||
2*sizeof(uint8_t) + // funcs
|
||||
2*sizeof(uint8_t) + // pads
|
||||
2*sizeof(unsigned short) + // func masks
|
||||
2*sizeof(unsigned short) + // ref values
|
||||
2*sizeof(unsigned short) + // write masks
|
||||
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
|
||||
|
@ -175,36 +169,65 @@ GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) ==
|
|||
class GrStencilSettings : private GrStencilSettingsStruct {
|
||||
|
||||
public:
|
||||
enum Face {
|
||||
kFront_Face = 0,
|
||||
kBack_Face = 1,
|
||||
};
|
||||
|
||||
GrStencilSettings() {
|
||||
fPad0 = fPad1 = 0;
|
||||
this->setDisabled();
|
||||
}
|
||||
|
||||
GrStencilOp frontPassOp() const { return fFrontPassOp; }
|
||||
GrStencilOp backPassOp() const { return fBackPassOp; }
|
||||
GrStencilOp frontFailOp() const { return fFrontFailOp; }
|
||||
GrStencilOp backFailOp() const { return fBackFailOp; }
|
||||
GrStencilFunc frontFunc() const { return fFrontFunc; }
|
||||
GrStencilFunc backFunc() const { return fBackFunc; }
|
||||
unsigned short frontFuncMask() const { return fFrontFuncMask; }
|
||||
unsigned short backFuncMask() const { return fBackFuncMask; }
|
||||
unsigned short frontFuncRef() const { return fFrontFuncRef; }
|
||||
unsigned short backFuncRef() const { return fBackFuncRef; }
|
||||
unsigned short frontWriteMask() const {return fFrontWriteMask; }
|
||||
unsigned short backWriteMask() const { return fBackWriteMask; }
|
||||
GrStencilOp frontPassOp() const { return static_cast<GrStencilOp>(fPassOps[kFront_Face]); }
|
||||
GrStencilOp backPassOp() const { return static_cast<GrStencilOp>(fPassOps[kBack_Face]); }
|
||||
GrStencilOp frontFailOp() const { return static_cast<GrStencilOp>(fFailOps[kFront_Face]); }
|
||||
GrStencilOp backFailOp() const { return static_cast<GrStencilOp>(fFailOps[kBack_Face]); }
|
||||
GrStencilFunc frontFunc() const { return static_cast<GrStencilFunc>(fFuncs[kFront_Face]); }
|
||||
GrStencilFunc backFunc() const { return static_cast<GrStencilFunc>(fFuncs[kBack_Face]); }
|
||||
uint16_t frontFuncMask() const { return fFuncMasks[kFront_Face]; }
|
||||
uint16_t backFuncMask() const { return fFuncMasks[kBack_Face]; }
|
||||
uint16_t frontFuncRef() const { return fFuncRefs[kFront_Face]; }
|
||||
uint16_t backFuncRef() const { return fFuncRefs[kBack_Face]; }
|
||||
uint16_t frontWriteMask() const { return fWriteMasks[kFront_Face]; }
|
||||
uint16_t backWriteMask() const { return fWriteMasks[kFront_Face]; }
|
||||
|
||||
void setFrontPassOp(GrStencilOp op) { fFrontPassOp = op; fFlags = 0;}
|
||||
void setBackPassOp(GrStencilOp op) { fBackPassOp = op; fFlags = 0;}
|
||||
void setFrontFailOp(GrStencilOp op) {fFrontFailOp = op; fFlags = 0;}
|
||||
void setBackFailOp(GrStencilOp op) { fBackFailOp = op; fFlags = 0;}
|
||||
void setFrontFunc(GrStencilFunc func) { fFrontFunc = func; fFlags = 0;}
|
||||
void setBackFunc(GrStencilFunc func) { fBackFunc = func; fFlags = 0;}
|
||||
void setFrontFuncMask(unsigned short mask) { fFrontFuncMask = mask; }
|
||||
void setBackFuncMask(unsigned short mask) { fBackFuncMask = mask; }
|
||||
void setFrontFuncRef(unsigned short ref) { fFrontFuncRef = ref; }
|
||||
void setBackFuncRef(unsigned short ref) { fBackFuncRef = ref; }
|
||||
void setFrontWriteMask(unsigned short writeMask) { fFrontWriteMask = writeMask; }
|
||||
void setBackWriteMask(unsigned short writeMask) { fBackWriteMask = writeMask; }
|
||||
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 setFrontPassOp(GrStencilOp op) { fPassOps[kFront_Face] = op; fFlags = 0;}
|
||||
void setBackPassOp(GrStencilOp op) { fPassOps[kBack_Face] = op; fFlags = 0;}
|
||||
void setFrontFailOp(GrStencilOp op) { fFailOps[kFront_Face] = op; fFlags = 0;}
|
||||
void setBackFailOp(GrStencilOp op) { fFailOps[kBack_Face] = op; fFlags = 0;}
|
||||
void setFrontFunc(GrStencilFunc func) { fFuncs[kFront_Face] = func; fFlags = 0;}
|
||||
void setBackFunc(GrStencilFunc func) { fFuncs[kBack_Face] = func; fFlags = 0;}
|
||||
void setFrontFuncMask(unsigned short mask) { fFuncMasks[kFront_Face] = mask; }
|
||||
void setBackFuncMask(unsigned short mask) { fFuncMasks[kBack_Face] = mask; }
|
||||
void setFrontFuncRef(unsigned short ref) { fFuncRefs[kFront_Face] = ref; }
|
||||
void setBackFuncRef(unsigned short ref) { fFuncRefs[kBack_Face] = ref; }
|
||||
void setFrontWriteMask(unsigned short writeMask) { fWriteMasks[kFront_Face] = writeMask; }
|
||||
void setBackWriteMask(unsigned short writeMask) { fWriteMasks[kBack_Face] = writeMask; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void setSame(GrStencilOp passOp,
|
||||
GrStencilOp failOp,
|
||||
|
@ -212,18 +235,12 @@ public:
|
|||
unsigned short funcMask,
|
||||
unsigned short funcRef,
|
||||
unsigned short writeMask) {
|
||||
fFrontPassOp = passOp;
|
||||
fBackPassOp = passOp;
|
||||
fFrontFailOp = failOp;
|
||||
fBackFailOp = failOp;
|
||||
fFrontFunc = func;
|
||||
fBackFunc = func;
|
||||
fFrontFuncMask = funcMask;
|
||||
fBackFuncMask = funcMask;
|
||||
fFrontFuncRef = funcRef;
|
||||
fBackFuncRef = funcRef;
|
||||
fFrontWriteMask = writeMask;
|
||||
fBackWriteMask = 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;
|
||||
}
|
||||
|
||||
|
@ -242,9 +259,9 @@ public:
|
|||
return false;
|
||||
}
|
||||
bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED(
|
||||
fFrontPassOp, fBackPassOp,
|
||||
fFrontFailOp, fBackFailOp,
|
||||
fFrontFunc ,fBackFunc);
|
||||
fPassOps[kFront_Face], fPassOps[kBack_Face],
|
||||
fFailOps[kFront_Face], fFailOps[kBack_Face],
|
||||
fFuncs[kFront_Face], fFuncs[kBack_Face]);
|
||||
fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
|
||||
return disabled;
|
||||
}
|
||||
|
@ -257,16 +274,16 @@ public:
|
|||
return false;
|
||||
}
|
||||
bool writes = GR_STENCIL_SETTINGS_DOES_WRITE(
|
||||
fFrontPassOp, fBackPassOp,
|
||||
fFrontFailOp, fBackFailOp,
|
||||
fFrontFunc, fBackFunc);
|
||||
fPassOps[kFront_Face], fPassOps[kBack_Face],
|
||||
fFailOps[kFront_Face], fFailOps[kBack_Face],
|
||||
fFuncs[kFront_Face], fFuncs[kBack_Face]);
|
||||
fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
|
||||
return writes;
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
// write an illegal value to the first member
|
||||
fFrontPassOp = (GrStencilOp)(uint8_t)-1;
|
||||
fPassOps[0] = (GrStencilOp)(uint8_t)-1;
|
||||
fFlags = 0;
|
||||
}
|
||||
|
||||
|
@ -339,13 +356,13 @@ GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
|
|||
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), \
|
||||
{(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), \
|
||||
{(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) \
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
|
||||
|
||||
#include "GrTemplates.h"
|
||||
#include "SkGr.h"
|
||||
#include "SkDescriptor.h"
|
||||
#include "SkGlyphCache.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "GrGpuGL.h"
|
||||
#include "GrGLStencilBuffer.h"
|
||||
#include "GrGLPath.h"
|
||||
#include "GrTemplates.h"
|
||||
#include "GrTypes.h"
|
||||
#include "SkTemplates.h"
|
||||
|
||||
|
@ -496,21 +497,16 @@ void GrGpuGL::onResetContext() {
|
|||
fHWBoundTextures[s] = NULL;
|
||||
}
|
||||
|
||||
fHWBounds.fScissorRect.invalidate();
|
||||
// set to true to force disableScissor to make a GL call.
|
||||
fHWBounds.fScissorEnabled = true;
|
||||
this->disableScissor();
|
||||
fHWScissorSettings.invalidate();
|
||||
|
||||
fHWBounds.fViewportRect.invalidate();
|
||||
fHWViewport.invalidate();
|
||||
|
||||
fHWStencilSettings.invalidate();
|
||||
// This is arbitrary. The above invalidate ensures a full setup of the
|
||||
// stencil on the next draw.
|
||||
fHWStencilClipMode = GrClipMaskManager::kRespectClip_StencilClipMode;
|
||||
fHWStencilTestEnabled = kUnknown_TriState;
|
||||
|
||||
fHWGeometryState.fIndexBuffer = NULL;
|
||||
fHWGeometryState.fVertexBuffer = NULL;
|
||||
|
||||
|
||||
fHWGeometryState.fArrayPtrsDirty = true;
|
||||
|
||||
fHWBoundRenderTarget = NULL;
|
||||
|
@ -1333,7 +1329,7 @@ GrPath* GrGpuGL::onCreatePath(const SkPath& inPath) {
|
|||
return path;
|
||||
}
|
||||
|
||||
void GrGpuGL::enableScissoring(const GrIRect& rect) {
|
||||
void GrGpuGL::flushScissor() {
|
||||
const GrDrawState& drawState = this->getDrawState();
|
||||
const GrGLRenderTarget* rt =
|
||||
static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget());
|
||||
|
@ -1341,28 +1337,31 @@ void GrGpuGL::enableScissoring(const GrIRect& rect) {
|
|||
GrAssert(NULL != rt);
|
||||
const GrGLIRect& vp = rt->getViewport();
|
||||
|
||||
GrGLIRect scissor;
|
||||
scissor.setRelativeTo(vp, rect.fLeft, rect.fTop,
|
||||
rect.width(), rect.height());
|
||||
if (scissor.contains(vp)) {
|
||||
disableScissor();
|
||||
return;
|
||||
if (fScissorState.fEnabled) {
|
||||
GrGLIRect scissor;
|
||||
scissor.setRelativeTo(vp,
|
||||
fScissorState.fRect.fLeft,
|
||||
fScissorState.fRect.fTop,
|
||||
fScissorState.fRect.width(),
|
||||
fScissorState.fRect.height());
|
||||
// if the scissor fully contains the viewport then we fall through and
|
||||
// disable the scissor test.
|
||||
if (!scissor.contains(vp)) {
|
||||
if (fHWScissorSettings.fRect != scissor) {
|
||||
scissor.pushToGLScissor(this->glInterface());
|
||||
fHWScissorSettings.fRect = scissor;
|
||||
}
|
||||
if (kYes_TriState != fHWScissorSettings.fEnabled) {
|
||||
GL_CALL(Enable(GR_GL_SCISSOR_TEST));
|
||||
fHWScissorSettings.fEnabled = kYes_TriState;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fHWBounds.fScissorRect != scissor) {
|
||||
scissor.pushToGLScissor(this->glInterface());
|
||||
fHWBounds.fScissorRect = scissor;
|
||||
}
|
||||
if (!fHWBounds.fScissorEnabled) {
|
||||
GL_CALL(Enable(GR_GL_SCISSOR_TEST));
|
||||
fHWBounds.fScissorEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGpuGL::disableScissor() {
|
||||
if (fHWBounds.fScissorEnabled) {
|
||||
if (kNo_TriState != fHWScissorSettings.fEnabled) {
|
||||
GL_CALL(Disable(GR_GL_SCISSOR_TEST));
|
||||
fHWBounds.fScissorEnabled = false;
|
||||
fHWScissorSettings.fEnabled = kNo_TriState;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1384,10 +1383,12 @@ void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
|
|||
}
|
||||
}
|
||||
this->flushRenderTarget(rect);
|
||||
if (NULL != rect)
|
||||
this->enableScissoring(*rect);
|
||||
else
|
||||
this->disableScissor();
|
||||
GrAutoTRestore<ScissorState> asr(&fScissorState);
|
||||
fScissorState.fEnabled = (NULL != rect);
|
||||
if (fScissorState.fEnabled) {
|
||||
fScissorState.fRect = *rect;
|
||||
}
|
||||
this->flushScissor();
|
||||
|
||||
GrGLfloat r, g, b, a;
|
||||
static const GrGLfloat scale255 = 1.f / 255.f;
|
||||
|
@ -1413,7 +1414,9 @@ void GrGpuGL::clearStencil() {
|
|||
|
||||
this->flushRenderTarget(&GrIRect::EmptyIRect());
|
||||
|
||||
this->disableScissor();
|
||||
GrAutoTRestore<ScissorState> asr(&fScissorState);
|
||||
fScissorState.fEnabled = false;
|
||||
this->flushScissor();
|
||||
|
||||
GL_CALL(StencilMask(0xffffffff));
|
||||
GL_CALL(ClearStencil(0));
|
||||
|
@ -1448,7 +1451,12 @@ void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) {
|
|||
value = 0;
|
||||
}
|
||||
this->flushRenderTarget(&GrIRect::EmptyIRect());
|
||||
this->enableScissoring(rect);
|
||||
|
||||
GrAutoTRestore<ScissorState> asr(&fScissorState);
|
||||
fScissorState.fEnabled = true;
|
||||
fScissorState.fRect = rect;
|
||||
this->flushScissor();
|
||||
|
||||
GL_CALL(StencilMask((uint32_t) clipStencilMask));
|
||||
GL_CALL(ClearStencil(value));
|
||||
GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
|
||||
|
@ -1625,9 +1633,9 @@ void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
|
|||
#endif
|
||||
fHWBoundRenderTarget = rt;
|
||||
const GrGLIRect& vp = rt->getViewport();
|
||||
if (fHWBounds.fViewportRect != vp) {
|
||||
if (fHWViewport != vp) {
|
||||
vp.pushToGLViewport(this->glInterface());
|
||||
fHWBounds.fViewportRect = vp;
|
||||
fHWViewport = vp;
|
||||
}
|
||||
}
|
||||
if (NULL == bound || !bound->isEmpty()) {
|
||||
|
@ -1747,28 +1755,25 @@ void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
|
|||
const GrGLIRect& vp = rt->getViewport();
|
||||
const GrIRect dirtyRect = rt->getResolveRect();
|
||||
GrGLIRect r;
|
||||
r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
|
||||
r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
|
||||
dirtyRect.width(), dirtyRect.height());
|
||||
|
||||
GrAutoTRestore<ScissorState> asr;
|
||||
if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) {
|
||||
// Apple's extension uses the scissor as the blit bounds.
|
||||
#if 1
|
||||
GL_CALL(Enable(GR_GL_SCISSOR_TEST));
|
||||
GL_CALL(Scissor(r.fLeft, r.fBottom,
|
||||
r.fWidth, r.fHeight));
|
||||
asr.reset(&fScissorState);
|
||||
fScissorState.fEnabled = true;
|
||||
fScissorState.fRect = dirtyRect;
|
||||
this->flushScissor();
|
||||
GL_CALL(ResolveMultisampleFramebuffer());
|
||||
fHWBounds.fScissorRect.invalidate();
|
||||
fHWBounds.fScissorEnabled = true;
|
||||
#else
|
||||
this->enableScissoring(dirtyRect);
|
||||
GL_CALL(ResolveMultisampleFramebuffer());
|
||||
#endif
|
||||
} else {
|
||||
if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) {
|
||||
// this respects the scissor during the blit, so disable it.
|
||||
GrAssert(GrGLCaps::kDesktopEXT_MSFBOType ==
|
||||
this->glCaps().msFBOType());
|
||||
this->disableScissor();
|
||||
asr.reset(&fScissorState);
|
||||
fScissorState.fEnabled = false;
|
||||
this->flushScissor();
|
||||
}
|
||||
int right = r.fLeft + r.fWidth;
|
||||
int top = r.fBottom + r.fHeight;
|
||||
|
@ -1832,16 +1837,16 @@ GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
|
|||
}
|
||||
|
||||
void set_gl_stencil(const GrGLInterface* gl,
|
||||
const GrStencilSettings& settings,
|
||||
GrGLenum glFace,
|
||||
GrStencilFunc func,
|
||||
GrStencilOp failOp,
|
||||
GrStencilOp passOp,
|
||||
unsigned int ref,
|
||||
unsigned int mask,
|
||||
unsigned int writeMask) {
|
||||
GrGLenum glFunc = gr_to_gl_stencil_func(func);
|
||||
GrGLenum glFailOp = gr_to_gl_stencil_op(failOp);
|
||||
GrGLenum glPassOp = gr_to_gl_stencil_op(passOp);
|
||||
GrStencilSettings::Face grFace) {
|
||||
GrGLenum glFunc = gr_to_gl_stencil_func(settings.func(grFace));
|
||||
GrGLenum glFailOp = gr_to_gl_stencil_op(settings.failOp(grFace));
|
||||
GrGLenum glPassOp = gr_to_gl_stencil_op(settings.passOp(grFace));
|
||||
|
||||
GrGLint ref = settings.funcRef(grFace);
|
||||
GrGLint mask = settings.funcMask(grFace);
|
||||
GrGLint writeMask = settings.writeMask(grFace);
|
||||
|
||||
if (GR_GL_FRONT_AND_BACK == glFace) {
|
||||
// we call the combined func just in case separate stencil is not
|
||||
|
@ -1858,112 +1863,36 @@ void set_gl_stencil(const GrGLInterface* gl,
|
|||
}
|
||||
|
||||
void GrGpuGL::flushStencil() {
|
||||
const GrDrawState& drawState = this->getDrawState();
|
||||
|
||||
// use stencil for clipping if clipping is enabled and the clip
|
||||
// has been written into the stencil.
|
||||
GrClipMaskManager::StencilClipMode clipMode;
|
||||
if (fClipMaskManager.isClipInStencil() &&
|
||||
drawState.isClipState()) {
|
||||
clipMode = GrClipMaskManager::kRespectClip_StencilClipMode;
|
||||
// We can't be modifying the clip and respecting it at the same time.
|
||||
GrAssert(!drawState.isStateFlagEnabled(kModifyStencilClip_StateBit));
|
||||
} else if (drawState.isStateFlagEnabled(kModifyStencilClip_StateBit)) {
|
||||
clipMode = GrClipMaskManager::kModifyClip_StencilClipMode;
|
||||
} else {
|
||||
clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode;
|
||||
}
|
||||
|
||||
// The caller may not be using the stencil buffer but we may need to enable
|
||||
// it in order to respect a stencil clip.
|
||||
const GrStencilSettings* settings = &drawState.getStencil();
|
||||
if (settings->isDisabled() &&
|
||||
GrClipMaskManager::kRespectClip_StencilClipMode == clipMode) {
|
||||
settings = GetClipStencilSettings();
|
||||
}
|
||||
|
||||
// TODO: dynamically attach a stencil buffer
|
||||
int stencilBits = 0;
|
||||
GrStencilBuffer* stencilBuffer =
|
||||
drawState.getRenderTarget()->getStencilBuffer();
|
||||
if (NULL != stencilBuffer) {
|
||||
stencilBits = stencilBuffer->bits();
|
||||
}
|
||||
GrAssert(stencilBits || settings->isDisabled());
|
||||
|
||||
bool updateStencilSettings = stencilBits > 0 &&
|
||||
((fHWStencilSettings != *settings) ||
|
||||
(fHWStencilClipMode != clipMode));
|
||||
if (updateStencilSettings) {
|
||||
if (settings->isDisabled()) {
|
||||
if (fStencilSettings.isDisabled()) {
|
||||
if (kNo_TriState != fHWStencilTestEnabled) {
|
||||
GL_CALL(Disable(GR_GL_STENCIL_TEST));
|
||||
} else {
|
||||
fHWStencilTestEnabled = kNo_TriState;
|
||||
}
|
||||
} else {
|
||||
if (kYes_TriState != fHWStencilTestEnabled) {
|
||||
GL_CALL(Enable(GR_GL_STENCIL_TEST));
|
||||
#if GR_DEBUG
|
||||
if (!this->getCaps().fStencilWrapOpsSupport) {
|
||||
GrAssert(settings->frontPassOp() != kIncWrap_StencilOp);
|
||||
GrAssert(settings->frontPassOp() != kDecWrap_StencilOp);
|
||||
GrAssert(settings->frontFailOp() != kIncWrap_StencilOp);
|
||||
GrAssert(settings->backFailOp() != kDecWrap_StencilOp);
|
||||
GrAssert(settings->backPassOp() != kIncWrap_StencilOp);
|
||||
GrAssert(settings->backPassOp() != kDecWrap_StencilOp);
|
||||
GrAssert(settings->backFailOp() != kIncWrap_StencilOp);
|
||||
GrAssert(settings->frontFailOp() != kDecWrap_StencilOp);
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int frontRef = settings->frontFuncRef();
|
||||
unsigned int frontMask = settings->frontFuncMask();
|
||||
unsigned int frontWriteMask = settings->frontWriteMask();
|
||||
|
||||
GrStencilFunc frontFunc =
|
||||
fClipMaskManager.adjustStencilParams(settings->frontFunc(),
|
||||
clipMode,
|
||||
stencilBits,
|
||||
&frontRef,
|
||||
&frontMask,
|
||||
&frontWriteMask);
|
||||
fHWStencilTestEnabled = kYes_TriState;
|
||||
}
|
||||
}
|
||||
if (fHWStencilSettings != fStencilSettings) {
|
||||
if (!fStencilSettings.isDisabled()) {
|
||||
if (this->getCaps().fTwoSidedStencilSupport) {
|
||||
unsigned int backRef = settings->backFuncRef();
|
||||
unsigned int backMask = settings->backFuncMask();
|
||||
unsigned int backWriteMask = settings->backWriteMask();
|
||||
|
||||
GrStencilFunc backFunc =
|
||||
fClipMaskManager.adjustStencilParams(settings->frontFunc(),
|
||||
clipMode,
|
||||
stencilBits,
|
||||
&backRef,
|
||||
&backMask,
|
||||
&backWriteMask);
|
||||
set_gl_stencil(this->glInterface(),
|
||||
fStencilSettings,
|
||||
GR_GL_FRONT,
|
||||
frontFunc,
|
||||
settings->frontFailOp(),
|
||||
settings->frontPassOp(),
|
||||
frontRef,
|
||||
frontMask,
|
||||
frontWriteMask);
|
||||
GrStencilSettings::kFront_Face);
|
||||
set_gl_stencil(this->glInterface(),
|
||||
fStencilSettings,
|
||||
GR_GL_BACK,
|
||||
backFunc,
|
||||
settings->backFailOp(),
|
||||
settings->backPassOp(),
|
||||
backRef,
|
||||
backMask,
|
||||
backWriteMask);
|
||||
GrStencilSettings::kBack_Face);
|
||||
} else {
|
||||
set_gl_stencil(this->glInterface(),
|
||||
fStencilSettings,
|
||||
GR_GL_FRONT_AND_BACK,
|
||||
frontFunc,
|
||||
settings->frontFailOp(),
|
||||
settings->frontPassOp(),
|
||||
frontRef,
|
||||
frontMask,
|
||||
frontWriteMask);
|
||||
GrStencilSettings::kFront_Face);
|
||||
}
|
||||
}
|
||||
fHWStencilSettings = *settings;
|
||||
fHWStencilClipMode = clipMode;
|
||||
fHWStencilSettings = fStencilSettings;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,8 +108,6 @@ protected:
|
|||
uint32_t vertexCount,
|
||||
uint32_t numVertices) SK_OVERRIDE;
|
||||
virtual void onGpuStencilPath(const GrPath&, GrPathFill) SK_OVERRIDE;
|
||||
virtual void enableScissoring(const GrIRect& rect) SK_OVERRIDE;
|
||||
virtual void disableScissor() SK_OVERRIDE;
|
||||
|
||||
virtual void clearStencil() SK_OVERRIDE;
|
||||
virtual void clearStencilClip(const GrIRect& rect,
|
||||
|
@ -206,6 +204,10 @@ private:
|
|||
};
|
||||
|
||||
// binds the texture and sets its texture params
|
||||
// This may also perform a downsample on the src texture which may or may
|
||||
// not modify the scissor test and rect. So in flushGraphicsState a
|
||||
// call to flushScissor must occur after all textures have been flushed via
|
||||
// this function.
|
||||
void flushBoundTextureAndParams(int stage);
|
||||
|
||||
// sets the texture matrix and domain for the currently bound program
|
||||
|
@ -232,6 +234,10 @@ private:
|
|||
// flushes dithering, color-mask, and face culling stat
|
||||
void flushMiscFixedFunctionState();
|
||||
|
||||
// flushes the scissor. see the note on flushBoundTextureAndParams about
|
||||
// flushing the scissor after that function is called.
|
||||
void flushScissor();
|
||||
|
||||
static void DeleteProgram(const GrGLInterface* gl,
|
||||
CachedData* programData);
|
||||
|
||||
|
@ -304,19 +310,24 @@ private:
|
|||
GrColor fHWConstAttribColor;
|
||||
GrColor fHWConstAttribCoverage;
|
||||
|
||||
// last scissor / viewport scissor state seen by the GL.
|
||||
struct {
|
||||
bool fScissorEnabled;
|
||||
GrGLIRect fScissorRect;
|
||||
GrGLIRect fViewportRect;
|
||||
} fHWBounds;
|
||||
|
||||
enum TriState {
|
||||
kNo_TriState,
|
||||
kYes_TriState,
|
||||
kUnknown_TriState
|
||||
};
|
||||
|
||||
// last scissor / viewport scissor state seen by the GL.
|
||||
struct {
|
||||
TriState fEnabled;
|
||||
GrGLIRect fRect;
|
||||
void invalidate() {
|
||||
fEnabled = kUnknown_TriState;
|
||||
fRect.invalidate();
|
||||
}
|
||||
} fHWScissorSettings;
|
||||
|
||||
GrGLIRect fHWViewport;
|
||||
|
||||
struct {
|
||||
size_t fVertexOffset;
|
||||
GrVertexLayout fVertexLayout;
|
||||
|
@ -349,8 +360,8 @@ private:
|
|||
}
|
||||
} fHWAAState;
|
||||
|
||||
GrClipMaskManager::StencilClipMode fHWStencilClipMode;
|
||||
GrStencilSettings fHWStencilSettings;
|
||||
GrStencilSettings fHWStencilSettings;
|
||||
TriState fHWStencilTestEnabled;
|
||||
|
||||
GrDrawState::DrawFace fHWDrawFace;
|
||||
TriState fHWWriteToColor;
|
||||
|
|
|
@ -454,6 +454,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
|
|||
}
|
||||
}
|
||||
this->flushColorMatrix();
|
||||
this->flushScissor();
|
||||
|
||||
GrIRect* rect = NULL;
|
||||
GrIRect clipBounds;
|
||||
|
|
Загрузка…
Ссылка в новой задаче