GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) { if (range > 1) { GrGLuint name; GL_CALL_RET(name, GenPaths(range)); return name; } if (NULL == fPathNameAllocator.get()) { static const int range = 65536; GrGLuint firstName; GL_CALL_RET(firstName, GenPaths(range)); fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range))); } // When allocating names one at a time, pull from a client-side pool of // available names in order to save a round trip to the GL server. GrGLuint name = fPathNameAllocator->allocateName(); if (0 == name) { // Our reserved path names are all in use. Fall back on GenPaths. GL_CALL_RET(name, GenPaths(1)); } return name; }
GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) { SkASSERT(range > 0); GrGLuint firstID; if (fPreallocatedPathCount >= range) { firstID = fFirstPreallocatedPathID; fPreallocatedPathCount -= range; fFirstPreallocatedPathID += range; return firstID; } // Allocate range + the amount to fill up preallocation amount. If succeed, either join with // the existing preallocation range or delete the existing and use the new (potentially partial) // preallocation range. GrGLsizei allocAmount = range + (kPathIDPreallocationAmount - fPreallocatedPathCount); if (allocAmount >= range) { GL_CALL_RET(firstID, GenPaths(allocAmount)); if (firstID != 0) { if (fPreallocatedPathCount > 0 && firstID == fFirstPreallocatedPathID + fPreallocatedPathCount) { firstID = fFirstPreallocatedPathID; fPreallocatedPathCount += allocAmount - range; fFirstPreallocatedPathID += range; return firstID; } if (allocAmount > range) { if (fPreallocatedPathCount > 0) { this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount); } fFirstPreallocatedPathID = firstID + range; fPreallocatedPathCount = allocAmount - range; } // Special case: if allocAmount == range, we have full preallocated range. return firstID; } } // Failed to allocate with preallocation. Remove existing preallocation and try to allocate just // the range. if (fPreallocatedPathCount > 0) { this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount); fPreallocatedPathCount = 0; } GL_CALL_RET(firstID, GenPaths(range)); if (firstID == 0) { SkDebugf("Warning: Failed to allocate path\n"); } return firstID; }
GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path) : INHERITED(gpu, kIsWrapped) { #ifndef SK_SCALAR_IS_FLOAT GrCrash("Assumes scalar is float."); #endif SkASSERT(!path.isEmpty()); GL_CALL_RET(fPathID, GenPaths(1)); SkSTArray<16, GrGLubyte, true> pathCommands; SkSTArray<16, SkPoint, true> pathPoints; int verbCnt = path.countVerbs(); int pointCnt = path.countPoints(); pathCommands.resize_back(verbCnt); pathPoints.resize_back(pointCnt); // TODO: Direct access to path points since we could pass them on directly. path.getPoints(&pathPoints[0], pointCnt); path.getVerbs(&pathCommands[0], verbCnt); GR_DEBUGCODE(int numPts = 0); for (int i = 0; i < verbCnt; ++i) { SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]); pathCommands[i] = verb_to_gl_path_cmd(v); GR_DEBUGCODE(numPts += num_pts(v)); } GrAssert(pathPoints.count() == numPts); GL_CALL(PathCommands(fPathID, verbCnt, &pathCommands[0], 2 * pointCnt, GR_GL_FLOAT, &pathPoints[0])); fBounds = path.getBounds(); }