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:
bsalomon@google.com 2012-06-21 19:58:20 +00:00
Родитель 8f7e1dac5c
Коммит a320194e42
14 изменённых файлов: 527 добавлений и 440 удалений

Просмотреть файл

@ -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;