author | Ryan VanderMeulen <ryanvm@gmail.com> |
Mon, 15 Oct 2018 14:25:06 -0400 | |
changeset 441522 | 86f5694c6c50995d0e3cd19be96d9db27240ab10 |
parent 441521 | bd4c433b0e5000a35f1b8f1694038d6f48f5abfe |
child 441523 | a1fb2da7388b017c761e0c0c6116e3ea7c3fac71 |
push id | 34867 |
push user | shindli@mozilla.com |
push date | Wed, 17 Oct 2018 00:55:53 +0000 |
treeherder | mozilla-central@778427bb6353 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | lsalzman |
bugs | 1498460 |
milestone | 64.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/skia/skia/src/gpu/GrTessellator.cpp +++ b/gfx/skia/skia/src/gpu/GrTessellator.cpp @@ -2269,28 +2269,28 @@ int get_contour_count(const SkPath& path } if (maxPts > ((int)SK_MaxU16 + 1)) { SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); return 0; } return contourCnt; } -int count_points(Poly* polys, SkPath::FillType fillType) { - int count = 0; +int64_t count_points(Poly* polys, SkPath::FillType fillType) { + int64_t count = 0; for (Poly* poly = polys; poly; poly = poly->fNext) { if (apply_fill_type(fillType, poly) && poly->fCount >= 3) { count += (poly->fCount - 2) * (TESSELLATOR_WIREFRAME ? 6 : 3); } } return count; } -int count_outer_mesh_points(const VertexList& outerMesh) { - int count = 0; +int64_t count_outer_mesh_points(const VertexList& outerMesh) { + int64_t count = 0; for (Vertex* v = outerMesh.fHead; v; v = v->fNext) { for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { count += TESSELLATOR_WIREFRAME ? 12 : 6; } } return count; } @@ -2322,23 +2322,24 @@ int PathToTriangles(const SkPath& path, *isLinear = true; return 0; } SkArenaAlloc alloc(kArenaChunkSize); VertexList outerMesh; Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, antialias, isLinear, &outerMesh); SkPath::FillType fillType = antialias ? SkPath::kWinding_FillType : path.getFillType(); - int count = count_points(polys, fillType); + int64_t count64 = count_points(polys, fillType); if (antialias) { - count += count_outer_mesh_points(outerMesh); + count64 += count_outer_mesh_points(outerMesh); } - if (0 == count) { + if (0 == count64 || count64 > SK_MaxS32) { return 0; } + int count = count64; void* verts = vertexAllocator->lock(count); if (!verts) { SkDebugf("Could not allocate vertices\n"); return 0; } LOG("emitting %d verts\n", count); @@ -2362,21 +2363,22 @@ int PathToVertices(const SkPath& path, S *verts = nullptr; return 0; } SkArenaAlloc alloc(kArenaChunkSize); bool isLinear; Poly* polys = path_to_polys(path, tolerance, clipBounds, contourCnt, alloc, false, &isLinear, nullptr); SkPath::FillType fillType = path.getFillType(); - int count = count_points(polys, fillType); - if (0 == count) { + int64_t count64 = count_points(polys, fillType); + if (0 == count64 || count64 > SK_MaxS32) { *verts = nullptr; return 0; } + int count = count64; *verts = new GrTessellator::WindingVertex[count]; GrTessellator::WindingVertex* vertsEnd = *verts; SkPoint* points = new SkPoint[count]; SkPoint* pointsEnd = points; for (Poly* poly = polys; poly; poly = poly->fNext) { if (apply_fill_type(fillType, poly)) { SkPoint* start = pointsEnd;
--- a/gfx/skia/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp +++ b/gfx/skia/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp @@ -17,16 +17,17 @@ #include "GrPathUtils.h" #include "GrProcessor.h" #include "GrSimpleMeshDrawOpHelper.h" #include "SkGeometry.h" #include "SkPathPriv.h" #include "SkPointPriv.h" #include "SkString.h" #include "SkTraceEvent.h" +#include "SkTypes.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLGeometryProcessor.h" #include "glsl/GrGLSLProgramDataManager.h" #include "glsl/GrGLSLUniformHandler.h" #include "glsl/GrGLSLVarying.h" #include "glsl/GrGLSLVertexGeoBuilder.h" #include "ops/GrMeshDrawOp.h" @@ -125,53 +126,58 @@ static void compute_vectors(SegmentArray // Make the normals point towards the outside SkPointPriv::Side normSide; if (dir == SkPathPriv::kCCW_FirstDirection) { normSide = SkPointPriv::kRight_Side; } else { normSide = SkPointPriv::kLeft_Side; } - *vCount = 0; - *iCount = 0; + int64_t vCount64 = 0; + int64_t iCount64 = 0; // compute normals at all points for (int a = 0; a < count; ++a) { Segment& sega = (*segments)[a]; int b = (a + 1) % count; Segment& segb = (*segments)[b]; const SkPoint* prevPt = &sega.endPt(); int n = segb.countPoints(); for (int p = 0; p < n; ++p) { segb.fNorms[p] = segb.fPts[p] - *prevPt; segb.fNorms[p].normalize(); SkPointPriv::SetOrthog(&segb.fNorms[p], segb.fNorms[p], normSide); prevPt = &segb.fPts[p]; } if (Segment::kLine == segb.fType) { - *vCount += 5; - *iCount += 9; + vCount64 += 5; + iCount64 += 9; } else { - *vCount += 6; - *iCount += 12; + vCount64 += 6; + iCount64 += 12; } } // compute mid-vectors where segments meet. TODO: Detect shallow corners // and leave out the wedges and close gaps by stitching segments together. for (int a = 0; a < count; ++a) { const Segment& sega = (*segments)[a]; int b = (a + 1) % count; Segment& segb = (*segments)[b]; segb.fMid = segb.fNorms[0] + sega.endNorm(); segb.fMid.normalize(); // corner wedges - *vCount += 4; - *iCount += 6; + vCount64 += 4; + iCount64 += 6; } + if (vCount64 > SK_MaxS32 || iCount64 > SK_MaxS32) { + return; + } + *vCount = vCount64; + *iCount = iCount64; } struct DegenerateTestData { DegenerateTestData() { fStage = kInitial; } bool isDegenerate() const { return kNonDegenerate != fStage; } enum { kInitial, kPoint,
--- a/gfx/skia/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp +++ b/gfx/skia/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp @@ -250,58 +250,70 @@ private: SkASSERT(fHelper.compatibleWithAlphaAsCoverage() ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) : vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr)); int instanceCount = fPaths.count(); - int vertexCount = 0; - int indexCount = 0; - int maxVertices = DEFAULT_BUFFER_SIZE; - int maxIndices = DEFAULT_BUFFER_SIZE; + int64_t vertexCount = 0; + int64_t indexCount = 0; + int64_t maxVertices = DEFAULT_BUFFER_SIZE; + int64_t maxIndices = DEFAULT_BUFFER_SIZE; uint8_t* vertices = (uint8_t*) sk_malloc_throw(maxVertices * vertexStride); uint16_t* indices = (uint16_t*) sk_malloc_throw(maxIndices * sizeof(uint16_t)); for (int i = 0; i < instanceCount; i++) { const PathData& args = fPaths[i]; GrAAConvexTessellator tess(args.fStyle, args.fStrokeWidth, args.fJoin, args.fMiterLimit); if (!tess.tessellate(args.fViewMatrix, args.fPath)) { continue; } - int currentIndices = tess.numIndices(); - if (indexCount + currentIndices > UINT16_MAX) { + int currentVertices = tess.numPts(); + if (vertexCount + currentVertices > static_cast<int>(UINT16_MAX)) { // if we added the current instance, we would overflow the indices we can store in a // uint16_t. Draw what we've got so far and reset. this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, indices); vertexCount = 0; indexCount = 0; } - int currentVertices = tess.numPts(); if (vertexCount + currentVertices > maxVertices) { maxVertices = SkTMax(vertexCount + currentVertices, maxVertices * 2); + if (maxVertices * vertexStride > SK_MaxS32) { + sk_free(vertices); + sk_free(indices); + return; + } vertices = (uint8_t*) sk_realloc_throw(vertices, maxVertices * vertexStride); } + int currentIndices = tess.numIndices(); if (indexCount + currentIndices > maxIndices) { maxIndices = SkTMax(indexCount + currentIndices, maxIndices * 2); + if (maxIndices * sizeof(uint16_t) > SK_MaxS32) { + sk_free(vertices); + sk_free(indices); + return; + } indices = (uint16_t*) sk_realloc_throw(indices, maxIndices * sizeof(uint16_t)); } extract_verts(tess, vertices + vertexStride * vertexCount, vertexStride, args.fColor, vertexCount, indices + indexCount, fHelper.compatibleWithAlphaAsCoverage()); vertexCount += currentVertices; indexCount += currentIndices; } - this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, - indices); + if (vertexCount <= SK_MaxS32 && indexCount <= SK_MaxS32) { + this->draw(target, gp.get(), pipeline, vertexCount, vertexStride, vertices, indexCount, + indices); + } sk_free(vertices); sk_free(indices); } bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override { AAFlatteningConvexPathOp* that = t->cast<AAFlatteningConvexPathOp>(); if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) { return false;
--- a/gfx/skia/skia/src/gpu/ops/GrSmallPathRenderer.cpp +++ b/gfx/skia/skia/src/gpu/ops/GrSmallPathRenderer.cpp @@ -264,16 +264,22 @@ private: kA8_GrMaskFormat, invert, fHelper.usesLocalCoords()); } // allocate vertices size_t vertexStride = flushInfo.fGeometryProcessor->getVertexStride(); SkASSERT(vertexStride == sizeof(SkPoint) + sizeof(GrColor) + 2*sizeof(uint16_t)); const GrBuffer* vertexBuffer; + + // We need to make sure we don't overflow a 32 bit int when we request space in the + // makeVertexSpace call below. + if (instanceCount > SK_MaxS32 / kVerticesPerQuad) { + return; + } void* vertices = target->makeVertexSpace(vertexStride, kVerticesPerQuad * instanceCount, &vertexBuffer, &flushInfo.fVertexOffset); flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer)); flushInfo.fIndexBuffer = target->resourceProvider()->refQuadIndexBuffer(); if (!vertices || !flushInfo.fIndexBuffer) { SkDebugf("Could not allocate vertices\n");