aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrClipMaskManager.cpp286
-rw-r--r--src/gpu/GrClipMaskManager.h57
-rw-r--r--src/gpu/GrDrawTarget.h1
-rw-r--r--src/gpu/GrGpu.cpp20
-rw-r--r--src/gpu/GrGpu.h38
-rw-r--r--src/gpu/GrStencil.cpp126
-rw-r--r--src/gpu/GrStencil.h151
-rw-r--r--src/gpu/SkGrFontScaler.cpp2
-rw-r--r--src/gpu/gl/GrGpuGL.cpp235
-rw-r--r--src/gpu/gl/GrGpuGL.h33
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp1
11 files changed, 517 insertions, 433 deletions
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 55a8192c3f..c16b4106a1 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -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;
- }
-
- 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!
+ // 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;
}
- 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;
-
- 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");
+ GrStencilSettings::Face face = GrStencilSettings::kFront_Face;
+ bool twoSided = fGpu->getCaps().fTwoSidedStencilSupport;
+
+ 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;
}
- const GrStencilFunc* table = gSpecialToBasicStencilFunc[respectClip];
- func = table[func - kBasicStencilFuncCount];
- GrAssert(func >= 0 && func < kBasicStencilFuncCount);
- } else {
- *mask &= userBits;
- *ref &= 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;
+ }
+ }
+ if (!twoSided) {
+ settings->copyFrontSettingsToBack();
}
- return func;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 1ceee16bec..144c042a81 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -28,19 +28,6 @@ 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;
};
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 6e5bc6764a..7bd330788c 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -16,6 +16,7 @@
#include "GrIndexBuffer.h"
#include "GrMatrix.h"
#include "GrRefCnt.h"
+#include "GrTemplates.h"
#include "SkXfermode.h"
#include "SkTLazy.h"
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index c8c983cbbe..132d2ed4db 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -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;
}
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index edbad34134..53c74249dd 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -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];
diff --git a/src/gpu/GrStencil.cpp b/src/gpu/GrStencil.cpp
index ab0e78c6a8..8d7534aa4c 100644
--- a/src/gpu/GrStencil.cpp
+++ b/src/gpu/GrStencil.cpp
@@ -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:
diff --git a/src/gpu/GrStencil.h b/src/gpu/GrStencil.h
index bba5aa67bf..3a7595a796 100644
--- a/src/gpu/GrStencil.h
+++ b/src/gpu/GrStencil.h
@@ -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; }
-
- 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 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]; }
+
+ 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) \
diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp
index d2e099b03d..430b5993eb 100644
--- a/src/gpu/SkGrFontScaler.cpp
+++ b/src/gpu/SkGrFontScaler.cpp
@@ -7,7 +7,7 @@
*/
-
+#include "GrTemplates.h"
#include "SkGr.h"
#include "SkDescriptor.h"
#include "SkGlyphCache.h"
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 5c1764cf29..76a7a63361 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -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 (fHWBounds.fScissorRect != scissor) {
- scissor.pushToGLScissor(this->glInterface());
- fHWBounds.fScissorRect = scissor;
- }
- if (!fHWBounds.fScissorEnabled) {
- GL_CALL(Enable(GR_GL_SCISSOR_TEST));
- fHWBounds.fScissorEnabled = true;
+ 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;
+ }
}
-}
-
-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));
- GL_CALL(ResolveMultisampleFramebuffer());
- fHWBounds.fScissorRect.invalidate();
- fHWBounds.fScissorEnabled = true;
-#else
- this->enableScissoring(dirtyRect);
+ asr.reset(&fScissorState);
+ fScissorState.fEnabled = true;
+ fScissorState.fRect = dirtyRect;
+ this->flushScissor();
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;
}
}
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 51e49ec1ec..6220efafe4 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -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;
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index f8d71ffbf4..3ad352070a 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -454,6 +454,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
}
}
this->flushColorMatrix();
+ this->flushScissor();
GrIRect* rect = NULL;
GrIRect clipBounds;