Bug 1498460 - Backport an upstream Skia patch. r=lsalzman
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 15 Oct 2018 14:25:06 -0400
changeset 441522 86f5694c6c50995d0e3cd19be96d9db27240ab10
parent 441521 bd4c433b0e5000a35f1b8f1694038d6f48f5abfe
child 441523 a1fb2da7388b017c761e0c0c6116e3ea7c3fac71
push id34867
push usershindli@mozilla.com
push dateWed, 17 Oct 2018 00:55:53 +0000
treeherdermozilla-central@778427bb6353 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1498460
milestone64.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
Bug 1498460 - Backport an upstream Skia patch. r=lsalzman Backport of: https://skia.googlesource.com/skia/+/d5b4593024544c3405615066aa5b4f94352eb3cb
gfx/skia/skia/src/gpu/GrTessellator.cpp
gfx/skia/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp
gfx/skia/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
gfx/skia/skia/src/gpu/ops/GrSmallPathRenderer.cpp
--- 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");