bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) { SK_TRACE_EVENT0("GrGLShaderBuilder::finish"); GrGLuint programId = 0; GL_CALL_RET(programId, CreateProgram()); if (!programId) { return false; } if (!this->compileAndAttachShaders(programId)) { GL_CALL(DeleteProgram(programId)); return false; } this->bindProgramLocations(programId); GL_CALL(LinkProgram(programId)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = !fGpu->ctxInfo().isChromium(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { GrGLint linked = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked)); if (!linked) { GrGLint infoLen = GR_GL_INIT_ZERO; GL_CALL(GetProgramiv(programId, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround // bug in chrome cmd buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GL_CALL(GetProgramInfoLog(programId, infoLen+1, &length, (char*)log.get())); GrPrintf((char*)log.get()); } SkDEBUGFAIL("Error linking program"); GL_CALL(DeleteProgram(programId)); return false; } } fUniformManager.getUniformLocations(programId, fUniforms); *outProgramId = programId; return true; }
bool GrDefaultPathRenderer::createGeom(GrScalar srcSpaceTol, GrDrawTarget::StageBitfield stages) { { SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom"); GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol); int maxPts = GrPathUtils::worstCasePointCount(*fPath, &fSubpathCount, srcSpaceTol); if (maxPts <= 0) { return false; } if (maxPts > ((int)SK_MaxU16 + 1)) { GrPrintf("Path not rendered, too many verts (%d)\n", maxPts); return false; } GrVertexLayout layout = 0; for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { if ((1 << s) & stages) { layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); } } fUseIndexedDraw = fSubpathCount > 1; int maxIdxs = 0; if (kHairLine_PathFill == fFill) { if (fUseIndexedDraw) { maxIdxs = 2 * maxPts; fPrimitiveType = kLines_PrimitiveType; } else { fPrimitiveType = kLineStrip_PrimitiveType; } } else { if (fUseIndexedDraw) { maxIdxs = 3 * maxPts; fPrimitiveType = kTriangles_PrimitiveType; } else { fPrimitiveType = kTriangleFan_PrimitiveType; } } GrPoint* base; if (!fTarget->reserveVertexSpace(layout, maxPts, (void**)&base)) { return false; } GrAssert(NULL != base); GrPoint* vert = base; uint16_t* idxBase = NULL; uint16_t* idx = NULL; uint16_t subpathIdxStart = 0; if (fUseIndexedDraw) { if (!fTarget->reserveIndexSpace(maxIdxs, (void**)&idxBase)) { fTarget->resetVertexSource(); return false; } GrAssert(NULL != idxBase); idx = idxBase; } fSubpathVertCount.reset(fSubpathCount); GrPoint pts[4]; bool first = true; int subpath = 0; SkPath::Iter iter(*fPath, false); for (;;) { GrPathCmd cmd = (GrPathCmd)iter.next(pts); switch (cmd) { case kMove_PathCmd: if (!first) { uint16_t currIdx = (uint16_t) (vert - base); fSubpathVertCount[subpath] = currIdx - subpathIdxStart; subpathIdxStart = currIdx; ++subpath; } *vert = pts[0]; vert++; break; case kLine_PathCmd: if (fUseIndexedDraw) { uint16_t prevIdx = (uint16_t)(vert - base) - 1; append_countour_edge_indices(fFill, subpathIdxStart, prevIdx, &idx); } *(vert++) = pts[1]; break; case kQuadratic_PathCmd: { // first pt of quad is the pt we ended on in previous step uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1; uint16_t numPts = (uint16_t) GrPathUtils::generateQuadraticPoints( pts[0], pts[1], pts[2], srcSpaceTolSqd, &vert, GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); if (fUseIndexedDraw) { for (uint16_t i = 0; i < numPts; ++i) { append_countour_edge_indices(fFill, subpathIdxStart, firstQPtIdx + i, &idx); } } break; } case kCubic_PathCmd: { // first pt of cubic is the pt we ended on in previous step uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1; uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints( pts[0], pts[1], pts[2], pts[3], srcSpaceTolSqd, &vert, GrPathUtils::cubicPointCount(pts, srcSpaceTol)); if (fUseIndexedDraw) { for (uint16_t i = 0; i < numPts; ++i) { append_countour_edge_indices(fFill, subpathIdxStart, firstCPtIdx + i, &idx); } } break; } case kClose_PathCmd: break; case kEnd_PathCmd: uint16_t currIdx = (uint16_t) (vert - base); fSubpathVertCount[subpath] = currIdx - subpathIdxStart; goto FINISHED; } first = false; } FINISHED: GrAssert((vert - base) <= maxPts); GrAssert((idx - idxBase) <= maxIdxs); fVertexCnt = vert - base; fIndexCnt = idx - idxBase; if (fTranslate.fX || fTranslate.fY) { int count = vert - base; for (int i = 0; i < count; i++) { base[i].offset(fTranslate.fX, fTranslate.fY); } } } // set these at the end so if we failed on first drawPath inside a // setPath/clearPath block we won't assume geom was created on a subsequent // drawPath in the same block. fPreviousSrcTol = srcSpaceTol; fPreviousStages = stages; return true; }
bool GrDefaultPathRenderer::createGeom(const SkPath& path, GrPathFill fill, GrScalar srcSpaceTol, GrDrawTarget* target, GrPrimitiveType* primType, int* vertexCnt, int* indexCnt, GrDrawTarget::AutoReleaseGeometry* arg) { { SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom"); GrScalar srcSpaceTolSqd = GrMul(srcSpaceTol, srcSpaceTol); int contourCnt; int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, srcSpaceTol); if (maxPts <= 0) { return false; } if (maxPts > ((int)SK_MaxU16 + 1)) { GrPrintf("Path not rendered, too many verts (%d)\n", maxPts); return false; } GrVertexLayout layout = 0; bool indexed = contourCnt > 1; int maxIdxs = 0; if (kHairLine_GrPathFill == fill) { if (indexed) { maxIdxs = 2 * maxPts; *primType = kLines_GrPrimitiveType; } else { *primType = kLineStrip_GrPrimitiveType; } } else { if (indexed) { maxIdxs = 3 * maxPts; *primType = kTriangles_GrPrimitiveType; } else { *primType = kTriangleFan_GrPrimitiveType; } } if (!arg->set(target, layout, maxPts, maxIdxs)) { return false; } uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices());; uint16_t* idx = idxBase; uint16_t subpathIdxStart = 0; GrPoint* base = reinterpret_cast<GrPoint*>(arg->vertices()); GrAssert(NULL != base); GrPoint* vert = base; GrPoint pts[4]; bool first = true; int subpath = 0; SkPath::Iter iter(path, false); for (;;) { GrPathCmd cmd = (GrPathCmd)iter.next(pts); switch (cmd) { case kMove_PathCmd: if (!first) { uint16_t currIdx = (uint16_t) (vert - base); subpathIdxStart = currIdx; ++subpath; } *vert = pts[0]; vert++; break; case kLine_PathCmd: if (indexed) { uint16_t prevIdx = (uint16_t)(vert - base) - 1; append_countour_edge_indices(fill, subpathIdxStart, prevIdx, &idx); } *(vert++) = pts[1]; break; case kQuadratic_PathCmd: { // first pt of quad is the pt we ended on in previous step uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1; uint16_t numPts = (uint16_t) GrPathUtils::generateQuadraticPoints( pts[0], pts[1], pts[2], srcSpaceTolSqd, &vert, GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); if (indexed) { for (uint16_t i = 0; i < numPts; ++i) { append_countour_edge_indices(fill, subpathIdxStart, firstQPtIdx + i, &idx); } } break; } case kCubic_PathCmd: { // first pt of cubic is the pt we ended on in previous step uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1; uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints( pts[0], pts[1], pts[2], pts[3], srcSpaceTolSqd, &vert, GrPathUtils::cubicPointCount(pts, srcSpaceTol)); if (indexed) { for (uint16_t i = 0; i < numPts; ++i) { append_countour_edge_indices(fill, subpathIdxStart, firstCPtIdx + i, &idx); } } break; } case kClose_PathCmd: break; case kEnd_PathCmd: // uint16_t currIdx = (uint16_t) (vert - base); goto FINISHED; } first = false; } FINISHED: GrAssert((vert - base) <= maxPts); GrAssert((idx - idxBase) <= maxIdxs); *vertexCnt = vert - base; *indexCnt = idx - idxBase; } return true; }