Don't use GrDrawTarget's AA state bit to convey whether to do custom-aa

Review URL: http://codereview.appspot.com/5314061/



git-svn-id: http://skia.googlecode.com/svn/trunk@2539 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-10-27 12:34:25 +00:00
parent 1e7281675d
commit 289533ada6
16 changed files with 144 additions and 141 deletions

View File

@ -585,9 +585,9 @@ private:
GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);
GrPathRenderer* getPathRenderer(const GrDrawTarget* target,
const GrPath& path,
GrPathFill fill);
GrPathRenderer* getPathRenderer(const GrPath& path,
GrPathFill fill,
bool antiAlias);
struct OffscreenRecord;

View File

@ -106,20 +106,15 @@ GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
fQuadsIndexBuffer->unref();
}
bool GrAAHairLinePathRenderer::supportsAA(const GrDrawTarget* target,
const SkPath& path,
GrPathFill fill) const {
return kHairLine_PathFill == fill;
}
bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target,
bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget::Caps& targetCaps,
const SkPath& path,
GrPathFill fill) const {
GrPathFill fill,
bool antiAlias) const {
static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask |
SkPath::kQuad_SegmentMask;
return (kHairLine_PathFill == fill &&
target->isAntialiasState() &&
(target->getCaps().fShaderDerivativeSupport ||
antiAlias &&
(targetCaps.fShaderDerivativeSupport ||
!(gReqDerivMask & path.getSegmentMasks())));
}

View File

@ -17,18 +17,16 @@ public:
static GrPathRenderer* Create(GrContext* context);
// GrPathRenderer overrides
virtual bool supportsAA(const GrDrawTarget* target,
const SkPath& path,
GrPathFill fill) const;
virtual bool canDrawPath(const GrDrawTarget* target,
virtual bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
const SkPath& path,
GrPathFill fill) const;
virtual void drawPath(GrDrawTarget::StageBitfield stages);
GrPathFill fill,
bool antiAlias) const SK_OVERRIDE;
virtual void drawPath(GrDrawTarget::StageBitfield stages) SK_OVERRIDE;
protected:
// GrPathRenderer overrides
virtual void pathWillClear();
virtual void pathWillClear() SK_OVERRIDE;
private:
void resetGeom();

View File

@ -333,7 +333,7 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture(TextureKey key,
fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
fGpu->disableState(GrDrawTarget::kDither_StateBit |
GrDrawTarget::kClip_StateBit |
GrDrawTarget::kAntialias_StateBit);
GrDrawTarget::kHWAntialias_StateBit);
GrSamplerState::Filter filter;
// if filtering is not desired then we want to ensure all
// texels in the resampled image are copies of texels from
@ -664,9 +664,6 @@ bool GrContext::doOffscreenAA(GrDrawTarget* target,
#if !GR_USE_OFFSCREEN_AA
return false;
#else
if (!target->isAntialiasState()) {
return false;
}
// Line primitves are always rasterized as 1 pixel wide.
// Super-sampling would make them too thin but MSAA would be OK.
if (isHairLines &&
@ -778,6 +775,9 @@ void GrContext::setupOffscreenAAPass1(GrDrawTarget* target,
tempPaint.reset();
SetPaint(tempPaint, target);
target->setRenderTarget(offRT0);
#if PREFER_MSAA_OFFSCREEN_AA
target->enableState(GrDrawTarget::kHWAntialias_StateBit);
#endif
GrMatrix transM;
int left = boundRect.fLeft + tileX * record->fTileSizeX;
@ -1166,16 +1166,12 @@ static bool apply_aa_to_rect(GrDrawTarget* target,
bool* useVertexCoverage) {
// we use a simple alpha ramp to do aa on axis-aligned rects
// do AA with alpha ramp if the caller requested AA, the rect
// will be axis-aligned,the render target is not
// multisampled, and the rect won't land on integer coords.
if (!target->isAntialiasState()) {
return false;
}
// will be axis-aligned, and the rect won't land on integer coords.
// we are keeping around the "tweak the alpha" trick because
// it is our only hope for the fixed-pipe implementation.
// In a shader implementation we can give a separate coverage input
// TODO: remove this ugliness when we drop the fixed-pipe impl
*useVertexCoverage = false;
if (!target->canTweakAlphaForCoverage()) {
if (target->getCaps().fSupportPerVertexCoverage) {
@ -1238,8 +1234,11 @@ void GrContext::drawRect(const GrPaint& paint,
GrRect devRect = rect;
GrMatrix combinedMatrix;
bool useVertexCoverage;
bool doAA = apply_aa_to_rect(target, rect, width, matrix,
&combinedMatrix, &devRect, &useVertexCoverage);
bool needAA = paint.fAntiAlias &&
!this->getRenderTarget()->isMultisampled();
bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
&combinedMatrix, &devRect,
&useVertexCoverage);
if (doAA) {
GrDrawTarget::AutoViewMatrixRestore avm(target);
@ -1490,6 +1489,8 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
// An Assumption here is that path renderer would use some form of tweaking
// the src color (either the input alpha or in the frag shader) to implement
// aa. If we have some future driver-mojo path AA that can do the right
@ -1498,10 +1499,22 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
#if GR_DEBUG
GrPrintf("Turning off AA to correctly apply blend.\n");
#endif
target->disableState(GrDrawTarget::kAntialias_StateBit);
prAA = false;
}
GrPathRenderer* pr = this->getPathRenderer(target, path, fill);
bool doOSAA = false;
GrPathRenderer* pr = NULL;
if (prAA) {
pr = this->getPathRenderer(path, fill, true);
if (NULL == pr) {
prAA = false;
doOSAA = this->doOffscreenAA(target, kHairLine_PathFill == fill);
pr = this->getPathRenderer(path, fill, false);
}
} else {
pr = this->getPathRenderer(path, fill, false);
}
if (NULL == pr) {
#if GR_DEBUG
GrPrintf("Unable to find path renderer compatible with path.\n");
@ -1509,12 +1522,10 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
return;
}
GrPathRenderer::AutoClearPath arp(pr, target, &path, fill, translate);
GrPathRenderer::AutoClearPath arp(pr, target, &path, fill, prAA, translate);
GrDrawTarget::StageBitfield stageMask = paint.getActiveStageMask();
if (!pr->supportsAA(target, path, fill) &&
this->doOffscreenAA(target, kHairLine_PathFill == fill)) {
if (doOSAA) {
bool needsStencil = pr->requiresStencilPass(target, path, fill);
// compute bounds as intersection of rt size, clip, and path
@ -1723,9 +1734,9 @@ void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
target->disableState(GrDrawTarget::kDither_StateBit);
}
if (paint.fAntiAlias) {
target->enableState(GrDrawTarget::kAntialias_StateBit);
target->enableState(GrDrawTarget::kHWAntialias_StateBit);
} else {
target->disableState(GrDrawTarget::kAntialias_StateBit);
target->disableState(GrDrawTarget::kHWAntialias_StateBit);
}
target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
target->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
@ -1763,14 +1774,15 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
return target;
}
GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
const GrPath& path,
GrPathFill fill) {
GrPathRenderer* GrContext::getPathRenderer(const GrPath& path,
GrPathFill fill,
bool antiAlias) {
if (NULL == fPathRendererChain) {
fPathRendererChain =
new GrPathRendererChain(this, GrPathRendererChain::kNone_UsageFlag);
}
return fPathRendererChain->getPathRenderer(target, path, fill);
return fPathRendererChain->getPathRenderer(fGpu->getCaps(), path,
fill, antiAlias);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -25,6 +25,16 @@ GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
fTarget = NULL;
}
bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget::Caps& targetCaps,
const SkPath& path,
GrPathFill fill,
bool antiAlias) const {
// this class can draw any path with any fill but doesn't do any
// anti-aliasing.
return !antiAlias;
}
////////////////////////////////////////////////////////////////////////////////
// Stencil rules for paths
@ -187,7 +197,7 @@ static inline bool single_pass_path(const GrDrawTarget& target,
}
bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
const GrPath& path,
const GrPath& path,
GrPathFill fill) const {
return !single_pass_path(*target, path, fill);
}

View File

@ -20,16 +20,17 @@ public:
GrDefaultPathRenderer(bool separateStencilSupport,
bool stencilWrapOpsSupport);
virtual bool canDrawPath(const GrDrawTarget* target,
virtual bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
const SkPath& path,
GrPathFill fill) const { return true; }
GrPathFill fill,
bool antiAlias) const SK_OVERRIDE;
virtual bool requiresStencilPass(const GrDrawTarget* target,
const SkPath& path,
GrPathFill fill) const;
GrPathFill fill) const SK_OVERRIDE;
virtual void drawPath(GrDrawTarget::StageBitfield stages);
virtual void drawPathToStencil();
virtual void drawPath(GrDrawTarget::StageBitfield stages) SK_OVERRIDE;
virtual void drawPathToStencil() SK_OVERRIDE;
protected:
virtual void pathWillClear();

View File

@ -999,7 +999,7 @@ bool GrDrawTarget::willUseHWAALines() const {
// but not in a premul-alpha way. So we only use them when our alpha
// is 0xff and tweaking the color for partial coverage is OK
if (!fCaps.fHWAALineSupport ||
!(kAntialias_StateBit & fCurrDrawState.fFlagBits)) {
!(kHWAntialias_StateBit & fCurrDrawState.fFlagBits)) {
return false;
}
BlendOptFlags opts = this->getBlendOpts();

View File

@ -114,23 +114,31 @@ public:
* default to disabled.
*/
enum StateBits {
kDither_StateBit = 0x01, //<! Perform color dithering
kAntialias_StateBit = 0x02, //<! Perform anti-aliasing. The render-
// target must support some form of AA
// (msaa, coverage sampling, etc). For
// GrGpu-created rendertarget/textures
// this is controlled by parameters
// passed to createTexture.
kClip_StateBit = 0x04, //<! Controls whether drawing is clipped
// against the region specified by
// setClip.
kNoColorWrites_StateBit = 0x08, //<! If set it disables writing colors.
// Useful while performing stencil
// ops.
kEdgeAAConcave_StateBit = 0x10,//<! If set, edge AA will test edge
// pairs for convexity while
// rasterizing. Set this if the
// source polygon is non-convex.
/**
* Perform dithering. TODO: Re-evaluate whether we need this bit
*/
kDither_StateBit = 0x01,
/**
* Perform HW anti-aliasing. This means either HW FSAA, if supported
* by the render target, or smooth-line rendering if a line primitive
* is drawn and line smoothing is supported by the 3D API.
*/
kHWAntialias_StateBit = 0x02,
/**
* Draws will respect the clip, otherwise the clip is ignored.
*/
kClip_StateBit = 0x04,
/**
* Disables writing to the color buffer. Useful when performing stencil
* operations.
*/
kNoColorWrites_StateBit = 0x08,
/**
* Modifies the behavior of edge AA specified by setEdgeAA. If set,
* will test edge pairs for convexity when rasterizing. Set this if the
* source polygon is non-convex.
*/
kEdgeAAConcave_StateBit = 0x10,
// subclass may use additional bits internally
kDummyStateBit,
kLastPublicStateBit = kDummyStateBit-1
@ -477,8 +485,8 @@ public:
return 0 != (fCurrDrawState.fFlagBits & kDither_StateBit);
}
bool isAntialiasState() const {
return 0 != (fCurrDrawState.fFlagBits & kAntialias_StateBit);
bool isHWAntialiasState() const {
return 0 != (fCurrDrawState.fFlagBits & kHWAntialias_StateBit);
}
bool isClipState() const {

View File

@ -600,7 +600,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
}
canRenderDirectToStencil =
!pr->requiresStencilPass(this, *clipPath, fill);
arp.set(pr, this, clipPath, fill, NULL);
arp.set(pr, this, clipPath, fill, false, NULL);
}
GrSetOp op = (c == start) ? startOp : clip.getOp(c);
@ -684,7 +684,8 @@ GrPathRenderer* GrGpu::getClipPathRenderer(const GrPath& path,
new GrPathRendererChain(this->getContext(),
GrPathRendererChain::kNonAAOnly_UsageFlag);
}
return fPathRendererChain->getPathRenderer(this, path, fill);
return fPathRendererChain->getPathRenderer(this->getCaps(),
path, fill, false);
}

View File

@ -1798,7 +1798,7 @@ void GrGpuGL::flushAAState(GrPrimitiveType type) {
fHWAAState.fMSAAEnabled = false;
}
} else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
!!(kAntialias_StateBit & fCurrDrawState.fFlagBits) !=
SkToBool(kHWAntialias_StateBit & fCurrDrawState.fFlagBits) !=
fHWAAState.fMSAAEnabled) {
if (fHWAAState.fMSAAEnabled) {
GL_CALL(Disable(GR_GL_MULTISAMPLE));

View File

@ -16,6 +16,7 @@ GrPathRenderer::GrPathRenderer()
void GrPathRenderer::setPath(GrDrawTarget* target,
const SkPath* path,
GrPathFill fill,
bool antiAlias,
const GrPoint* translate) {
GrAssert(NULL == fPath);
GrAssert(NULL == fTarget);
@ -24,6 +25,7 @@ void GrPathRenderer::setPath(GrDrawTarget* target,
fTarget = target;
fPath = path;
fFill = fill;
fAntiAlias = antiAlias;
if (NULL != translate) {
fTranslate = *translate;
} else {

View File

@ -24,7 +24,7 @@ struct GrPoint;
* Paths may be drawn multiple times as when tiling for supersampling. The
* calls on GrPathRenderer to draw a path will look like this:
*
* pr->setPath(target, path, fill, translate); // sets the path to draw
* pr->setPath(target, path, fill, aa, translate); // sets the path to draw
* pr->drawPath(...); // draw the path
* pr->drawPath(...);
* ...
@ -54,27 +54,20 @@ public:
* Returns true if this path renderer is able to render the path.
* Returning false allows the caller to fallback to another path renderer.
* When searching for a path renderer capable of rendering a path this
* function is called. The path renderer can examine the path, fill rule,
* and draw settings that will be used (via the targetparameter). If "true"
* is reported note that the caller is permitted to make modifications to
* the following settings of the target between the calls to canDrawPath and
* drawPath:
* 1. view matrix: The matrix at drawPath time may have additional scale
* scale and translation applied
* 2. render target: The render target may change between canDrawPath
* and drawPath.
* The GrPathRenderer subclass's decision about whether to return true
* or false in its implementation of this function should consider these
* possible state changes.
* function is called.
*
* @param path The path to draw
* @param fill The fill rule to use
* @param targetCaps The caps of the draw target that will be used to draw
* the path.
* @param path The path to draw
* @param fill The fill rule to use
* @param antiAlias True if anti-aliasing is required.
*
* @return true if the path can be drawn by this object, false otherwise.
*/
virtual bool canDrawPath(const GrDrawTarget* target,
virtual bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
const SkPath& path,
GrPathFill fill) const = 0;
GrPathFill fill,
bool antiAlias) const = 0;
/**
* For complex clips Gr uses the stencil buffer. The path renderer must be
@ -101,15 +94,6 @@ public:
const SkPath& path,
GrPathFill fill) const { return false; }
/**
* @return true if the path renderer can perform anti-aliasing (aside from
* having FSAA enabled for a render target). Target is provided to
* communicate the draw state (blend mode, stage settings, etc).
*/
virtual bool supportsAA(const GrDrawTarget* target,
const SkPath& path,
GrPathFill fill) const { return false; }
/**
* Sets the path to render and target to render into. All calls to drawPath
* and drawPathToStencil must occur between setPath and clearPath. The
@ -125,12 +109,14 @@ public:
* @param target the target to draw into.
* @param path the path to draw.
* @param fill the fill rule to apply.
* @param antiAlias perform antiAliasing when drawing the path.
* @param translate optional additional translation to apply to
* the path. NULL means (0,0).
*/
void setPath(GrDrawTarget* target,
const SkPath* path,
GrPathFill fill,
bool antiAlias,
const GrPoint* translate);
/**
@ -179,24 +165,26 @@ public:
fPathRenderer = NULL;
}
AutoClearPath(GrPathRenderer* pr,
GrDrawTarget* target,
const SkPath* path,
GrPathFill fill,
const GrPoint* translate) {
GrDrawTarget* target,
const SkPath* path,
GrPathFill fill,
bool antiAlias,
const GrPoint* translate) {
GrAssert(NULL != pr);
pr->setPath(target, path, fill, translate);
pr->setPath(target, path, fill, antiAlias, translate);
fPathRenderer = pr;
}
void set(GrPathRenderer* pr,
GrDrawTarget* target,
const SkPath* path,
GrPathFill fill,
bool antiAlias,
const GrPoint* translate) {
if (NULL != fPathRenderer) {
fPathRenderer->clearPath();
}
GrAssert(NULL != pr);
pr->setPath(target, path, fill, translate);
pr->setPath(target, path, fill, antiAlias, translate);
fPathRenderer = pr;
}
~AutoClearPath() {
@ -219,6 +207,7 @@ protected:
GrDrawTarget* fTarget;
GrPathFill fFill;
GrPoint fTranslate;
bool fAntiAlias;
private:

View File

@ -32,25 +32,20 @@ GrPathRenderer* GrPathRendererChain::addPathRenderer(GrPathRenderer* pr) {
return pr;
}
GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrDrawTarget* target,
const GrPath& path,
GrPathFill fill) {
GrPathRenderer* GrPathRendererChain::getPathRenderer(
const GrDrawTarget::Caps& targetCaps,
const GrPath& path,
GrPathFill fill,
bool antiAlias) {
if (!fInit) {
this->init();
}
bool preferAA = target->isAntialiasState() &&
!target->getRenderTarget()->isMultisampled();
GrPathRenderer* nonAAPR = NULL;
for (int i = 0; i < fChain.count(); ++i) {
if (fChain[i]->canDrawPath(target, path, fill)) {
if (!preferAA || fChain[i]->supportsAA(target, path, fill)) {
return fChain[i];
} else {
nonAAPR = fChain[i];
}
if (fChain[i]->canDrawPath(targetCaps, path, fill, antiAlias)) {
return fChain[i];
}
}
return nonAAPR;
return NULL;
}
void GrPathRendererChain::init() {

View File

@ -10,11 +10,12 @@
#ifndef GrPathRendererChain_DEFINED
#define GrPathRendererChain_DEFINED
#include "GrDrawTarget.h"
#include "GrRefCnt.h"
#include "SkTArray.h"
class GrContext;
class GrDrawTarget;
class SkPath;
class GrPathRenderer;
@ -39,9 +40,10 @@ public:
// takes a ref and unrefs in destructor
GrPathRenderer* addPathRenderer(GrPathRenderer* pr);
GrPathRenderer* getPathRenderer(const GrDrawTarget* target,
GrPathRenderer* getPathRenderer(const GrDrawTarget::Caps& targetCaps,
const SkPath& path,
GrPathFill fill);
GrPathFill fill,
bool antiAlias);
private:

View File

@ -457,7 +457,7 @@ FINISHED:
}
if (subpathCnt == 1 && !inverted && fPath->isConvex()) {
if (fTarget->isAntialiasState()) {
if (fAntiAlias) {
GrEdgeArray edges;
GrMatrix inverse, matrix = fTarget->getViewMatrix();
fTarget->getViewInverse(&inverse);
@ -492,7 +492,7 @@ FINISHED:
return;
}
if (fTarget->isAntialiasState()) {
if (fAntiAlias) {
// Run the tesselator once to get the boundaries.
GrBoundaryTess btess(count, fill_type_to_glu_winding_rule(fFill));
btess.addVertices(base, subpathVertCount, subpathCnt);
@ -590,9 +590,10 @@ FINISHED:
}
}
bool GrTesselatedPathRenderer::canDrawPath(const GrDrawTarget* target,
bool GrTesselatedPathRenderer::canDrawPath(const GrDrawTarget::Caps& caps,
const SkPath& path,
GrPathFill fill) const {
GrPathFill fill,
bool antiAlias) const {
return kHairLine_PathFill != fill;
}
@ -600,8 +601,3 @@ void GrTesselatedPathRenderer::drawPathToStencil() {
GrAlwaysAssert(!"multipass stencil should not be needed");
}
bool GrTesselatedPathRenderer::supportsAA(const GrDrawTarget* target,
const SkPath& path,
GrPathFill fill) const {
return true;
}

View File

@ -17,17 +17,11 @@ public:
GrTesselatedPathRenderer();
virtual void drawPath(GrDrawTarget::StageBitfield stages);
virtual bool canDrawPath(const GrDrawTarget* target,
virtual bool canDrawPath(const GrDrawTarget::Caps& targetCaps,
const GrPath& path,
GrPathFill fill) const;
virtual bool requiresStencilPass(const GrDrawTarget* target,
const GrPath& path,
GrPathFill fill) const { return false; }
virtual void drawPathToStencil();
virtual bool supportsAA(const GrDrawTarget* target,
const GrPath& path,
GrPathFill fill) const;
GrPathFill fill,
bool antiAlias) const SK_OVERRIDE;
virtual void drawPathToStencil() SK_OVERRIDE;
};
#endif