aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gpu/include/GrDrawTarget.h27
-rw-r--r--gpu/include/GrTesselatedPathRenderer.h3
-rw-r--r--gpu/src/GrDrawTarget.cpp12
-rw-r--r--gpu/src/GrGLProgram.cpp30
-rw-r--r--gpu/src/GrGLProgram.h3
-rw-r--r--gpu/src/GrGpuGLShaders.cpp21
-rw-r--r--gpu/src/GrGpuGLShaders.h3
-rw-r--r--gpu/src/GrTesselatedPathRenderer.cpp113
-rw-r--r--gyp/skia.gyp10
-rw-r--r--src/utils/unix/SkOSWindow_Unix.cpp2
10 files changed, 203 insertions, 21 deletions
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index e8f1793759..93b381dd9f 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -66,18 +66,22 @@ public:
* default to disabled.
*/
enum StateBits {
- kDither_StateBit = 0x1,//<! Perform color dithering
- kAntialias_StateBit = 0x2,//<! Perform anti-aliasing. The render-
+ 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 = 0x4,//<! Controls whether drawing is clipped
+ kClip_StateBit = 0x04, //<! Controls whether drawing is clipped
// against the region specified by
// setClip.
- kNoColorWrites_StateBit = 0x8,//<! If set it disables writing colors.
- // Useful while performing stencil ops.
+ kNoColorWrites_StateBit = 0x08, //<! If set it disables writing colors.
+ // Useful while performing stencil
+ // ops.
+ kEdgeAA_StateBit = 0x10, //<! Perform edge anti-aliasing.
+ // Requires the edges to be passed in
+ // setEdgeAAData().
// subclass may use additional bits internally
kDummyStateBit,
@@ -154,6 +158,7 @@ protected:
GrStencilSettings fStencilSettings;
GrMatrix fViewMatrix;
+ float fEdgeAAEdges[18];
bool operator ==(const DrState& s) const {
return 0 == memcmp(this, &s, sizeof(DrState));
}
@@ -362,6 +367,10 @@ public:
return 0 != (fCurrDrawState.fFlagBits & kDither_StateBit);
}
+ bool isAntialiasState() const {
+ return 0 != (fCurrDrawState.fFlagBits & kAntialias_StateBit);
+ }
+
bool isClipState() const {
return 0 != (fCurrDrawState.fFlagBits & kClip_StateBit);
}
@@ -483,6 +492,14 @@ public:
*/
bool canDisableBlend() const;
+ /**
+ * Sets the edge data required for edge antialiasing.
+ *
+ * @param edges 3 * 6 float values, representing the edge
+ * equations in Ax + By + C form
+ */
+ void setEdgeAAData(const float edges[18]);
+
private:
static const int TEX_COORD_BIT_CNT = kNumStages*kMaxTexCoords;
public:
diff --git a/gpu/include/GrTesselatedPathRenderer.h b/gpu/include/GrTesselatedPathRenderer.h
index 3efc471b4c..accd114e4c 100644
--- a/gpu/include/GrTesselatedPathRenderer.h
+++ b/gpu/include/GrTesselatedPathRenderer.h
@@ -39,6 +39,9 @@ public:
GrPathIter* path,
GrPathFill fill,
const GrPoint* translate);
+ virtual bool supportsAA(GrDrawTarget* target,
+ GrPathIter* path,
+ GrPathFill fill);
};
#endif
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 668dc3a415..5e515137dc 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -478,6 +478,11 @@ void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
///////////////////////////////////////////////////////////////////////////////
bool GrDrawTarget::canDisableBlend() const {
+ // If we're using edge antialiasing, we can't force blend off.
+ if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
+ return false;
+ }
+
if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
(kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
return true;
@@ -524,6 +529,13 @@ bool GrDrawTarget::canDisableBlend() const {
// ...then we disable blend.
return true;
}
+
+///////////////////////////////////////////////////////////////////////////////
+void GrDrawTarget::setEdgeAAData(const float edges[18]) {
+ memcpy(fCurrDrawState.fEdgeAAEdges, edges, sizeof(fCurrDrawState.fEdgeAAEdges));
+}
+
+
///////////////////////////////////////////////////////////////////////////////
void GrDrawTarget::drawRect(const GrRect& rect,
const GrMatrix* matrix,
diff --git a/gpu/src/GrGLProgram.cpp b/gpu/src/GrGLProgram.cpp
index 1c0db251b7..ce4e7dbd03 100644
--- a/gpu/src/GrGLProgram.cpp
+++ b/gpu/src/GrGLProgram.cpp
@@ -54,6 +54,7 @@ const char* GrShaderPrecision() {
#define POS_ATTR_NAME "aPosition"
#define COL_ATTR_NAME "aColor"
#define COL_UNI_NAME "uColor"
+#define EDGES_UNI_NAME "uEdges"
#define COL_FILTER_UNI_NAME "uColorFilter"
static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
@@ -269,6 +270,10 @@ bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const {
break;
}
+ if (fProgramDesc.fUsesEdgeAA) {
+ segments.fFSUnis.append("uniform vec3 " EDGES_UNI_NAME "[6];\n");
+ }
+
if (fProgramDesc.fEmitsPointSize){
segments.fVSCode.append("\tgl_PointSize = 1.0;\n");
}
@@ -352,6 +357,23 @@ bool GrGLProgram::genProgram(GrGLProgram::CachedData* programData) const {
}
} else {
+ if (fProgramDesc.fUsesEdgeAA) {
+ // FIXME: put the a's in a loop
+ segments.fFSCode.append(
+ "\tvec3 pos = vec3(gl_FragCoord.xy, 1);\n"
+ "\tfloat a0 = clamp(dot(uEdges[0], pos), 0.0, 1.0);\n"
+ "\tfloat a1 = clamp(dot(uEdges[1], pos), 0.0, 1.0);\n"
+ "\tfloat a2 = clamp(dot(uEdges[2], pos), 0.0, 1.0);\n"
+ "\tfloat a3 = clamp(dot(uEdges[3], pos), 0.0, 1.0);\n"
+ "\tfloat a4 = clamp(dot(uEdges[4], pos), 0.0, 1.0);\n"
+ "\tfloat a5 = clamp(dot(uEdges[5], pos), 0.0, 1.0);\n"
+ "\tfloat edgeAlpha = min(min(a0 * a1, a2 * a3), a4 * a5);\n");
+ if (inColor.size()) {
+ inColor.append(" * edgeAlpha");
+ } else {
+ inColor = "vec4(edgeAlpha)";
+ }
+ }
// we may not have any incoming color
const char * incomingColor = (inColor.size() ? inColor.c_str()
: "vec4(1,1,1,1)");
@@ -583,6 +605,14 @@ void GrGLProgram::getUniformLocationsAndInitCache(CachedData* programData) const
GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni);
}
+ if (fProgramDesc.fUsesEdgeAA) {
+ programData->fUniLocations.fEdgesUni =
+ GR_GL(GetUniformLocation(progID, EDGES_UNI_NAME));
+ GrAssert(kUnusedUniform != programData->fUniLocations.fEdgesUni);
+ } else {
+ programData->fUniLocations.fEdgesUni = kUnusedUniform;
+ }
+
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
StageUniLocations& locations = programData->fUniLocations.fStages[s];
if (fProgramDesc.fStages[s].fEnabled) {
diff --git a/gpu/src/GrGLProgram.h b/gpu/src/GrGLProgram.h
index 08902387e7..1611ca21c4 100644
--- a/gpu/src/GrGLProgram.h
+++ b/gpu/src/GrGLProgram.h
@@ -108,6 +108,7 @@ private:
} fColorType;
bool fEmitsPointSize;
+ bool fUsesEdgeAA;
SkXfermode::Mode fColorFilterXfermode;
@@ -163,11 +164,13 @@ public:
struct UniLocations {
GrGLint fViewMatrixUni;
GrGLint fColorUni;
+ GrGLint fEdgesUni;
GrGLint fColorFilterUni;
StageUniLocations fStages[GrDrawTarget::kNumStages];
void reset() {
fViewMatrixUni = kUnusedUniform;
fColorUni = kUnusedUniform;
+ fEdgesUni = kUnusedUniform;
fColorFilterUni = kUnusedUniform;
for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
fStages[s].reset();
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index 937c8ed422..8965b06520 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -36,7 +36,7 @@ private:
#if GR_DEBUG
typedef GrBinHashKey<Entry, 4> ProgramHashKey; // Flex the dynamic allocation muscle in debug
#else
- typedef GrBinHashKey<Entry, 32> ProgramHashKey;
+ typedef GrBinHashKey<Entry, 64> ProgramHashKey;
#endif
class Entry : public ::GrNoncopyable {
@@ -396,6 +396,22 @@ void GrGpuGLShaders::flushTexelSize(int s) {
}
}
+void GrGpuGLShaders::flushEdgeAAData() {
+ const int& uni = fProgramData->fUniLocations.fEdgesUni;
+ if (GrGLProgram::kUnusedUniform != uni) {
+ float edges[18];
+ memcpy(edges, fCurrDrawState.fEdgeAAEdges, sizeof(edges));
+ // Flip the edges in Y
+ float height = fCurrDrawState.fRenderTarget->height();
+ for (int i = 0; i < 6; ++i) {
+ float b = edges[i * 3 + 1];
+ edges[i * 3 + 1] = -b;
+ edges[i * 3 + 2] += b * height;
+ }
+ GR_GL(Uniform3fv(uni, 6, edges));
+ }
+}
+
static const float ONE_OVER_255 = 1.f / 255.f;
#define GR_COLOR_TO_VEC4(color) {\
@@ -500,6 +516,7 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
this->flushTexelSize(s);
}
+ this->flushEdgeAAData();
resetDirtyFlags();
return true;
}
@@ -632,6 +649,8 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type) {
desc.fColorType = GrGLProgram::ProgramDesc::kAttribute_ColorType;
}
+ desc.fUsesEdgeAA = fCurrDrawState.fFlagBits & kEdgeAA_StateBit;
+
for (int s = 0; s < kNumStages; ++s) {
GrGLProgram::ProgramDesc::StageDesc& stage = desc.fStages[s];
diff --git a/gpu/src/GrGpuGLShaders.h b/gpu/src/GrGpuGLShaders.h
index a1bcaf08be..bb3024faf9 100644
--- a/gpu/src/GrGpuGLShaders.h
+++ b/gpu/src/GrGpuGLShaders.h
@@ -63,6 +63,9 @@ private:
// flushes the normalized texel size
void flushTexelSize(int stage);
+ // flushes the edges for edge AA
+ void flushEdgeAAData();
+
static void DeleteProgram(GrGLProgram::CachedData* programData);
void ProgramUnitTest();
diff --git a/gpu/src/GrTesselatedPathRenderer.cpp b/gpu/src/GrTesselatedPathRenderer.cpp
index 8ed2c2249e..3993adb5d9 100644
--- a/gpu/src/GrTesselatedPathRenderer.cpp
+++ b/gpu/src/GrTesselatedPathRenderer.cpp
@@ -55,8 +55,8 @@ static void combineData(GLdouble coords[3], void* vertexData[4],
{
PolygonData* polygonData = static_cast<PolygonData*>(data);
int index = polygonData->fVertices->count();
- *polygonData->fVertices->append() = GrPoint(static_cast<float>(coords[0]),
- static_cast<float>(coords[1]));
+ *polygonData->fVertices->append() = GrPoint::Make(static_cast<float>(coords[0]),
+ static_cast<float>(coords[1]));
*outData = reinterpret_cast<void*>(index);
}
@@ -83,6 +83,59 @@ static unsigned fill_type_to_glu_winding_rule(GrPathFill fill) {
GrTesselatedPathRenderer::GrTesselatedPathRenderer() {
}
+class Edge {
+ public:
+ Edge() {}
+ Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
+ GrPoint intersect(const Edge& other) {
+ return GrPoint::Make(
+ (fY * other.fZ - other.fY * fZ) / (fX * other.fY - other.fX * fY),
+ (fX * other.fZ - other.fX * fZ) / (other.fX * fY - fX * other.fY));
+ }
+ float fX, fY, fZ;
+};
+
+typedef GrTDArray<Edge> EdgeArray;
+
+bool isCCW(const GrPoint* v)
+{
+ GrVec v1 = v[1] - v[0];
+ GrVec v2 = v[2] - v[1];
+ return v1.cross(v2) < 0;
+}
+
+static size_t computeEdgesAndOffsetVertices(const GrMatrix& matrix,
+ const GrMatrix& inverse,
+ GrPoint* vertices,
+ size_t numVertices,
+ EdgeArray* edges)
+{
+ GrPoint p = vertices[numVertices - 1];
+ matrix.mapPoints(&p, 1);
+ float sign = isCCW(vertices) ? -1.0f : 1.0f;
+ for (size_t i = 0; i < numVertices; ++i) {
+ GrPoint q = vertices[i];
+ matrix.mapPoints(&q, 1);
+ if (p == q) continue;
+ GrVec tangent = GrVec::Make(p.fY - q.fY, q.fX - p.fX);
+ float scale = sign / tangent.length();
+ float cross2 = p.fX * q.fY - q.fX * p.fY;
+ Edge edge(tangent.fX * scale,
+ tangent.fY * scale,
+ cross2 * scale + 0.5f);
+ *edges->append() = edge;
+ p = q;
+ }
+ Edge prev_edge = *edges->back();
+ for (size_t i = 0; i < edges->count(); ++i) {
+ Edge edge = edges->at(i);
+ vertices[i] = prev_edge.intersect(edge);
+ inverse.mapPoints(&vertices[i], 1);
+ prev_edge = edge;
+ }
+ return edges->count();
+}
+
void GrTesselatedPathRenderer::drawPath(GrDrawTarget* target,
GrDrawTarget::StageBitfield stages,
GrPathIter* path,
@@ -193,10 +246,10 @@ FINISHED:
if (target->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
}
- *vert++ = GrPoint(bounds.fLeft, bounds.fTop);
- *vert++ = GrPoint(bounds.fLeft, bounds.fBottom);
- *vert++ = GrPoint(bounds.fRight, bounds.fBottom);
- *vert++ = GrPoint(bounds.fRight, bounds.fTop);
+ *vert++ = GrPoint::Make(bounds.fLeft, bounds.fTop);
+ *vert++ = GrPoint::Make(bounds.fLeft, bounds.fBottom);
+ *vert++ = GrPoint::Make(bounds.fRight, bounds.fBottom);
+ *vert++ = GrPoint::Make(bounds.fRight, bounds.fTop);
subpathVertCount[subpath++] = 4;
}
@@ -205,9 +258,40 @@ FINISHED:
size_t count = vert - base;
+ if (count < 3) {
+ delete[] base;
+ return;
+ }
+
if (subpathCnt == 1 && !inverted && path->convexHint() == kConvex_ConvexHint) {
- target->setVertexSourceToArray(layout, base, count);
- target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
+ if (target->isAntialiasState()) {
+ target->enableState(GrDrawTarget::kEdgeAA_StateBit);
+ EdgeArray edges;
+ GrMatrix inverse, matrix = target->getViewMatrix();
+ target->getViewInverse(&inverse);
+
+ count = computeEdgesAndOffsetVertices(matrix, inverse, base, count, &edges);
+ GrPoint triangle[3];
+ triangle[0] = base[0];
+ Edge triangleEdges[6];
+ triangleEdges[0] = *edges.back();
+ triangleEdges[1] = edges[0];
+ for (size_t i = 1; i < count - 1; i++) {
+ triangle[1] = base[i];
+ triangle[2] = base[i + 1];
+ triangleEdges[2] = edges[i - 1];
+ triangleEdges[3] = edges[i];
+ triangleEdges[4] = edges[i];
+ triangleEdges[5] = edges[i + 1];
+ target->setVertexSourceToArray(layout, triangle, 3);
+ target->setEdgeAAData(&triangleEdges[0].fX);
+ target->drawNonIndexed(kTriangles_PrimitiveType, 0, 3);
+ }
+ target->disableState(GrDrawTarget::kEdgeAA_StateBit);
+ } else {
+ target->setVertexSourceToArray(layout, base, count);
+ target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
+ }
delete[] base;
return;
}
@@ -241,7 +325,7 @@ FINISHED:
int end = start + subpathVertCount[sp];
for (; i < end; ++i) {
double* inVertex = &inVertices[i * 3];
- *vertices.append() = GrPoint(inVertex[0], inVertex[1]);
+ *vertices.append() = GrPoint::Make(inVertex[0], inVertex[1]);
internal_gluTessVertex(tess, inVertex, reinterpret_cast<void*>(i));
}
internal_gluTessEndContour(tess);
@@ -275,3 +359,14 @@ void GrTesselatedPathRenderer::drawPathToStencil(GrDrawTarget* target,
const GrPoint* translate) {
GrAlwaysAssert(!"multipass stencil should not be needed");
}
+
+bool GrTesselatedPathRenderer::supportsAA(GrDrawTarget* target,
+ GrPathIter* path,
+ GrPathFill fill) {
+ int subpathCnt = 0;
+ int tol = GrPathUtils::gTolerance;
+ GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
+ return (subpathCnt == 1 &&
+ !IsFillInverted(fill) &&
+ path->convexHint() == kConvex_ConvexHint);
+}
diff --git a/gyp/skia.gyp b/gyp/skia.gyp
index c37d567aee..7247828bb1 100644
--- a/gyp/skia.gyp
+++ b/gyp/skia.gyp
@@ -904,9 +904,9 @@
'../include/core',
'../include/config',
],
- #'dependencies': [
- # 'libtess',
- #],
+ 'dependencies': [
+ 'libtess',
+ ],
'sources': [
'../gpu/include/GrAllocator.h',
'../gpu/include/GrAllocPool.h',
@@ -959,7 +959,7 @@
'../gpu/include/GrTArray.h',
'../gpu/include/GrTBSearch.h',
'../gpu/include/GrTDArray.h',
- #'../gpu/include/GrTesselatedPathRenderer.h',
+ '../gpu/include/GrTesselatedPathRenderer.h',
'../gpu/include/GrTextContext.h',
'../gpu/include/GrTextStrike.h',
'../gpu/include/GrTexture.h',
@@ -1008,7 +1008,7 @@
'../gpu/src/GrRedBlackTree.h',
'../gpu/src/GrResource.cpp',
'../gpu/src/GrStencil.cpp',
- #'../gpu/src/GrTesselatedPathRenderer.cpp',
+ '../gpu/src/GrTesselatedPathRenderer.cpp',
'../gpu/src/GrTextContext.cpp',
'../gpu/src/GrTextStrike.cpp',
'../gpu/src/GrTextStrike_impl.h',
diff --git a/src/utils/unix/SkOSWindow_Unix.cpp b/src/utils/unix/SkOSWindow_Unix.cpp
index 5f63b539f9..4ec0c74306 100644
--- a/src/utils/unix/SkOSWindow_Unix.cpp
+++ b/src/utils/unix/SkOSWindow_Unix.cpp
@@ -88,7 +88,7 @@ void SkOSWindow::restartLoop()
{
// We have a new window, so we need to set the title again and restart the
// loop.
- this->setTitle(this->getTitle());
+ this->onSetTitle(this->getTitle());
fRestart = true;
}