diff options
-rw-r--r-- | gpu/include/GrDrawTarget.h | 27 | ||||
-rw-r--r-- | gpu/include/GrTesselatedPathRenderer.h | 3 | ||||
-rw-r--r-- | gpu/src/GrDrawTarget.cpp | 12 | ||||
-rw-r--r-- | gpu/src/GrGLProgram.cpp | 30 | ||||
-rw-r--r-- | gpu/src/GrGLProgram.h | 3 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders.cpp | 21 | ||||
-rw-r--r-- | gpu/src/GrGpuGLShaders.h | 3 | ||||
-rw-r--r-- | gpu/src/GrTesselatedPathRenderer.cpp | 113 | ||||
-rw-r--r-- | gyp/skia.gyp | 10 | ||||
-rw-r--r-- | src/utils/unix/SkOSWindow_Unix.cpp | 2 |
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; } |