static void add_quads(const SkPoint p[3], int subdiv, const SkMatrix* toDevice, const SkMatrix* toSrc, BezierVertex** vert) { SkASSERT(subdiv >= 0); if (subdiv) { SkPoint newP[5]; SkChopQuadAtHalf(p, newP); add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); } else { bloat_quad(p, toDevice, toSrc, *vert); set_uv_quad(p, *vert); *vert += kQuadNumVertices; } }
bool GrAAHairLinePathRenderer::createGeom( const SkPath& path, GrDrawTarget* target, int* lineCnt, int* quadCnt, GrDrawTarget::AutoReleaseGeometry* arg) { const GrDrawState& drawState = target->getDrawState(); int rtHeight = drawState.getRenderTarget()->height(); GrIRect devClipBounds; target->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); GrVertexLayout layout = GrDrawState::kEdge_VertexLayoutBit; SkMatrix viewM = drawState.getViewMatrix(); PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; IntArray qSubdivs; *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, &lines, &quads, &qSubdivs); *lineCnt = lines.count() / 2; int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; GrAssert(sizeof(Vertex) == GrDrawState::VertexSize(layout)); if (!arg->set(target, layout, vertCnt, 0)) { return false; } Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices()); const SkMatrix* toDevice = NULL; const SkMatrix* toSrc = NULL; SkMatrix ivm; if (viewM.hasPerspective()) { if (viewM.invert(&ivm)) { toDevice = &viewM; toSrc = &ivm; } } for (int i = 0; i < *lineCnt; ++i) { add_line(&lines[2*i], rtHeight, toSrc, &verts); } int unsubdivQuadCnt = quads.count() / 3; for (int i = 0; i < unsubdivQuadCnt; ++i) { GrAssert(qSubdivs[i] >= 0); add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); } return true; }
void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) { // Setup the viewmatrix and localmatrix for the GrGeometryProcessor. SkMatrix invert; if (!this->viewMatrix().invert(&invert)) { return; } // we will transform to identity space if the viewmatrix does not have perspective bool hasPerspective = this->viewMatrix().hasPerspective(); const SkMatrix* geometryProcessorViewM = &SkMatrix::I(); const SkMatrix* geometryProcessorLocalM = &invert; const SkMatrix* toDevice = NULL; const SkMatrix* toSrc = NULL; if (hasPerspective) { geometryProcessorViewM = &this->viewMatrix(); geometryProcessorLocalM = &SkMatrix::I(); toDevice = &this->viewMatrix(); toSrc = &invert; } // Setup geometry processors for worst case uint32_t gpFlags = GrDefaultGeoProcFactory::kPosition_GPType | GrDefaultGeoProcFactory::kCoverage_GPType; SkAutoTUnref<const GrGeometryProcessor> lineGP( GrDefaultGeoProcFactory::Create(gpFlags, this->color(), this->usesLocalCoords(), this->coverageIgnored(), *geometryProcessorViewM, *geometryProcessorLocalM, this->coverage())); SkAutoTUnref<const GrGeometryProcessor> quadGP( GrQuadEffect::Create(this->color(), *geometryProcessorViewM, kHairlineAA_GrProcessorEdgeType, batchTarget->caps(), *geometryProcessorLocalM, this->usesLocalCoords(), this->coverage())); SkAutoTUnref<const GrGeometryProcessor> conicGP( GrConicEffect::Create(this->color(), *geometryProcessorViewM, kHairlineAA_GrProcessorEdgeType, batchTarget->caps(), *geometryProcessorLocalM, this->usesLocalCoords(), this->coverage())); // This is hand inlined for maximum performance. PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; PREALLOC_PTARRAY(128) conics; IntArray qSubdivs; FloatArray cWeights; int quadCount = 0; int instanceCount = fGeoData.count(); for (int i = 0; i < instanceCount; i++) { const Geometry& args = fGeoData[i]; quadCount += gather_lines_and_quads(args.fPath, args.fViewMatrix, args.fDevClipBounds, &lines, &quads, &conics, &qSubdivs, &cWeights); } int lineCount = lines.count() / 2; int conicCount = conics.count() / 3; // do lines first if (lineCount) { SkAutoTUnref<const GrIndexBuffer> linesIndexBuffer( ref_lines_index_buffer(batchTarget->resourceProvider())); batchTarget->initDraw(lineGP, pipeline); const GrVertexBuffer* vertexBuffer; int firstVertex; size_t vertexStride = lineGP->getVertexStride(); int vertexCount = kLineSegNumVertices * lineCount; LineVertex* verts = reinterpret_cast<LineVertex*>( batchTarget->makeVertSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex)); if (!verts|| !linesIndexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } SkASSERT(lineGP->getVertexStride() == sizeof(LineVertex)); for (int i = 0; i < lineCount; ++i) { add_line(&lines[2*i], toSrc, this->coverage(), &verts); } { GrVertices vertices; vertices.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, linesIndexBuffer, firstVertex, kLineSegNumVertices, kIdxsPerLineSeg, lineCount, kLineSegsNumInIdxBuffer); batchTarget->draw(vertices); } } if (quadCount || conicCount) { const GrVertexBuffer* vertexBuffer; int firstVertex; SkAutoTUnref<const GrIndexBuffer> quadsIndexBuffer( ref_quads_index_buffer(batchTarget->resourceProvider())); size_t vertexStride = sizeof(BezierVertex); int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * conicCount; void *vertices = batchTarget->makeVertSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex); if (!vertices || !quadsIndexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } // Setup vertices BezierVertex* verts = reinterpret_cast<BezierVertex*>(vertices); int unsubdivQuadCnt = quads.count() / 3; for (int i = 0; i < unsubdivQuadCnt; ++i) { SkASSERT(qSubdivs[i] >= 0); add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); } // Start Conics for (int i = 0; i < conicCount; ++i) { add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts); } if (quadCount > 0) { batchTarget->initDraw(quadGP, pipeline); { GrVertices verts; verts.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer, firstVertex, kQuadNumVertices, kIdxsPerQuad, quadCount, kQuadsNumInIdxBuffer); batchTarget->draw(verts); firstVertex += quadCount * kQuadNumVertices; } } if (conicCount > 0) { batchTarget->initDraw(conicGP, pipeline); { GrVertices verts; verts.initInstanced(kTriangles_GrPrimitiveType, vertexBuffer, quadsIndexBuffer, firstVertex, kQuadNumVertices, kIdxsPerQuad, conicCount, kQuadsNumInIdxBuffer); batchTarget->draw(verts); } } } }
bool GrAAHairLinePathRenderer::createGeom(GrDrawTarget::StageBitfield stages) { int rtHeight = fTarget->getRenderTarget()->height(); GrIRect clip; if (fTarget->getClip().hasConservativeBounds()) { GrRect clipRect = fTarget->getClip().getConservativeBounds(); clipRect.roundOut(&clip); } else { clip.setLargest(); } // If none of the inputs that affect generation of path geometry have // have changed since last previous path draw then we can reuse the // previous geoemtry. if (stages == fPreviousStages && fPreviousViewMatrix == fTarget->getViewMatrix() && fPreviousTranslate == fTranslate && rtHeight == fPreviousRTHeight && fClipRect == clip) { return true; } GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit; for (int s = 0; s < GrDrawState::kNumStages; ++s) { if ((1 << s) & stages) { layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); } } GrMatrix viewM = fTarget->getViewMatrix(); PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; IntArray qSubdivs; fQuadCnt = generate_lines_and_quads(*fPath, viewM, fTranslate, clip, &lines, &quads, &qSubdivs); fLineSegmentCnt = lines.count() / 2; int vertCnt = kVertsPerLineSeg * fLineSegmentCnt + kVertsPerQuad * fQuadCnt; GrAssert(sizeof(Vertex) == GrDrawTarget::VertexSize(layout)); Vertex* verts; if (!fTarget->reserveVertexSpace(layout, vertCnt, (void**)&verts)) { return false; } Vertex* base = verts; const GrMatrix* toDevice = NULL; const GrMatrix* toSrc = NULL; GrMatrix ivm; if (viewM.hasPerspective()) { if (viewM.invert(&ivm)) { toDevice = &viewM; toSrc = &ivm; } } for (int i = 0; i < fLineSegmentCnt; ++i) { add_line(&lines[2*i], rtHeight, toSrc, &verts); } int unsubdivQuadCnt = quads.count() / 3; for (int i = 0; i < unsubdivQuadCnt; ++i) { GrAssert(qSubdivs[i] >= 0); add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); } fPreviousStages = stages; fPreviousViewMatrix = fTarget->getViewMatrix(); fPreviousRTHeight = rtHeight; fClipRect = clip; fPreviousTranslate = fTranslate; return true; }
bool GrAAHairLinePathRenderer::createBezierGeom( const SkPath& path, GrDrawTarget* target, const PtArray& quads, int quadCnt, const PtArray& conics, int conicCnt, const IntArray& qSubdivs, const FloatArray& cWeights, GrDrawTarget::AutoReleaseGeometry* arg, SkRect* devBounds) { GrDrawState* drawState = target->drawState(); const SkMatrix& viewM = drawState->getViewMatrix(); int vertCnt = kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt; int vAttribCnt = SK_ARRAY_COUNT(gHairlineBezierAttribs); target->drawState()->setVertexAttribs<gHairlineBezierAttribs>(vAttribCnt, sizeof(BezierVertex)); if (!arg->set(target, vertCnt, 0)) { return false; } BezierVertex* verts = reinterpret_cast<BezierVertex*>(arg->vertices()); const SkMatrix* toDevice = NULL; const SkMatrix* toSrc = NULL; SkMatrix ivm; if (viewM.hasPerspective()) { if (viewM.invert(&ivm)) { toDevice = &viewM; toSrc = &ivm; } } // Seed the dev bounds with some pts known to be inside. Each quad and conic grows the bounding // box to include its vertices. SkPoint seedPts[2]; if (quadCnt) { seedPts[0] = quads[0]; seedPts[1] = quads[2]; } else if (conicCnt) { seedPts[0] = conics[0]; seedPts[1] = conics[2]; } if (toDevice) { toDevice->mapPoints(seedPts, 2); } devBounds->set(seedPts[0], seedPts[1]); int unsubdivQuadCnt = quads.count() / 3; for (int i = 0; i < unsubdivQuadCnt; ++i) { SkASSERT(qSubdivs[i] >= 0); add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); } // Start Conics for (int i = 0; i < conicCnt; ++i) { add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds); } return true; }
int main (int argc, char *argv[]) { if (argc != 2) usage (argv[0]); std::string twopt_table_file = argv[1]; Npoint_Functions::Pixel_Quadrilaterals_Rhombic<int> q; Npoint_Functions::Twopt_Table<int> twopt_table; twopt_table.read_file (twopt_table_file); Npoint_Functions::Pixel_Triangles_Equilateral<int> triangles; triangles.find_triangles (twopt_table); q.initialize (triangles); /* Build the list of pixels storing information about their base pixel as * this is needed for the transformations. */ std::vector<PixelInfo> pixel_list; { std::vector<int> pl0, pl4; myHealpix::base0_list (q.Nside(), pl0); myHealpix::base4_list (q.Nside(), pl4); pixel_list.resize(pl0.size()+pl4.size()); for (size_t j=0; j < pl0.size(); ++j) { pixel_list[j].pixnum = pl0[j]; pixel_list[j].basepix = PixelInfo::BASE0; } for (size_t j=0; j < pl4.size(); ++j) { pixel_list[j+pl0.size()].pixnum = pl4[j]; pixel_list[j+pl0.size()].basepix = PixelInfo::BASE4; } } #pragma omp parallel shared (pixel_list) firstprivate (q) { std::vector<int> tri; std::vector<int> thirdpt; thirdpt.reserve(1000); int pix; PixelTrans pixtrans (q.Nside(), q.Scheme()); /* Buffer space. We save the quadrilaterals in a buffer and then * write them out all at once. This is done so that we don't have * threads fighting each other to get write access. We can't have them * all write at once. */ // Number of quad space we want to reserve. This is a bit under 500MB. const size_t Nbuf = 30000000; simple_vector<int> quad_buf(4*Nbuf); #pragma omp for schedule(dynamic,1) for (size_t j=0; j < pixel_list.size(); ++j) { pix = pixel_list[j].pixnum; // shorthand q.initialize(pix); while (q.next(tri, thirdpt)) { // First add the quads. add_quads (tri, thirdpt, quad_buf); // Next shift by base pixel 3 times. for (int n=0; n < 3; ++n) { pixtrans.shift_by_base (tri); pixtrans.shift_by_base (thirdpt); add_quads (tri, thirdpt, quad_buf); } // Then reflect through z=0 line pixtrans.reflect_through_z0 (tri); pixtrans.reflect_through_z0 (thirdpt); add_quads (tri, thirdpt, quad_buf); // and shift by base pixel 3 times. for (int n=0; n < 3; ++n) { pixtrans.shift_by_base (tri); pixtrans.shift_by_base (thirdpt); add_quads (tri, thirdpt, quad_buf); } // If we have a base0 pixel we are done if (pixel_list[j].basepix == PixelInfo::BASE0) continue; // Otherwise we have more transformations to do. // Reflect through z-axis pixtrans.reflect_through_zaxis (tri); pixtrans.reflect_through_zaxis (thirdpt); add_quads (tri, thirdpt, quad_buf); // and shift by base pixel 3 times. for (int n=0; n < 3; ++n) { pixtrans.shift_by_base (tri); pixtrans.shift_by_base (thirdpt); add_quads (tri, thirdpt, quad_buf); } // Then reflect through z=0 line pixtrans.reflect_through_z0 (tri); pixtrans.reflect_through_z0 (thirdpt); add_quads (tri, thirdpt, quad_buf); // and shift by base pixel 3 times. for (int n=0; n < 3; ++n) { pixtrans.shift_by_base (tri); pixtrans.shift_by_base (thirdpt); add_quads (tri, thirdpt, quad_buf); } } } write_quad_buffer (quad_buf); } return 0; }