зеркало из https://github.com/mozilla/moz-skia.git
Improve gpu path subdiv with perspective, remove tolerance scale, fix comment
Review URL: http://codereview.appspot.com/4993041/ git-svn-id: http://skia.googlecode.com/svn/trunk@2239 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
a5adf5385d
Коммит
181e9bd948
|
@ -692,11 +692,6 @@ bool GrContext::prepareForOffscreenAA(GrDrawTarget* target,
|
|||
GR_STATIC_ASSERT(4 == OFFSCREEN_SSAA_SCALE);
|
||||
desc.fAALevel = kNone_GrAALevel;
|
||||
}
|
||||
// Avoid overtesselating paths in AA buffers; may unduly reduce quality
|
||||
// of simple circles?
|
||||
if (pr) {
|
||||
//pr->scaleCurveTolerance(GrIntToScalar(record->fScale));
|
||||
}
|
||||
|
||||
desc.fWidth *= record->fScale;
|
||||
desc.fHeight *= record->fScale;
|
||||
|
@ -881,10 +876,6 @@ void GrContext::doOffscreenAAPass2(GrDrawTarget* target,
|
|||
void GrContext::cleanupOffscreenAA(GrDrawTarget* target,
|
||||
GrPathRenderer* pr,
|
||||
OffscreenRecord* record) {
|
||||
if (pr) {
|
||||
// Counterpart of scale() in prepareForOffscreenAA()
|
||||
//pr->scaleCurveTolerance(SkScalarInvert(SkIntToScalar(record->fScale)));
|
||||
}
|
||||
target->restoreDrawState(record->fSavedState);
|
||||
}
|
||||
|
||||
|
|
|
@ -374,18 +374,9 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawTarget::StageBitfield stages,
|
|||
bool stencilOnly) {
|
||||
|
||||
GrMatrix viewM = fTarget->getViewMatrix();
|
||||
// In order to tesselate the path we get a bound on how much the matrix can
|
||||
// stretch when mapping to screen coordinates.
|
||||
GrScalar stretch = viewM.getMaxStretch();
|
||||
bool useStretch = stretch > 0;
|
||||
GrScalar tol = fCurveTolerance;
|
||||
GrScalar tol = GR_Scalar1;
|
||||
tol = GrPathUtils::scaleToleranceToSrc(tol, viewM);
|
||||
|
||||
if (!useStretch) {
|
||||
// TODO: deal with perspective in some better way.
|
||||
tol /= 10;
|
||||
} else {
|
||||
tol = GrScalarDiv(tol, stretch);
|
||||
}
|
||||
// FIXME: It's really dumb that we recreate the verts for a new vertex
|
||||
// layout. We only do that because the GrDrawTarget API doesn't allow
|
||||
// us to change the vertex layout after reserveVertexSpace(). We won't
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
#include "GrPathRenderer.h"
|
||||
|
||||
GrPathRenderer::GrPathRenderer()
|
||||
: fCurveTolerance (GR_Scalar1)
|
||||
, fPath(NULL)
|
||||
: fPath(NULL)
|
||||
, fTarget(NULL) {
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ public:
|
|||
* This is called to install custom path renderers in every GrContext at
|
||||
* create time. The default implementation in GrCreatePathRenderer_none.cpp
|
||||
* does not add any additional renderers. Link against another
|
||||
* implementation to install your own. The most recently added is the
|
||||
* most preferred path renderer.
|
||||
* implementation to install your own. The first added is the most preferred
|
||||
* path renderer, second is second most preferred, etc.
|
||||
*
|
||||
* @param context the context that will use the path renderer
|
||||
* @param flags flags indicating how path renderers will be used
|
||||
|
@ -169,16 +169,6 @@ public:
|
|||
GrCrash("Unexpected call to drawPathToStencil.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply curve tolerance by the given value, increasing or decreasing
|
||||
* the maximum error permitted in tesselating curves with short straight
|
||||
* line segments.
|
||||
*/
|
||||
void scaleCurveTolerance(GrScalar multiplier) {
|
||||
GrAssert(multiplier > 0);
|
||||
fCurveTolerance = SkScalarMul(fCurveTolerance, multiplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that sets a path and automatically remove it in destructor.
|
||||
*/
|
||||
|
@ -224,7 +214,6 @@ protected:
|
|||
virtual void pathWasSet() {}
|
||||
virtual void pathWillClear() {}
|
||||
|
||||
GrScalar fCurveTolerance;
|
||||
const SkPath* fPath;
|
||||
GrDrawTarget* fTarget;
|
||||
GrPathFill fFill;
|
||||
|
|
|
@ -8,10 +8,27 @@
|
|||
|
||||
|
||||
#include "GrPathUtils.h"
|
||||
|
||||
#include "GrPoint.h"
|
||||
|
||||
GrScalar GrPathUtils::scaleToleranceToSrc(GrScalar devTol,
|
||||
const GrMatrix& viewM) {
|
||||
// In order to tesselate the path we get a bound on how much the matrix can
|
||||
// stretch when mapping to screen coordinates.
|
||||
GrScalar stretch = viewM.getMaxStretch();
|
||||
GrScalar srcTol = devTol;
|
||||
|
||||
if (stretch < 0) {
|
||||
// TODO: deal with perspective in some better way.
|
||||
srcTol /= 5;
|
||||
stretch = -stretch;
|
||||
}
|
||||
srcTol = GrScalarDiv(srcTol, stretch);
|
||||
return srcTol;
|
||||
}
|
||||
|
||||
static const int MAX_POINTS_PER_CURVE = 1 << 10;
|
||||
const GrScalar GrPathUtils::gMinCurveTol (GrFloatToScalar(0.0001f));
|
||||
static const GrScalar gMinCurveTol = GrFloatToScalar(0.0001f);
|
||||
|
||||
uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[],
|
||||
GrScalar tol) {
|
||||
|
|
|
@ -10,41 +10,42 @@
|
|||
#ifndef GrPathUtils_DEFINED
|
||||
#define GrPathUtils_DEFINED
|
||||
|
||||
#include "GrNoncopyable.h"
|
||||
#include "GrPoint.h"
|
||||
#include "GrMatrix.h"
|
||||
#include "GrPath.h"
|
||||
|
||||
class GrPoint;
|
||||
|
||||
/**
|
||||
* Utilities for evaluating paths.
|
||||
*/
|
||||
class GrPathUtils : public GrNoncopyable {
|
||||
public:
|
||||
/// Since we divide by tol if we're computing exact worst-case bounds,
|
||||
/// very small tolerances will be increased to gMinCurveTol.
|
||||
static int worstCasePointCount(const GrPath&,
|
||||
int* subpaths,
|
||||
GrScalar tol);
|
||||
/// Since we divide by tol if we're computing exact worst-case bounds,
|
||||
/// very small tolerances will be increased to gMinCurveTol.
|
||||
static uint32_t quadraticPointCount(const GrPoint points[], GrScalar tol);
|
||||
static uint32_t generateQuadraticPoints(const GrPoint& p0,
|
||||
const GrPoint& p1,
|
||||
const GrPoint& p2,
|
||||
GrScalar tolSqd,
|
||||
GrPoint** points,
|
||||
uint32_t pointsLeft);
|
||||
/// Since we divide by tol if we're computing exact worst-case bounds,
|
||||
/// very small tolerances will be increased to gMinCurveTol.
|
||||
static uint32_t cubicPointCount(const GrPoint points[], GrScalar tol);
|
||||
static uint32_t generateCubicPoints(const GrPoint& p0,
|
||||
const GrPoint& p1,
|
||||
const GrPoint& p2,
|
||||
const GrPoint& p3,
|
||||
GrScalar tolSqd,
|
||||
GrPoint** points,
|
||||
uint32_t pointsLeft);
|
||||
namespace GrPathUtils {
|
||||
GrScalar scaleToleranceToSrc(GrScalar devTol,
|
||||
const GrMatrix& viewM);
|
||||
|
||||
/// Since we divide by tol if we're computing exact worst-case bounds,
|
||||
/// very small tolerances will be increased to gMinCurveTol.
|
||||
int worstCasePointCount(const GrPath&,
|
||||
int* subpaths,
|
||||
GrScalar tol);
|
||||
/// Since we divide by tol if we're computing exact worst-case bounds,
|
||||
/// very small tolerances will be increased to gMinCurveTol.
|
||||
uint32_t quadraticPointCount(const GrPoint points[], GrScalar tol);
|
||||
uint32_t generateQuadraticPoints(const GrPoint& p0,
|
||||
const GrPoint& p1,
|
||||
const GrPoint& p2,
|
||||
GrScalar tolSqd,
|
||||
GrPoint** points,
|
||||
uint32_t pointsLeft);
|
||||
/// Since we divide by tol if we're computing exact worst-case bounds,
|
||||
/// very small tolerances will be increased to gMinCurveTol.
|
||||
uint32_t cubicPointCount(const GrPoint points[], GrScalar tol);
|
||||
uint32_t generateCubicPoints(const GrPoint& p0,
|
||||
const GrPoint& p1,
|
||||
const GrPoint& p2,
|
||||
const GrPoint& p3,
|
||||
GrScalar tolSqd,
|
||||
GrPoint** points,
|
||||
uint32_t pointsLeft);
|
||||
|
||||
private:
|
||||
static const GrScalar gMinCurveTol;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -351,18 +351,9 @@ void GrTesselatedPathRenderer::drawPath(GrDrawTarget::StageBitfield stages) {
|
|||
GrAssert(GrDrawTarget::kBoth_DrawFace == fTarget->getDrawFace());
|
||||
|
||||
GrMatrix viewM = fTarget->getViewMatrix();
|
||||
// In order to tesselate the path we get a bound on how much the matrix can
|
||||
// stretch when mapping to screen coordinates.
|
||||
GrScalar stretch = viewM.getMaxStretch();
|
||||
bool useStretch = stretch > 0;
|
||||
GrScalar tol = fCurveTolerance;
|
||||
|
||||
if (!useStretch) {
|
||||
// TODO: deal with perspective in some better way.
|
||||
tol /= 10;
|
||||
} else {
|
||||
tol = GrScalarDiv(tol, stretch);
|
||||
}
|
||||
GrScalar tol = GR_Scalar1;
|
||||
tol = GrPathUtils::scaleToleranceToSrc(tol, viewM);
|
||||
GrScalar tolSqd = GrMul(tol, tol);
|
||||
|
||||
int subpathCnt;
|
||||
|
|
|
@ -501,10 +501,12 @@ public:
|
|||
void toDumpString(SkString*) const;
|
||||
|
||||
/**
|
||||
* Calculates the maximum stretching factor of the matrix. Only defined if
|
||||
* the matrix does not have perspective.
|
||||
* Calculates the maximum stretching factor of the matrix. If the matrix has
|
||||
* perspective the max stretch at the origin (in the pre-matrix space) is
|
||||
* computed and returned as a negative.
|
||||
*
|
||||
* @return maximum strecthing factor or negative if matrix has perspective.
|
||||
* @return maximum strecthing factor or negative max stretching factor at
|
||||
* the origin if matrix has perspective.
|
||||
*/
|
||||
SkScalar getMaxStretch() const;
|
||||
|
||||
|
|
|
@ -28,6 +28,11 @@ protected:
|
|||
|
||||
|
||||
virtual void onDrawContent(SkCanvas* canvas) {
|
||||
SkMatrix m;
|
||||
m.reset();
|
||||
m.setPerspX(0.00020);
|
||||
canvas->concat(m);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
|
@ -38,6 +43,7 @@ protected:
|
|||
SkPath curves;
|
||||
SkPath hulls;
|
||||
SkPath ctrlPts;
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
SkScalar pts[] = {
|
||||
rand.nextUScalar1(), rand.nextUScalar1(),
|
||||
|
|
|
@ -1674,10 +1674,6 @@ bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
|
|||
SkScalar SkMatrix::getMaxStretch() const {
|
||||
TypeMask mask = this->getType();
|
||||
|
||||
if (mask & kPerspective_Mask) {
|
||||
return -SK_Scalar1;
|
||||
}
|
||||
|
||||
SkScalar stretch;
|
||||
|
||||
if (this->isIdentity()) {
|
||||
|
@ -1702,7 +1698,8 @@ SkScalar SkMatrix::getMaxStretch() const {
|
|||
// and roots are guaraunteed to be pos and real).
|
||||
SkScalar largerRoot;
|
||||
SkScalar bSqd = SkScalarMul(b,b);
|
||||
if (bSqd <= SkFloatToScalar(1e-10)) { // will be true if upper left 2x2 is orthogonal, which is common, so save some math
|
||||
// if upper left 2x2 is orthogonal save some math
|
||||
if (bSqd <= SK_ScalarNearlyZero) {
|
||||
largerRoot = SkMaxScalar(a, c);
|
||||
} else {
|
||||
SkScalar aminusc = a - c;
|
||||
|
@ -1710,8 +1707,17 @@ SkScalar SkMatrix::getMaxStretch() const {
|
|||
SkScalar x = SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd) / 2;
|
||||
largerRoot = apluscdiv2 + x;
|
||||
}
|
||||
|
||||
stretch = SkScalarSqrt(largerRoot);
|
||||
if (mask & kPerspective_Mask) {
|
||||
stretch = -stretch;
|
||||
if (fMat[kMPersp2] != kMatrix22Elem) {
|
||||
#if defined(SK_SCALAR_IS_FLOAT)
|
||||
stretch /= fMat[kMPersp2];
|
||||
#else
|
||||
stretch = SkFractDiv(stretch, fMat[kMPersp2]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(SK_DEBUG) && 0
|
||||
// test a bunch of vectors. None should be scaled by more than stretch
|
||||
|
|
Загрузка…
Ссылка в новой задаче