aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2015-04-30 13:49:27 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-30 13:49:27 -0700
commit3e708c53f79a04b588b6ca8e535e61f986d80b47 (patch)
treea074e51af90cf5b96898632a7bfda14e8236b09a /src/gpu
parent1c2c441fede0ae9573afc098017011e3439624a9 (diff)
Add batch unit tests for ovals
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrBatch.h1
-rw-r--r--src/gpu/GrBatchTest.cpp11
-rw-r--r--src/gpu/GrOvalRenderer.cpp334
-rw-r--r--src/gpu/GrOvalRenderer.h2
-rw-r--r--src/gpu/GrTestUtils.cpp61
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(&center, 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