diff options
author | joshualitt <joshualitt@chromium.org> | 2015-04-30 13:49:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-30 13:49:27 -0700 |
commit | 3e708c53f79a04b588b6ca8e535e61f986d80b47 (patch) | |
tree | a074e51af90cf5b96898632a7bfda14e8236b09a /src/gpu | |
parent | 1c2c441fede0ae9573afc098017011e3439624a9 (diff) |
Add batch unit tests for ovals
BUG=skia:
Review URL: https://codereview.chromium.org/1108403005
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrBatch.h | 1 | ||||
-rw-r--r-- | src/gpu/GrBatchTest.cpp | 11 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.cpp | 334 | ||||
-rw-r--r-- | src/gpu/GrOvalRenderer.h | 2 | ||||
-rw-r--r-- | src/gpu/GrTestUtils.cpp | 61 |
5 files changed, 290 insertions, 119 deletions
diff --git a/src/gpu/GrBatch.h b/src/gpu/GrBatch.h index 7d621e046a..92a9c08ef2 100644 --- a/src/gpu/GrBatch.h +++ b/src/gpu/GrBatch.h @@ -38,6 +38,7 @@ struct GrInitInvariantOutput; * If there are any possible optimizations which might require knowing more about the full state of * the draw, ie whether or not the GrBatch is allowed to tweak alpha for coverage, then this * information will be communicated to the GrBatch prior to geometry generation. + * TODO Batch should own the draw bounds */ class GrBatch : public SkRefCnt { diff --git a/src/gpu/GrBatchTest.cpp b/src/gpu/GrBatchTest.cpp index 4a368311a2..fa8333d3c2 100644 --- a/src/gpu/GrBatchTest.cpp +++ b/src/gpu/GrBatchTest.cpp @@ -13,10 +13,21 @@ BATCH_TEST_EXTERN(AAFillRectBatch); BATCH_TEST_EXTERN(AAStrokeRectBatch); +BATCH_TEST_EXTERN(DashBatch); +BATCH_TEST_EXTERN(CircleBatch); +BATCH_TEST_EXTERN(DIEllipseBatch); +BATCH_TEST_EXTERN(EllipseBatch); +BATCH_TEST_EXTERN(RRectBatch); static BatchTestFunc gTestBatches[] = { BATCH_TEST_ENTRY(AAFillRectBatch), BATCH_TEST_ENTRY(AAStrokeRectBatch), + BATCH_TEST_ENTRY(DashBatch), + BATCH_TEST_ENTRY(CircleBatch), + BATCH_TEST_ENTRY(DIEllipseBatch), + BATCH_TEST_ENTRY(EllipseBatch), + BATCH_TEST_ENTRY(RRectBatch) + }; GrBatch* GrRandomBatch(SkRandom* random, GrContext* context) { diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 9a02a87157..b9303cf24d 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -9,6 +9,7 @@ #include "GrBatch.h" #include "GrBatchTarget.h" +#include "GrBatchTest.h" #include "GrBufferAllocPool.h" #include "GrDrawTarget.h" #include "GrGeometryProcessor.h" @@ -878,13 +879,12 @@ private: SkSTArray<1, Geometry, true> fGeoData; }; -void GrOvalRenderer::drawCircle(GrDrawTarget* target, - GrPipelineBuilder* pipelineBuilder, - GrColor color, - const SkMatrix& viewMatrix, - bool useCoverageAA, - const SkRect& circle, - const SkStrokeRec& stroke) { +static GrBatch* create_circle_batch(GrColor color, + const SkMatrix& viewMatrix, + bool useCoverageAA, + const SkRect& circle, + const SkStrokeRec& stroke, + SkRect* bounds) { SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); viewMatrix.mapPoints(¢er, 1); SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width())); @@ -918,12 +918,8 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target, outerRadius += SK_ScalarHalf; innerRadius -= SK_ScalarHalf; - SkRect bounds = SkRect::MakeLTRB( - center.fX - outerRadius, - center.fY - outerRadius, - center.fX + outerRadius, - center.fY + outerRadius - ); + bounds->setLTRB(center.fX - outerRadius, center.fY - outerRadius, + center.fX + outerRadius, center.fY + outerRadius); CircleBatch::Geometry geometry; geometry.fViewMatrix = viewMatrix; @@ -931,9 +927,21 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target, geometry.fInnerRadius = innerRadius; geometry.fOuterRadius = outerRadius; geometry.fStroke = isStrokeOnly && innerRadius > 0; - geometry.fDevBounds = bounds; + geometry.fDevBounds = *bounds; - SkAutoTUnref<GrBatch> batch(CircleBatch::Create(geometry)); + return CircleBatch::Create(geometry); +} + +void GrOvalRenderer::drawCircle(GrDrawTarget* target, + GrPipelineBuilder* pipelineBuilder, + GrColor color, + const SkMatrix& viewMatrix, + bool useCoverageAA, + const SkRect& circle, + const SkStrokeRec& stroke) { + SkRect bounds; + SkAutoTUnref<GrBatch> batch(create_circle_batch(color, viewMatrix, useCoverageAA, circle, + stroke, &bounds)); target->drawBatch(pipelineBuilder, batch, &bounds); } @@ -1138,13 +1146,12 @@ private: SkSTArray<1, Geometry, true> fGeoData; }; -bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, - GrPipelineBuilder* pipelineBuilder, - GrColor color, - const SkMatrix& viewMatrix, - bool useCoverageAA, - const SkRect& ellipse, - const SkStrokeRec& stroke) { +static GrBatch* create_ellipse_batch(GrColor color, + const SkMatrix& viewMatrix, + bool useCoverageAA, + const SkRect& ellipse, + const SkStrokeRec& stroke, + SkRect* bounds) { #ifdef SK_DEBUG { // we should have checked for this previously @@ -1188,13 +1195,13 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, // we only handle thick strokes for near-circular ellipses if (scaledStroke.length() > SK_ScalarHalf && (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) { - return false; + return NULL; } // we don't handle it if curvature of the stroke is less than curvature of the ellipse if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius || scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) { - return false; + return NULL; } // this is legit only if scale & translation (which should be the case at the moment) @@ -1213,12 +1220,8 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, xRadius += SK_ScalarHalf; yRadius += SK_ScalarHalf; - SkRect bounds = SkRect::MakeLTRB( - center.fX - xRadius, - center.fY - yRadius, - center.fX + xRadius, - center.fY + yRadius - ); + bounds->setLTRB(center.fX - xRadius, center.fY - yRadius, + center.fX + xRadius, center.fY + yRadius); EllipseBatch::Geometry geometry; geometry.fViewMatrix = viewMatrix; @@ -1228,11 +1231,26 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, geometry.fInnerXRadius = innerXRadius; geometry.fInnerYRadius = innerYRadius; geometry.fStroke = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0; - geometry.fDevBounds = bounds; + geometry.fDevBounds = *bounds; - SkAutoTUnref<GrBatch> batch(EllipseBatch::Create(geometry)); - target->drawBatch(pipelineBuilder, batch, &bounds); + return EllipseBatch::Create(geometry); +} +bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, + GrPipelineBuilder* pipelineBuilder, + GrColor color, + const SkMatrix& viewMatrix, + bool useCoverageAA, + const SkRect& ellipse, + const SkStrokeRec& stroke) { + SkRect bounds; + SkAutoTUnref<GrBatch> batch(create_ellipse_batch(color, viewMatrix, useCoverageAA, ellipse, + stroke, &bounds)); + if (!batch) { + return false; + } + + target->drawBatch(pipelineBuilder, batch, &bounds); return true; } @@ -1430,13 +1448,12 @@ private: SkSTArray<1, Geometry, true> fGeoData; }; -bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, - GrPipelineBuilder* pipelineBuilder, - GrColor color, - const SkMatrix& viewMatrix, - bool useCoverageAA, - const SkRect& ellipse, - const SkStrokeRec& stroke) { +static GrBatch* create_diellipse_batch(GrColor color, + const SkMatrix& viewMatrix, + bool useCoverageAA, + const SkRect& ellipse, + const SkStrokeRec& stroke, + SkRect* bounds) { SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); SkScalar xRadius = SkScalarHalf(ellipse.width()); SkScalar yRadius = SkScalarHalf(ellipse.height()); @@ -1461,13 +1478,13 @@ bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, // we only handle thick strokes for near-circular ellipses if (strokeWidth > SK_ScalarHalf && (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) { - return false; + return NULL; } // we don't handle it if curvature of the stroke is less than curvature of the ellipse if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius || strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) { - return false; + return NULL; } // set inner radius (if needed) @@ -1492,12 +1509,8 @@ bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); - SkRect bounds = SkRect::MakeLTRB( - center.fX - xRadius - geoDx, - center.fY - yRadius - geoDy, - center.fX + xRadius + geoDx, - center.fY + yRadius + geoDy - ); + bounds->setLTRB(center.fX - xRadius - geoDx, center.fY - yRadius - geoDy, + center.fX + xRadius + geoDx, center.fY + yRadius + geoDy); DIEllipseBatch::Geometry geometry; geometry.fViewMatrix = viewMatrix; @@ -1509,13 +1522,26 @@ bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, geometry.fGeoDx = geoDx; geometry.fGeoDy = geoDy; geometry.fMode = mode; - geometry.fBounds = bounds; + geometry.fBounds = *bounds; - viewMatrix.mapRect(&bounds); + viewMatrix.mapRect(bounds); + return DIEllipseBatch::Create(geometry); +} - SkAutoTUnref<GrBatch> batch(DIEllipseBatch::Create(geometry)); +bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, + GrPipelineBuilder* pipelineBuilder, + GrColor color, + const SkMatrix& viewMatrix, + bool useCoverageAA, + const SkRect& ellipse, + const SkStrokeRec& stroke) { + SkRect bounds; + SkAutoTUnref<GrBatch> batch(create_diellipse_batch(color, viewMatrix, useCoverageAA, ellipse, + stroke, &bounds)); + if (!batch) { + return false; + } target->drawBatch(pipelineBuilder, batch, &bounds); - return true; } @@ -1544,26 +1570,6 @@ static const int kIndicesPerRRect = SK_ARRAY_COUNT(gRRectIndices); static const int kVertsPerRRect = 16; static const int kNumRRectsInIndexBuffer = 256; -GrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(bool isStrokeOnly) { - if (isStrokeOnly) { - if (NULL == fStrokeRRectIndexBuffer) { - fStrokeRRectIndexBuffer = fGpu->createInstancedIndexBuffer(gRRectIndices, - kIndicesPerStrokeRRect, - kNumRRectsInIndexBuffer, - kVertsPerRRect); - } - return fStrokeRRectIndexBuffer; - } else { - if (NULL == fRRectIndexBuffer) { - fRRectIndexBuffer = fGpu->createInstancedIndexBuffer(gRRectIndices, - kIndicesPerRRect, - kNumRRectsInIndexBuffer, - kVertsPerRRect); - } - return fRRectIndexBuffer; - } -} - bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, GrPipelineBuilder* pipelineBuilder, GrColor color, @@ -2057,34 +2063,45 @@ private: const GrIndexBuffer* fIndexBuffer; }; -bool GrOvalRenderer::drawRRect(GrDrawTarget* target, - GrPipelineBuilder* pipelineBuilder, - GrColor color, - const SkMatrix& viewMatrix, - bool useAA, - const SkRRect& rrect, - const SkStrokeRec& stroke) { - if (rrect.isOval()) { - return this->drawOval(target, pipelineBuilder, color, viewMatrix, useAA, rrect.getBounds(), - stroke); - } - - bool useCoverageAA = useAA && - !pipelineBuilder->getRenderTarget()->isMultisampled(); - - // only anti-aliased rrects for now - if (!useCoverageAA) { - return false; - } - - if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { - return false; +static GrIndexBuffer* create_rrect_indexbuffer(GrIndexBuffer** strokeRRectIndexBuffer, + GrIndexBuffer** rrectIndexBuffer, + bool isStrokeOnly, + GrGpu* gpu) { + if (isStrokeOnly) { + if (NULL == *strokeRRectIndexBuffer) { + *strokeRRectIndexBuffer = gpu->createInstancedIndexBuffer(gRRectIndices, + kIndicesPerStrokeRRect, + kNumRRectsInIndexBuffer, + kVertsPerRRect); + } + return *strokeRRectIndexBuffer; + } else { + if (NULL == *rrectIndexBuffer) { + *rrectIndexBuffer = gpu->createInstancedIndexBuffer(gRRectIndices, + kIndicesPerRRect, + kNumRRectsInIndexBuffer, + kVertsPerRRect); + } + return *rrectIndexBuffer; } +} +static GrBatch* create_rrect_batch(GrColor color, + const SkMatrix& viewMatrix, + const SkRRect& rrect, + const SkStrokeRec& stroke, + SkRect* bounds, + GrIndexBuffer** strokeRRectIndexBuffer, + GrIndexBuffer** rrectIndexBuffer, + GrGpu* gpu) { + SkASSERT(viewMatrix.rectStaysRect()); + SkASSERT(rrect.isSimple()); + SkASSERT(!rrect.isOval()); + + // RRect batchs only handle simple, but not too simple, rrects // do any matrix crunching before we reset the draw state for device coords const SkRect& rrectBounds = rrect.getBounds(); - SkRect bounds; - viewMatrix.mapRect(&bounds, rrectBounds); + viewMatrix.mapRect(bounds, rrectBounds); SkVector radii = rrect.getSimpleRadii(); SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*radii.fX + @@ -2114,7 +2131,7 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, // if half of strokewidth is greater than radius, we don't handle that right now if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStroke.fY > yRadius) { - return false; + return NULL; } } @@ -2124,13 +2141,16 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, // We could consider falling back to rect rendering here, since a tiny radius is // indistinguishable from a square corner. if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { - return false; + return NULL; } - GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly); + GrIndexBuffer* indexBuffer = create_rrect_indexbuffer(strokeRRectIndexBuffer, + rrectIndexBuffer, + isStrokeOnly, + gpu); if (NULL == indexBuffer) { SkDebugf("Failed to create index buffer!\n"); - return false; + return NULL; } // if the corners are circles, use the circle renderer @@ -2149,7 +2169,7 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, innerRadius = xRadius - halfWidth; } outerRadius += halfWidth; - bounds.outset(halfWidth, halfWidth); + bounds->outset(halfWidth, halfWidth); } isStrokeOnly = (isStrokeOnly && innerRadius >= 0); @@ -2163,7 +2183,7 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, innerRadius -= SK_ScalarHalf; // Expand the rect so all the pixels will be captured. - bounds.outset(SK_ScalarHalf, SK_ScalarHalf); + bounds->outset(SK_ScalarHalf, SK_ScalarHalf); RRectCircleRendererBatch::Geometry geometry; geometry.fViewMatrix = viewMatrix; @@ -2171,10 +2191,9 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, geometry.fInnerRadius = innerRadius; geometry.fOuterRadius = outerRadius; geometry.fStroke = isStrokeOnly; - geometry.fDevBounds = bounds; + geometry.fDevBounds = *bounds; - SkAutoTUnref<GrBatch> batch(RRectCircleRendererBatch::Create(geometry, indexBuffer)); - target->drawBatch(pipelineBuilder, batch, &bounds); + return RRectCircleRendererBatch::Create(geometry, indexBuffer); // otherwise we use the ellipse renderer } else { @@ -2190,13 +2209,13 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, // we only handle thick strokes for near-circular ellipses if (scaledStroke.length() > SK_ScalarHalf && (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) { - return false; + return NULL; } // we don't handle it if curvature of the stroke is less than curvature of the ellipse if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius || scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) { - return false; + return NULL; } // this is legit only if scale & translation (which should be the case at the moment) @@ -2207,13 +2226,13 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, xRadius += scaledStroke.fX; yRadius += scaledStroke.fY; - bounds.outset(scaledStroke.fX, scaledStroke.fY); + bounds->outset(scaledStroke.fX, scaledStroke.fY); } isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); // Expand the rect so all the pixels will be captured. - bounds.outset(SK_ScalarHalf, SK_ScalarHalf); + bounds->outset(SK_ScalarHalf, SK_ScalarHalf); RRectEllipseRendererBatch::Geometry geometry; geometry.fViewMatrix = viewMatrix; @@ -2223,10 +2242,101 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, geometry.fInnerXRadius = innerXRadius; geometry.fInnerYRadius = innerYRadius; geometry.fStroke = isStrokeOnly; - geometry.fDevBounds = bounds; + geometry.fDevBounds = *bounds; - SkAutoTUnref<GrBatch> batch(RRectEllipseRendererBatch::Create(geometry, indexBuffer)); - target->drawBatch(pipelineBuilder, batch, &bounds); + return RRectEllipseRendererBatch::Create(geometry, indexBuffer); } +} + +bool GrOvalRenderer::drawRRect(GrDrawTarget* target, + GrPipelineBuilder* pipelineBuilder, + GrColor color, + const SkMatrix& viewMatrix, + bool useAA, + const SkRRect& rrect, + const SkStrokeRec& stroke) { + if (rrect.isOval()) { + return this->drawOval(target, pipelineBuilder, color, viewMatrix, useAA, rrect.getBounds(), + stroke); + } + + bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isMultisampled(); + + // only anti-aliased rrects for now + if (!useCoverageAA) { + return false; + } + + if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { + return false; + } + + SkRect bounds; + SkAutoTUnref<GrBatch> batch(create_rrect_batch(color, viewMatrix, rrect, stroke, &bounds, + &fStrokeRRectIndexBuffer, &fRRectIndexBuffer, + fGpu)); + if (!batch) { + return false; + } + + target->drawBatch(pipelineBuilder, batch, &bounds); return true; } + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef GR_TEST_UTILS + +static SkStrokeRec random_strokerec(SkRandom* random) { + SkStrokeRec::InitStyle style = + SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1)); + SkStrokeRec rec(style); + bool strokeAndFill = random->nextBool(); + SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f; + rec.setStrokeStyle(strokeWidth, strokeAndFill); + return rec; +} + +BATCH_TEST_DEFINE(CircleBatch) { + SkMatrix viewMatrix = GrTest::TestMatrix(random); + GrColor color = GrRandomColor(random); + bool useCoverageAA = random->nextBool(); + SkRect circle = GrTest::TestRect(random); + SkRect bounds; // unused + return create_circle_batch(color, viewMatrix, useCoverageAA, circle, random_strokerec(random), + &bounds); +} + +BATCH_TEST_DEFINE(EllipseBatch) { + SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); + GrColor color = GrRandomColor(random); + bool useCoverageAA = random->nextBool(); + SkRect ellipse = GrTest::TestRect(random); + SkRect bounds; // unused + return create_ellipse_batch(color, viewMatrix, useCoverageAA, ellipse, + random_strokerec(random), &bounds); +} + +BATCH_TEST_DEFINE(DIEllipseBatch) { + SkMatrix viewMatrix = GrTest::TestMatrix(random); + GrColor color = GrRandomColor(random); + bool useCoverageAA = random->nextBool(); + SkRect ellipse = GrTest::TestRect(random); + SkRect bounds; // unused + return create_diellipse_batch(color, viewMatrix, useCoverageAA, ellipse, + random_strokerec(random), &bounds); +} + +BATCH_TEST_DEFINE(RRectBatch) { + SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); + GrColor color = GrRandomColor(random); + const SkRRect& rrect = GrTest::TestRRectSimple(random); + + static GrIndexBuffer* gStrokeRRectIndexBuffer; + static GrIndexBuffer* gRRectIndexBuffer; + SkRect bounds; + return create_rrect_batch(color, viewMatrix, rrect, random_strokerec(random), &bounds, + &gStrokeRRectIndexBuffer, &gRRectIndexBuffer, context->getGpu()); +} + +#endif diff --git a/src/gpu/GrOvalRenderer.h b/src/gpu/GrOvalRenderer.h index 9d861c5b8d..f31aa69bb2 100644 --- a/src/gpu/GrOvalRenderer.h +++ b/src/gpu/GrOvalRenderer.h @@ -79,8 +79,6 @@ private: const SkRect& circle, const SkStrokeRec& stroke); - GrIndexBuffer* rRectIndexBuffer(bool isStrokeOnly); - GrGpu* fGpu; GrIndexBuffer* fRRectIndexBuffer; GrIndexBuffer* fStrokeRRectIndexBuffer; diff --git a/src/gpu/GrTestUtils.cpp b/src/gpu/GrTestUtils.cpp index d0cea5565c..36256c3173 100644 --- a/src/gpu/GrTestUtils.cpp +++ b/src/gpu/GrTestUtils.cpp @@ -7,6 +7,7 @@ #include "GrTestUtils.h" #include "SkMatrix.h" +#include "SkRRect.h" #ifdef GR_TEST_UTILS @@ -15,6 +16,7 @@ const SkMatrix& TestMatrix(SkRandom* random) { static SkMatrix gMatrices[5]; static bool gOnce; if (!gOnce) { + gOnce = true; gMatrices[0].reset(); gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100)); gMatrices[2].setRotate(SkIntToScalar(17)); @@ -24,15 +26,15 @@ const SkMatrix& TestMatrix(SkRandom* random) { gMatrices[4].setRotate(SkIntToScalar(215)); gMatrices[4].set(SkMatrix::kMPersp0, 0.00013f); gMatrices[4].set(SkMatrix::kMPersp1, -0.000039f); - gOnce = true; } return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))]; } const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) { - static SkMatrix gMatrices[4]; + static SkMatrix gMatrices[5]; static bool gOnce; if (!gOnce) { + gOnce = true; // identity gMatrices[0].reset(); // translation @@ -46,7 +48,6 @@ const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) { gMatrices[4].reset(); gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1)); gMatrices[4].setRotate(47); - gOnce = true; for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) { SkASSERT(gMatrices[i].preservesRightAngles()); @@ -55,20 +56,70 @@ const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) { return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))]; } +const SkMatrix& TestMatrixRectStaysRect(SkRandom* random) { + static SkMatrix gMatrices[6]; + static bool gOnce; + if (!gOnce) { + gOnce = true; + // identity + gMatrices[0].reset(); + // translation + gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100)); + // scale + gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17)); + // scale + translation + gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17)); + gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33)); + // reflection + gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1)); + // 90 degress rotation + gMatrices[5].setRotate(90); + + for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) { + SkASSERT(gMatrices[i].rectStaysRect()); + } + } + return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))]; +} + const SkRect& TestRect(SkRandom* random) { - static SkRect gRects[1]; + static SkRect gRects[7]; static bool gOnce; if (!gOnce) { + gOnce = true; gRects[0] = SkRect::MakeWH(1.f, 1.f); gRects[1] = SkRect::MakeWH(1.0f, 256.0f); gRects[2] = SkRect::MakeWH(256.0f, 1.0f); gRects[4] = SkRect::MakeLargest(); gRects[5] = SkRect::MakeLTRB(-65535.0f, -65535.0f, 65535.0f, 65535.0f); gRects[6] = SkRect::MakeLTRB(10.0f, 10.0f, -10.0f, -10.0f); - gOnce = true; } return gRects[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRects)))]; } + +const SkRRect& TestRRectSimple(SkRandom* random) { + static SkRRect gRRect[4]; + static bool gOnce; + if (!gOnce) { + gOnce = true; + SkRect square = SkRect::MakeWH(10.f, 10.f); + SkRect rectangle = SkRect::MakeWH(10.f, 20.f); + // rect + gRRect[0].setRect(square); + // oval + gRRect[1].setOval(rectangle); + // true round rect with circular corners + gRRect[2].setRectXY(rectangle, 1.f, 1.f); + // true round rect with elliptical corners + gRRect[3].setRectXY(rectangle, 2.0f, 1.0f); + + for (size_t i = 0; i < SK_ARRAY_COUNT(gRRect); i++) { + SkASSERT(gRRect[i].isSimple()); + } + } + return gRRect[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRRect)))]; +} + }; #endif |