OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrOvalRenderer.h" | 8 #include "GrOvalRenderer.h" |
9 | 9 |
10 #include "GrBatch.h" | 10 #include "GrBatch.h" |
11 #include "GrBatchTarget.h" | 11 #include "GrBatchTarget.h" |
| 12 #include "GrBatchTest.h" |
12 #include "GrBufferAllocPool.h" | 13 #include "GrBufferAllocPool.h" |
13 #include "GrDrawTarget.h" | 14 #include "GrDrawTarget.h" |
14 #include "GrGeometryProcessor.h" | 15 #include "GrGeometryProcessor.h" |
15 #include "GrGpu.h" | 16 #include "GrGpu.h" |
16 #include "GrInvariantOutput.h" | 17 #include "GrInvariantOutput.h" |
17 #include "GrPipelineBuilder.h" | 18 #include "GrPipelineBuilder.h" |
18 #include "GrProcessor.h" | 19 #include "GrProcessor.h" |
19 #include "GrVertexBuffer.h" | 20 #include "GrVertexBuffer.h" |
20 #include "SkRRect.h" | 21 #include "SkRRect.h" |
21 #include "SkStrokeRec.h" | 22 #include "SkStrokeRec.h" |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 bool fCoverageIgnored; | 872 bool fCoverageIgnored; |
872 }; | 873 }; |
873 | 874 |
874 static const int kVertsPerCircle = 4; | 875 static const int kVertsPerCircle = 4; |
875 static const int kIndicesPerCircle = 6; | 876 static const int kIndicesPerCircle = 6; |
876 | 877 |
877 BatchTracker fBatch; | 878 BatchTracker fBatch; |
878 SkSTArray<1, Geometry, true> fGeoData; | 879 SkSTArray<1, Geometry, true> fGeoData; |
879 }; | 880 }; |
880 | 881 |
881 void GrOvalRenderer::drawCircle(GrDrawTarget* target, | 882 static GrBatch* create_circle_batch(GrColor color, |
882 GrPipelineBuilder* pipelineBuilder, | 883 const SkMatrix& viewMatrix, |
883 GrColor color, | 884 bool useCoverageAA, |
884 const SkMatrix& viewMatrix, | 885 const SkRect& circle, |
885 bool useCoverageAA, | 886 const SkStrokeRec& stroke, |
886 const SkRect& circle, | 887 SkRect* bounds) { |
887 const SkStrokeRec& stroke) { | |
888 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); | 888 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); |
889 viewMatrix.mapPoints(¢er, 1); | 889 viewMatrix.mapPoints(¢er, 1); |
890 SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width())); | 890 SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width())); |
891 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); | 891 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); |
892 | 892 |
893 SkStrokeRec::Style style = stroke.getStyle(); | 893 SkStrokeRec::Style style = stroke.getStyle(); |
894 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 894 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
895 SkStrokeRec::kHairline_Style == style; | 895 SkStrokeRec::kHairline_Style == style; |
896 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 896 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
897 | 897 |
(...skipping 13 matching lines...) Expand all Loading... |
911 } | 911 } |
912 } | 912 } |
913 | 913 |
914 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform simpler | 914 // The radii are outset for two reasons. First, it allows the shader to simp
ly perform simpler |
915 // computation because the computed alpha is zero, rather than 50%, at the r
adius. | 915 // computation because the computed alpha is zero, rather than 50%, at the r
adius. |
916 // Second, the outer radius is used to compute the verts of the bounding box
that is rendered | 916 // Second, the outer radius is used to compute the verts of the bounding box
that is rendered |
917 // and the outset ensures the box will cover all partially covered by the ci
rcle. | 917 // and the outset ensures the box will cover all partially covered by the ci
rcle. |
918 outerRadius += SK_ScalarHalf; | 918 outerRadius += SK_ScalarHalf; |
919 innerRadius -= SK_ScalarHalf; | 919 innerRadius -= SK_ScalarHalf; |
920 | 920 |
921 SkRect bounds = SkRect::MakeLTRB( | 921 bounds->setLTRB(center.fX - outerRadius, center.fY - outerRadius, |
922 center.fX - outerRadius, | 922 center.fX + outerRadius, center.fY + outerRadius); |
923 center.fY - outerRadius, | |
924 center.fX + outerRadius, | |
925 center.fY + outerRadius | |
926 ); | |
927 | 923 |
928 CircleBatch::Geometry geometry; | 924 CircleBatch::Geometry geometry; |
929 geometry.fViewMatrix = viewMatrix; | 925 geometry.fViewMatrix = viewMatrix; |
930 geometry.fColor = color; | 926 geometry.fColor = color; |
931 geometry.fInnerRadius = innerRadius; | 927 geometry.fInnerRadius = innerRadius; |
932 geometry.fOuterRadius = outerRadius; | 928 geometry.fOuterRadius = outerRadius; |
933 geometry.fStroke = isStrokeOnly && innerRadius > 0; | 929 geometry.fStroke = isStrokeOnly && innerRadius > 0; |
934 geometry.fDevBounds = bounds; | 930 geometry.fDevBounds = *bounds; |
935 | 931 |
936 SkAutoTUnref<GrBatch> batch(CircleBatch::Create(geometry)); | 932 return CircleBatch::Create(geometry); |
| 933 } |
| 934 |
| 935 void GrOvalRenderer::drawCircle(GrDrawTarget* target, |
| 936 GrPipelineBuilder* pipelineBuilder, |
| 937 GrColor color, |
| 938 const SkMatrix& viewMatrix, |
| 939 bool useCoverageAA, |
| 940 const SkRect& circle, |
| 941 const SkStrokeRec& stroke) { |
| 942 SkRect bounds; |
| 943 SkAutoTUnref<GrBatch> batch(create_circle_batch(color, viewMatrix, useCovera
geAA, circle, |
| 944 stroke, &bounds)); |
937 target->drawBatch(pipelineBuilder, batch, &bounds); | 945 target->drawBatch(pipelineBuilder, batch, &bounds); |
938 } | 946 } |
939 | 947 |
940 /////////////////////////////////////////////////////////////////////////////// | 948 /////////////////////////////////////////////////////////////////////////////// |
941 | 949 |
942 class EllipseBatch : public GrBatch { | 950 class EllipseBatch : public GrBatch { |
943 public: | 951 public: |
944 struct Geometry { | 952 struct Geometry { |
945 GrColor fColor; | 953 GrColor fColor; |
946 SkMatrix fViewMatrix; | 954 SkMatrix fViewMatrix; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1131 bool fCoverageIgnored; | 1139 bool fCoverageIgnored; |
1132 }; | 1140 }; |
1133 | 1141 |
1134 static const int kVertsPerEllipse = 4; | 1142 static const int kVertsPerEllipse = 4; |
1135 static const int kIndicesPerEllipse = 6; | 1143 static const int kIndicesPerEllipse = 6; |
1136 | 1144 |
1137 BatchTracker fBatch; | 1145 BatchTracker fBatch; |
1138 SkSTArray<1, Geometry, true> fGeoData; | 1146 SkSTArray<1, Geometry, true> fGeoData; |
1139 }; | 1147 }; |
1140 | 1148 |
1141 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, | 1149 static GrBatch* create_ellipse_batch(GrColor color, |
1142 GrPipelineBuilder* pipelineBuilder, | 1150 const SkMatrix& viewMatrix, |
1143 GrColor color, | 1151 bool useCoverageAA, |
1144 const SkMatrix& viewMatrix, | 1152 const SkRect& ellipse, |
1145 bool useCoverageAA, | 1153 const SkStrokeRec& stroke, |
1146 const SkRect& ellipse, | 1154 SkRect* bounds) { |
1147 const SkStrokeRec& stroke) { | |
1148 #ifdef SK_DEBUG | 1155 #ifdef SK_DEBUG |
1149 { | 1156 { |
1150 // we should have checked for this previously | 1157 // we should have checked for this previously |
1151 bool isAxisAlignedEllipse = viewMatrix.rectStaysRect(); | 1158 bool isAxisAlignedEllipse = viewMatrix.rectStaysRect(); |
1152 SkASSERT(useCoverageAA && isAxisAlignedEllipse); | 1159 SkASSERT(useCoverageAA && isAxisAlignedEllipse); |
1153 } | 1160 } |
1154 #endif | 1161 #endif |
1155 | 1162 |
1156 // do any matrix crunching before we reset the draw state for device coords | 1163 // do any matrix crunching before we reset the draw state for device coords |
1157 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); | 1164 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); |
(...skipping 23 matching lines...) Expand all Loading... |
1181 if (hasStroke) { | 1188 if (hasStroke) { |
1182 if (SkScalarNearlyZero(scaledStroke.length())) { | 1189 if (SkScalarNearlyZero(scaledStroke.length())) { |
1183 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); | 1190 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); |
1184 } else { | 1191 } else { |
1185 scaledStroke.scale(SK_ScalarHalf); | 1192 scaledStroke.scale(SK_ScalarHalf); |
1186 } | 1193 } |
1187 | 1194 |
1188 // we only handle thick strokes for near-circular ellipses | 1195 // we only handle thick strokes for near-circular ellipses |
1189 if (scaledStroke.length() > SK_ScalarHalf && | 1196 if (scaledStroke.length() > SK_ScalarHalf && |
1190 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)
) { | 1197 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)
) { |
1191 return false; | 1198 return NULL; |
1192 } | 1199 } |
1193 | 1200 |
1194 // we don't handle it if curvature of the stroke is less than curvature
of the ellipse | 1201 // we don't handle it if curvature of the stroke is less than curvature
of the ellipse |
1195 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY
)*xRadius || | 1202 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY
)*xRadius || |
1196 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX
)*yRadius) { | 1203 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX
)*yRadius) { |
1197 return false; | 1204 return NULL; |
1198 } | 1205 } |
1199 | 1206 |
1200 // this is legit only if scale & translation (which should be the case a
t the moment) | 1207 // this is legit only if scale & translation (which should be the case a
t the moment) |
1201 if (isStrokeOnly) { | 1208 if (isStrokeOnly) { |
1202 innerXRadius = xRadius - scaledStroke.fX; | 1209 innerXRadius = xRadius - scaledStroke.fX; |
1203 innerYRadius = yRadius - scaledStroke.fY; | 1210 innerYRadius = yRadius - scaledStroke.fY; |
1204 } | 1211 } |
1205 | 1212 |
1206 xRadius += scaledStroke.fX; | 1213 xRadius += scaledStroke.fX; |
1207 yRadius += scaledStroke.fY; | 1214 yRadius += scaledStroke.fY; |
1208 } | 1215 } |
1209 | 1216 |
1210 // We've extended the outer x radius out half a pixel to antialias. | 1217 // We've extended the outer x radius out half a pixel to antialias. |
1211 // This will also expand the rect so all the pixels will be captured. | 1218 // This will also expand the rect so all the pixels will be captured. |
1212 // TODO: Consider if we should use sqrt(2)/2 instead | 1219 // TODO: Consider if we should use sqrt(2)/2 instead |
1213 xRadius += SK_ScalarHalf; | 1220 xRadius += SK_ScalarHalf; |
1214 yRadius += SK_ScalarHalf; | 1221 yRadius += SK_ScalarHalf; |
1215 | 1222 |
1216 SkRect bounds = SkRect::MakeLTRB( | 1223 bounds->setLTRB(center.fX - xRadius, center.fY - yRadius, |
1217 center.fX - xRadius, | 1224 center.fX + xRadius, center.fY + yRadius); |
1218 center.fY - yRadius, | |
1219 center.fX + xRadius, | |
1220 center.fY + yRadius | |
1221 ); | |
1222 | 1225 |
1223 EllipseBatch::Geometry geometry; | 1226 EllipseBatch::Geometry geometry; |
1224 geometry.fViewMatrix = viewMatrix; | 1227 geometry.fViewMatrix = viewMatrix; |
1225 geometry.fColor = color; | 1228 geometry.fColor = color; |
1226 geometry.fXRadius = xRadius; | 1229 geometry.fXRadius = xRadius; |
1227 geometry.fYRadius = yRadius; | 1230 geometry.fYRadius = yRadius; |
1228 geometry.fInnerXRadius = innerXRadius; | 1231 geometry.fInnerXRadius = innerXRadius; |
1229 geometry.fInnerYRadius = innerYRadius; | 1232 geometry.fInnerYRadius = innerYRadius; |
1230 geometry.fStroke = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0; | 1233 geometry.fStroke = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0; |
1231 geometry.fDevBounds = bounds; | 1234 geometry.fDevBounds = *bounds; |
1232 | 1235 |
1233 SkAutoTUnref<GrBatch> batch(EllipseBatch::Create(geometry)); | 1236 return EllipseBatch::Create(geometry); |
| 1237 } |
| 1238 |
| 1239 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, |
| 1240 GrPipelineBuilder* pipelineBuilder, |
| 1241 GrColor color, |
| 1242 const SkMatrix& viewMatrix, |
| 1243 bool useCoverageAA, |
| 1244 const SkRect& ellipse, |
| 1245 const SkStrokeRec& stroke) { |
| 1246 SkRect bounds; |
| 1247 SkAutoTUnref<GrBatch> batch(create_ellipse_batch(color, viewMatrix, useCover
ageAA, ellipse, |
| 1248 stroke, &bounds)); |
| 1249 if (!batch) { |
| 1250 return false; |
| 1251 } |
| 1252 |
1234 target->drawBatch(pipelineBuilder, batch, &bounds); | 1253 target->drawBatch(pipelineBuilder, batch, &bounds); |
1235 | |
1236 return true; | 1254 return true; |
1237 } | 1255 } |
1238 | 1256 |
1239 ////////////////////////////////////////////////////////////////////////////////
///////////////// | 1257 ////////////////////////////////////////////////////////////////////////////////
///////////////// |
1240 | 1258 |
1241 class DIEllipseBatch : public GrBatch { | 1259 class DIEllipseBatch : public GrBatch { |
1242 public: | 1260 public: |
1243 struct Geometry { | 1261 struct Geometry { |
1244 GrColor fColor; | 1262 GrColor fColor; |
1245 SkMatrix fViewMatrix; | 1263 SkMatrix fViewMatrix; |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1423 bool fCoverageIgnored; | 1441 bool fCoverageIgnored; |
1424 }; | 1442 }; |
1425 | 1443 |
1426 static const int kVertsPerEllipse = 4; | 1444 static const int kVertsPerEllipse = 4; |
1427 static const int kIndicesPerEllipse = 6; | 1445 static const int kIndicesPerEllipse = 6; |
1428 | 1446 |
1429 BatchTracker fBatch; | 1447 BatchTracker fBatch; |
1430 SkSTArray<1, Geometry, true> fGeoData; | 1448 SkSTArray<1, Geometry, true> fGeoData; |
1431 }; | 1449 }; |
1432 | 1450 |
1433 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, | 1451 static GrBatch* create_diellipse_batch(GrColor color, |
1434 GrPipelineBuilder* pipelineBuilder, | 1452 const SkMatrix& viewMatrix, |
1435 GrColor color, | 1453 bool useCoverageAA, |
1436 const SkMatrix& viewMatrix, | 1454 const SkRect& ellipse, |
1437 bool useCoverageAA, | 1455 const SkStrokeRec& stroke, |
1438 const SkRect& ellipse, | 1456 SkRect* bounds) { |
1439 const SkStrokeRec& stroke) { | |
1440 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); | 1457 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); |
1441 SkScalar xRadius = SkScalarHalf(ellipse.width()); | 1458 SkScalar xRadius = SkScalarHalf(ellipse.width()); |
1442 SkScalar yRadius = SkScalarHalf(ellipse.height()); | 1459 SkScalar yRadius = SkScalarHalf(ellipse.height()); |
1443 | 1460 |
1444 SkStrokeRec::Style style = stroke.getStyle(); | 1461 SkStrokeRec::Style style = stroke.getStyle(); |
1445 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? | 1462 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? |
1446 DIEllipseEdgeEffect::kStroke : | 1463 DIEllipseEdgeEffect::kStroke : |
1447 (SkStrokeRec::kHairline_Style == style) ? | 1464 (SkStrokeRec::kHairline_Style == style) ? |
1448 DIEllipseEdgeEffect::kHairline : DIEllipseEd
geEffect::kFill; | 1465 DIEllipseEdgeEffect::kHairline : DIEllipseEd
geEffect::kFill; |
1449 | 1466 |
1450 SkScalar innerXRadius = 0; | 1467 SkScalar innerXRadius = 0; |
1451 SkScalar innerYRadius = 0; | 1468 SkScalar innerYRadius = 0; |
1452 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty
le) { | 1469 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty
le) { |
1453 SkScalar strokeWidth = stroke.getWidth(); | 1470 SkScalar strokeWidth = stroke.getWidth(); |
1454 | 1471 |
1455 if (SkScalarNearlyZero(strokeWidth)) { | 1472 if (SkScalarNearlyZero(strokeWidth)) { |
1456 strokeWidth = SK_ScalarHalf; | 1473 strokeWidth = SK_ScalarHalf; |
1457 } else { | 1474 } else { |
1458 strokeWidth *= SK_ScalarHalf; | 1475 strokeWidth *= SK_ScalarHalf; |
1459 } | 1476 } |
1460 | 1477 |
1461 // we only handle thick strokes for near-circular ellipses | 1478 // we only handle thick strokes for near-circular ellipses |
1462 if (strokeWidth > SK_ScalarHalf && | 1479 if (strokeWidth > SK_ScalarHalf && |
1463 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)
) { | 1480 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)
) { |
1464 return false; | 1481 return NULL; |
1465 } | 1482 } |
1466 | 1483 |
1467 // we don't handle it if curvature of the stroke is less than curvature
of the ellipse | 1484 // we don't handle it if curvature of the stroke is less than curvature
of the ellipse |
1468 if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius || | 1485 if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius || |
1469 strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) { | 1486 strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) { |
1470 return false; | 1487 return NULL; |
1471 } | 1488 } |
1472 | 1489 |
1473 // set inner radius (if needed) | 1490 // set inner radius (if needed) |
1474 if (SkStrokeRec::kStroke_Style == style) { | 1491 if (SkStrokeRec::kStroke_Style == style) { |
1475 innerXRadius = xRadius - strokeWidth; | 1492 innerXRadius = xRadius - strokeWidth; |
1476 innerYRadius = yRadius - strokeWidth; | 1493 innerYRadius = yRadius - strokeWidth; |
1477 } | 1494 } |
1478 | 1495 |
1479 xRadius += strokeWidth; | 1496 xRadius += strokeWidth; |
1480 yRadius += strokeWidth; | 1497 yRadius += strokeWidth; |
1481 } | 1498 } |
1482 if (DIEllipseEdgeEffect::kStroke == mode) { | 1499 if (DIEllipseEdgeEffect::kStroke == mode) { |
1483 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt
roke : | 1500 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt
roke : |
1484 DIEllipseEdgeEffect::kFi
ll; | 1501 DIEllipseEdgeEffect::kFi
ll; |
1485 } | 1502 } |
1486 | 1503 |
1487 // This expands the outer rect so that after CTM we end up with a half-pixel
border | 1504 // This expands the outer rect so that after CTM we end up with a half-pixel
border |
1488 SkScalar a = viewMatrix[SkMatrix::kMScaleX]; | 1505 SkScalar a = viewMatrix[SkMatrix::kMScaleX]; |
1489 SkScalar b = viewMatrix[SkMatrix::kMSkewX]; | 1506 SkScalar b = viewMatrix[SkMatrix::kMSkewX]; |
1490 SkScalar c = viewMatrix[SkMatrix::kMSkewY]; | 1507 SkScalar c = viewMatrix[SkMatrix::kMSkewY]; |
1491 SkScalar d = viewMatrix[SkMatrix::kMScaleY]; | 1508 SkScalar d = viewMatrix[SkMatrix::kMScaleY]; |
1492 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); | 1509 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); |
1493 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); | 1510 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); |
1494 | 1511 |
1495 SkRect bounds = SkRect::MakeLTRB( | 1512 bounds->setLTRB(center.fX - xRadius - geoDx, center.fY - yRadius - geoDy, |
1496 center.fX - xRadius - geoDx, | 1513 center.fX + xRadius + geoDx, center.fY + yRadius + geoDy); |
1497 center.fY - yRadius - geoDy, | |
1498 center.fX + xRadius + geoDx, | |
1499 center.fY + yRadius + geoDy | |
1500 ); | |
1501 | 1514 |
1502 DIEllipseBatch::Geometry geometry; | 1515 DIEllipseBatch::Geometry geometry; |
1503 geometry.fViewMatrix = viewMatrix; | 1516 geometry.fViewMatrix = viewMatrix; |
1504 geometry.fColor = color; | 1517 geometry.fColor = color; |
1505 geometry.fXRadius = xRadius; | 1518 geometry.fXRadius = xRadius; |
1506 geometry.fYRadius = yRadius; | 1519 geometry.fYRadius = yRadius; |
1507 geometry.fInnerXRadius = innerXRadius; | 1520 geometry.fInnerXRadius = innerXRadius; |
1508 geometry.fInnerYRadius = innerYRadius; | 1521 geometry.fInnerYRadius = innerYRadius; |
1509 geometry.fGeoDx = geoDx; | 1522 geometry.fGeoDx = geoDx; |
1510 geometry.fGeoDy = geoDy; | 1523 geometry.fGeoDy = geoDy; |
1511 geometry.fMode = mode; | 1524 geometry.fMode = mode; |
1512 geometry.fBounds = bounds; | 1525 geometry.fBounds = *bounds; |
1513 | 1526 |
1514 viewMatrix.mapRect(&bounds); | 1527 viewMatrix.mapRect(bounds); |
| 1528 return DIEllipseBatch::Create(geometry); |
| 1529 } |
1515 | 1530 |
1516 SkAutoTUnref<GrBatch> batch(DIEllipseBatch::Create(geometry)); | 1531 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, |
| 1532 GrPipelineBuilder* pipelineBuilder, |
| 1533 GrColor color, |
| 1534 const SkMatrix& viewMatrix, |
| 1535 bool useCoverageAA, |
| 1536 const SkRect& ellipse, |
| 1537 const SkStrokeRec& stroke) { |
| 1538 SkRect bounds; |
| 1539 SkAutoTUnref<GrBatch> batch(create_diellipse_batch(color, viewMatrix, useCov
erageAA, ellipse, |
| 1540 stroke, &bounds)); |
| 1541 if (!batch) { |
| 1542 return false; |
| 1543 } |
1517 target->drawBatch(pipelineBuilder, batch, &bounds); | 1544 target->drawBatch(pipelineBuilder, batch, &bounds); |
1518 | |
1519 return true; | 1545 return true; |
1520 } | 1546 } |
1521 | 1547 |
1522 /////////////////////////////////////////////////////////////////////////////// | 1548 /////////////////////////////////////////////////////////////////////////////// |
1523 | 1549 |
1524 static const uint16_t gRRectIndices[] = { | 1550 static const uint16_t gRRectIndices[] = { |
1525 // corners | 1551 // corners |
1526 0, 1, 5, 0, 5, 4, | 1552 0, 1, 5, 0, 5, 4, |
1527 2, 3, 7, 2, 7, 6, | 1553 2, 3, 7, 2, 7, 6, |
1528 8, 9, 13, 8, 13, 12, | 1554 8, 9, 13, 8, 13, 12, |
1529 10, 11, 15, 10, 15, 14, | 1555 10, 11, 15, 10, 15, 14, |
1530 | 1556 |
1531 // edges | 1557 // edges |
1532 1, 2, 6, 1, 6, 5, | 1558 1, 2, 6, 1, 6, 5, |
1533 4, 5, 9, 4, 9, 8, | 1559 4, 5, 9, 4, 9, 8, |
1534 6, 7, 11, 6, 11, 10, | 1560 6, 7, 11, 6, 11, 10, |
1535 9, 10, 14, 9, 14, 13, | 1561 9, 10, 14, 9, 14, 13, |
1536 | 1562 |
1537 // center | 1563 // center |
1538 // we place this at the end so that we can ignore these indices when renderi
ng stroke-only | 1564 // we place this at the end so that we can ignore these indices when renderi
ng stroke-only |
1539 5, 6, 10, 5, 10, 9 | 1565 5, 6, 10, 5, 10, 9 |
1540 }; | 1566 }; |
1541 | 1567 |
1542 static const int kIndicesPerStrokeRRect = SK_ARRAY_COUNT(gRRectIndices) - 6; | 1568 static const int kIndicesPerStrokeRRect = SK_ARRAY_COUNT(gRRectIndices) - 6; |
1543 static const int kIndicesPerRRect = SK_ARRAY_COUNT(gRRectIndices); | 1569 static const int kIndicesPerRRect = SK_ARRAY_COUNT(gRRectIndices); |
1544 static const int kVertsPerRRect = 16; | 1570 static const int kVertsPerRRect = 16; |
1545 static const int kNumRRectsInIndexBuffer = 256; | 1571 static const int kNumRRectsInIndexBuffer = 256; |
1546 | 1572 |
1547 GrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(bool isStrokeOnly) { | |
1548 if (isStrokeOnly) { | |
1549 if (NULL == fStrokeRRectIndexBuffer) { | |
1550 fStrokeRRectIndexBuffer = fGpu->createInstancedIndexBuffer(gRRectInd
ices, | |
1551 kIndicesP
erStrokeRRect, | |
1552 kNumRRect
sInIndexBuffer, | |
1553 kVertsPer
RRect); | |
1554 } | |
1555 return fStrokeRRectIndexBuffer; | |
1556 } else { | |
1557 if (NULL == fRRectIndexBuffer) { | |
1558 fRRectIndexBuffer = fGpu->createInstancedIndexBuffer(gRRectIndices, | |
1559 kIndicesPerRRec
t, | |
1560 kNumRRectsInInd
exBuffer, | |
1561 kVertsPerRRect)
; | |
1562 } | |
1563 return fRRectIndexBuffer; | |
1564 } | |
1565 } | |
1566 | |
1567 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, | 1573 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, |
1568 GrPipelineBuilder* pipelineBuilder, | 1574 GrPipelineBuilder* pipelineBuilder, |
1569 GrColor color, | 1575 GrColor color, |
1570 const SkMatrix& viewMatrix, | 1576 const SkMatrix& viewMatrix, |
1571 bool useAA, | 1577 bool useAA, |
1572 const SkRRect& origOuter, | 1578 const SkRRect& origOuter, |
1573 const SkRRect& origInner) { | 1579 const SkRRect& origInner) { |
1574 bool applyAA = useAA && | 1580 bool applyAA = useAA && |
1575 !pipelineBuilder->getRenderTarget()->isMultisampled(); | 1581 !pipelineBuilder->getRenderTarget()->isMultisampled(); |
1576 GrPipelineBuilder::AutoRestoreFragmentProcessors arfp; | 1582 GrPipelineBuilder::AutoRestoreFragmentProcessors arfp; |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2050 bool fUsesLocalCoords; | 2056 bool fUsesLocalCoords; |
2051 bool fColorIgnored; | 2057 bool fColorIgnored; |
2052 bool fCoverageIgnored; | 2058 bool fCoverageIgnored; |
2053 }; | 2059 }; |
2054 | 2060 |
2055 BatchTracker fBatch; | 2061 BatchTracker fBatch; |
2056 SkSTArray<1, Geometry, true> fGeoData; | 2062 SkSTArray<1, Geometry, true> fGeoData; |
2057 const GrIndexBuffer* fIndexBuffer; | 2063 const GrIndexBuffer* fIndexBuffer; |
2058 }; | 2064 }; |
2059 | 2065 |
2060 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, | 2066 static GrIndexBuffer* create_rrect_indexbuffer(GrIndexBuffer** strokeRRectIndexB
uffer, |
2061 GrPipelineBuilder* pipelineBuilder, | 2067 GrIndexBuffer** rrectIndexBuffer, |
2062 GrColor color, | 2068 bool isStrokeOnly, |
2063 const SkMatrix& viewMatrix, | 2069 GrGpu* gpu) { |
2064 bool useAA, | 2070 if (isStrokeOnly) { |
2065 const SkRRect& rrect, | 2071 if (NULL == *strokeRRectIndexBuffer) { |
2066 const SkStrokeRec& stroke) { | 2072 *strokeRRectIndexBuffer = gpu->createInstancedIndexBuffer(gRRectIndi
ces, |
2067 if (rrect.isOval()) { | 2073 kIndicesPe
rStrokeRRect, |
2068 return this->drawOval(target, pipelineBuilder, color, viewMatrix, useAA,
rrect.getBounds(), | 2074 kNumRRects
InIndexBuffer, |
2069 stroke); | 2075 kVertsPerR
Rect); |
| 2076 } |
| 2077 return *strokeRRectIndexBuffer; |
| 2078 } else { |
| 2079 if (NULL == *rrectIndexBuffer) { |
| 2080 *rrectIndexBuffer = gpu->createInstancedIndexBuffer(gRRectIndices, |
| 2081 kIndicesPerRRect
, |
| 2082 kNumRRectsInInde
xBuffer, |
| 2083 kVertsPerRRect); |
| 2084 } |
| 2085 return *rrectIndexBuffer; |
2070 } | 2086 } |
| 2087 } |
2071 | 2088 |
2072 bool useCoverageAA = useAA && | 2089 static GrBatch* create_rrect_batch(GrColor color, |
2073 !pipelineBuilder->getRenderTarget()->isMultisampled(); | 2090 const SkMatrix& viewMatrix, |
| 2091 const SkRRect& rrect, |
| 2092 const SkStrokeRec& stroke, |
| 2093 SkRect* bounds, |
| 2094 GrIndexBuffer** strokeRRectIndexBuffer, |
| 2095 GrIndexBuffer** rrectIndexBuffer, |
| 2096 GrGpu* gpu) { |
| 2097 SkASSERT(viewMatrix.rectStaysRect()); |
| 2098 SkASSERT(rrect.isSimple()); |
| 2099 SkASSERT(!rrect.isOval()); |
2074 | 2100 |
2075 // only anti-aliased rrects for now | 2101 // RRect batchs only handle simple, but not too simple, rrects |
2076 if (!useCoverageAA) { | |
2077 return false; | |
2078 } | |
2079 | |
2080 if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { | |
2081 return false; | |
2082 } | |
2083 | |
2084 // do any matrix crunching before we reset the draw state for device coords | 2102 // do any matrix crunching before we reset the draw state for device coords |
2085 const SkRect& rrectBounds = rrect.getBounds(); | 2103 const SkRect& rrectBounds = rrect.getBounds(); |
2086 SkRect bounds; | 2104 viewMatrix.mapRect(bounds, rrectBounds); |
2087 viewMatrix.mapRect(&bounds, rrectBounds); | |
2088 | 2105 |
2089 SkVector radii = rrect.getSimpleRadii(); | 2106 SkVector radii = rrect.getSimpleRadii(); |
2090 SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*radii.fX + | 2107 SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*radii.fX + |
2091 viewMatrix[SkMatrix::kMSkewY]*radii.fY); | 2108 viewMatrix[SkMatrix::kMSkewY]*radii.fY); |
2092 SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*radii.fX + | 2109 SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*radii.fX + |
2093 viewMatrix[SkMatrix::kMScaleY]*radii.fY); | 2110 viewMatrix[SkMatrix::kMScaleY]*radii.fY); |
2094 | 2111 |
2095 SkStrokeRec::Style style = stroke.getStyle(); | 2112 SkStrokeRec::Style style = stroke.getStyle(); |
2096 | 2113 |
2097 // do (potentially) anisotropic mapping of stroke | 2114 // do (potentially) anisotropic mapping of stroke |
2098 SkVector scaledStroke; | 2115 SkVector scaledStroke; |
2099 SkScalar strokeWidth = stroke.getWidth(); | 2116 SkScalar strokeWidth = stroke.getWidth(); |
2100 | 2117 |
2101 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 2118 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
2102 SkStrokeRec::kHairline_Style == style; | 2119 SkStrokeRec::kHairline_Style == style; |
2103 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 2120 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
2104 | 2121 |
2105 if (hasStroke) { | 2122 if (hasStroke) { |
2106 if (SkStrokeRec::kHairline_Style == style) { | 2123 if (SkStrokeRec::kHairline_Style == style) { |
2107 scaledStroke.set(1, 1); | 2124 scaledStroke.set(1, 1); |
2108 } else { | 2125 } else { |
2109 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc
aleX] + | 2126 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc
aleX] + |
2110 viewMatrix[SkMatrix::kMSk
ewY])); | 2127 viewMatrix[SkMatrix::kMSk
ewY])); |
2111 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk
ewX] + | 2128 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk
ewX] + |
2112 viewMatrix[SkMatrix::kMSc
aleY])); | 2129 viewMatrix[SkMatrix::kMSc
aleY])); |
2113 } | 2130 } |
2114 | 2131 |
2115 // if half of strokewidth is greater than radius, we don't handle that r
ight now | 2132 // if half of strokewidth is greater than radius, we don't handle that r
ight now |
2116 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok
e.fY > yRadius) { | 2133 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok
e.fY > yRadius) { |
2117 return false; | 2134 return NULL; |
2118 } | 2135 } |
2119 } | 2136 } |
2120 | 2137 |
2121 // The way the effect interpolates the offset-to-ellipse/circle-center attri
bute only works on | 2138 // The way the effect interpolates the offset-to-ellipse/circle-center attri
bute only works on |
2122 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r
ect of the nine- | 2139 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r
ect of the nine- |
2123 // patch will have fractional coverage. This only matters when the interior
is actually filled. | 2140 // patch will have fractional coverage. This only matters when the interior
is actually filled. |
2124 // We could consider falling back to rect rendering here, since a tiny radiu
s is | 2141 // We could consider falling back to rect rendering here, since a tiny radiu
s is |
2125 // indistinguishable from a square corner. | 2142 // indistinguishable from a square corner. |
2126 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { | 2143 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { |
2127 return false; | 2144 return NULL; |
2128 } | 2145 } |
2129 | 2146 |
2130 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly); | 2147 GrIndexBuffer* indexBuffer = create_rrect_indexbuffer(strokeRRectIndexBuffer
, |
| 2148 rrectIndexBuffer, |
| 2149 isStrokeOnly, |
| 2150 gpu); |
2131 if (NULL == indexBuffer) { | 2151 if (NULL == indexBuffer) { |
2132 SkDebugf("Failed to create index buffer!\n"); | 2152 SkDebugf("Failed to create index buffer!\n"); |
2133 return false; | 2153 return NULL; |
2134 } | 2154 } |
2135 | 2155 |
2136 // if the corners are circles, use the circle renderer | 2156 // if the corners are circles, use the circle renderer |
2137 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { | 2157 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { |
2138 SkScalar innerRadius = 0.0f; | 2158 SkScalar innerRadius = 0.0f; |
2139 SkScalar outerRadius = xRadius; | 2159 SkScalar outerRadius = xRadius; |
2140 SkScalar halfWidth = 0; | 2160 SkScalar halfWidth = 0; |
2141 if (hasStroke) { | 2161 if (hasStroke) { |
2142 if (SkScalarNearlyZero(scaledStroke.fX)) { | 2162 if (SkScalarNearlyZero(scaledStroke.fX)) { |
2143 halfWidth = SK_ScalarHalf; | 2163 halfWidth = SK_ScalarHalf; |
2144 } else { | 2164 } else { |
2145 halfWidth = SkScalarHalf(scaledStroke.fX); | 2165 halfWidth = SkScalarHalf(scaledStroke.fX); |
2146 } | 2166 } |
2147 | 2167 |
2148 if (isStrokeOnly) { | 2168 if (isStrokeOnly) { |
2149 innerRadius = xRadius - halfWidth; | 2169 innerRadius = xRadius - halfWidth; |
2150 } | 2170 } |
2151 outerRadius += halfWidth; | 2171 outerRadius += halfWidth; |
2152 bounds.outset(halfWidth, halfWidth); | 2172 bounds->outset(halfWidth, halfWidth); |
2153 } | 2173 } |
2154 | 2174 |
2155 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); | 2175 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); |
2156 | 2176 |
2157 // The radii are outset for two reasons. First, it allows the shader to
simply perform | 2177 // The radii are outset for two reasons. First, it allows the shader to
simply perform |
2158 // simpler computation because the computed alpha is zero, rather than 5
0%, at the radius. | 2178 // simpler computation because the computed alpha is zero, rather than 5
0%, at the radius. |
2159 // Second, the outer radius is used to compute the verts of the bounding
box that is | 2179 // Second, the outer radius is used to compute the verts of the bounding
box that is |
2160 // rendered and the outset ensures the box will cover all partially cove
red by the rrect | 2180 // rendered and the outset ensures the box will cover all partially cove
red by the rrect |
2161 // corners. | 2181 // corners. |
2162 outerRadius += SK_ScalarHalf; | 2182 outerRadius += SK_ScalarHalf; |
2163 innerRadius -= SK_ScalarHalf; | 2183 innerRadius -= SK_ScalarHalf; |
2164 | 2184 |
2165 // Expand the rect so all the pixels will be captured. | 2185 // Expand the rect so all the pixels will be captured. |
2166 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 2186 bounds->outset(SK_ScalarHalf, SK_ScalarHalf); |
2167 | 2187 |
2168 RRectCircleRendererBatch::Geometry geometry; | 2188 RRectCircleRendererBatch::Geometry geometry; |
2169 geometry.fViewMatrix = viewMatrix; | 2189 geometry.fViewMatrix = viewMatrix; |
2170 geometry.fColor = color; | 2190 geometry.fColor = color; |
2171 geometry.fInnerRadius = innerRadius; | 2191 geometry.fInnerRadius = innerRadius; |
2172 geometry.fOuterRadius = outerRadius; | 2192 geometry.fOuterRadius = outerRadius; |
2173 geometry.fStroke = isStrokeOnly; | 2193 geometry.fStroke = isStrokeOnly; |
2174 geometry.fDevBounds = bounds; | 2194 geometry.fDevBounds = *bounds; |
2175 | 2195 |
2176 SkAutoTUnref<GrBatch> batch(RRectCircleRendererBatch::Create(geometry, i
ndexBuffer)); | 2196 return RRectCircleRendererBatch::Create(geometry, indexBuffer); |
2177 target->drawBatch(pipelineBuilder, batch, &bounds); | |
2178 | 2197 |
2179 // otherwise we use the ellipse renderer | 2198 // otherwise we use the ellipse renderer |
2180 } else { | 2199 } else { |
2181 SkScalar innerXRadius = 0.0f; | 2200 SkScalar innerXRadius = 0.0f; |
2182 SkScalar innerYRadius = 0.0f; | 2201 SkScalar innerYRadius = 0.0f; |
2183 if (hasStroke) { | 2202 if (hasStroke) { |
2184 if (SkScalarNearlyZero(scaledStroke.length())) { | 2203 if (SkScalarNearlyZero(scaledStroke.length())) { |
2185 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); | 2204 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); |
2186 } else { | 2205 } else { |
2187 scaledStroke.scale(SK_ScalarHalf); | 2206 scaledStroke.scale(SK_ScalarHalf); |
2188 } | 2207 } |
2189 | 2208 |
2190 // we only handle thick strokes for near-circular ellipses | 2209 // we only handle thick strokes for near-circular ellipses |
2191 if (scaledStroke.length() > SK_ScalarHalf && | 2210 if (scaledStroke.length() > SK_ScalarHalf && |
2192 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRad
ius)) { | 2211 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRad
ius)) { |
2193 return false; | 2212 return NULL; |
2194 } | 2213 } |
2195 | 2214 |
2196 // we don't handle it if curvature of the stroke is less than curvat
ure of the ellipse | 2215 // we don't handle it if curvature of the stroke is less than curvat
ure of the ellipse |
2197 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStrok
e.fY)*xRadius || | 2216 if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStrok
e.fY)*xRadius || |
2198 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStrok
e.fX)*yRadius) { | 2217 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStrok
e.fX)*yRadius) { |
2199 return false; | 2218 return NULL; |
2200 } | 2219 } |
2201 | 2220 |
2202 // this is legit only if scale & translation (which should be the ca
se at the moment) | 2221 // this is legit only if scale & translation (which should be the ca
se at the moment) |
2203 if (isStrokeOnly) { | 2222 if (isStrokeOnly) { |
2204 innerXRadius = xRadius - scaledStroke.fX; | 2223 innerXRadius = xRadius - scaledStroke.fX; |
2205 innerYRadius = yRadius - scaledStroke.fY; | 2224 innerYRadius = yRadius - scaledStroke.fY; |
2206 } | 2225 } |
2207 | 2226 |
2208 xRadius += scaledStroke.fX; | 2227 xRadius += scaledStroke.fX; |
2209 yRadius += scaledStroke.fY; | 2228 yRadius += scaledStroke.fY; |
2210 bounds.outset(scaledStroke.fX, scaledStroke.fY); | 2229 bounds->outset(scaledStroke.fX, scaledStroke.fY); |
2211 } | 2230 } |
2212 | 2231 |
2213 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); | 2232 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); |
2214 | 2233 |
2215 // Expand the rect so all the pixels will be captured. | 2234 // Expand the rect so all the pixels will be captured. |
2216 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 2235 bounds->outset(SK_ScalarHalf, SK_ScalarHalf); |
2217 | 2236 |
2218 RRectEllipseRendererBatch::Geometry geometry; | 2237 RRectEllipseRendererBatch::Geometry geometry; |
2219 geometry.fViewMatrix = viewMatrix; | 2238 geometry.fViewMatrix = viewMatrix; |
2220 geometry.fColor = color; | 2239 geometry.fColor = color; |
2221 geometry.fXRadius = xRadius; | 2240 geometry.fXRadius = xRadius; |
2222 geometry.fYRadius = yRadius; | 2241 geometry.fYRadius = yRadius; |
2223 geometry.fInnerXRadius = innerXRadius; | 2242 geometry.fInnerXRadius = innerXRadius; |
2224 geometry.fInnerYRadius = innerYRadius; | 2243 geometry.fInnerYRadius = innerYRadius; |
2225 geometry.fStroke = isStrokeOnly; | 2244 geometry.fStroke = isStrokeOnly; |
2226 geometry.fDevBounds = bounds; | 2245 geometry.fDevBounds = *bounds; |
2227 | 2246 |
2228 SkAutoTUnref<GrBatch> batch(RRectEllipseRendererBatch::Create(geometry,
indexBuffer)); | 2247 return RRectEllipseRendererBatch::Create(geometry, indexBuffer); |
2229 target->drawBatch(pipelineBuilder, batch, &bounds); | |
2230 } | 2248 } |
| 2249 } |
| 2250 |
| 2251 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, |
| 2252 GrPipelineBuilder* pipelineBuilder, |
| 2253 GrColor color, |
| 2254 const SkMatrix& viewMatrix, |
| 2255 bool useAA, |
| 2256 const SkRRect& rrect, |
| 2257 const SkStrokeRec& stroke) { |
| 2258 if (rrect.isOval()) { |
| 2259 return this->drawOval(target, pipelineBuilder, color, viewMatrix, useAA,
rrect.getBounds(), |
| 2260 stroke); |
| 2261 } |
| 2262 |
| 2263 bool useCoverageAA = useAA && !pipelineBuilder->getRenderTarget()->isMultisa
mpled(); |
| 2264 |
| 2265 // only anti-aliased rrects for now |
| 2266 if (!useCoverageAA) { |
| 2267 return false; |
| 2268 } |
| 2269 |
| 2270 if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { |
| 2271 return false; |
| 2272 } |
| 2273 |
| 2274 SkRect bounds; |
| 2275 SkAutoTUnref<GrBatch> batch(create_rrect_batch(color, viewMatrix, rrect, str
oke, &bounds, |
| 2276 &fStrokeRRectIndexBuffer, &fR
RectIndexBuffer, |
| 2277 fGpu)); |
| 2278 if (!batch) { |
| 2279 return false; |
| 2280 } |
| 2281 |
| 2282 target->drawBatch(pipelineBuilder, batch, &bounds); |
2231 return true; | 2283 return true; |
2232 } | 2284 } |
| 2285 |
| 2286 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 2287 |
| 2288 #ifdef GR_TEST_UTILS |
| 2289 |
| 2290 static SkStrokeRec random_strokerec(SkRandom* random) { |
| 2291 SkStrokeRec::InitStyle style = |
| 2292 SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_Init
Style + 1)); |
| 2293 SkStrokeRec rec(style); |
| 2294 bool strokeAndFill = random->nextBool(); |
| 2295 SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f; |
| 2296 rec.setStrokeStyle(strokeWidth, strokeAndFill); |
| 2297 return rec; |
| 2298 } |
| 2299 |
| 2300 BATCH_TEST_DEFINE(CircleBatch) { |
| 2301 SkMatrix viewMatrix = GrTest::TestMatrix(random); |
| 2302 GrColor color = GrRandomColor(random); |
| 2303 bool useCoverageAA = random->nextBool(); |
| 2304 SkRect circle = GrTest::TestRect(random); |
| 2305 SkRect bounds; // unused |
| 2306 return create_circle_batch(color, viewMatrix, useCoverageAA, circle, random_
strokerec(random), |
| 2307 &bounds); |
| 2308 } |
| 2309 |
| 2310 BATCH_TEST_DEFINE(EllipseBatch) { |
| 2311 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); |
| 2312 GrColor color = GrRandomColor(random); |
| 2313 bool useCoverageAA = random->nextBool(); |
| 2314 SkRect ellipse = GrTest::TestRect(random); |
| 2315 SkRect bounds; // unused |
| 2316 return create_ellipse_batch(color, viewMatrix, useCoverageAA, ellipse, |
| 2317 random_strokerec(random), &bounds); |
| 2318 } |
| 2319 |
| 2320 BATCH_TEST_DEFINE(DIEllipseBatch) { |
| 2321 SkMatrix viewMatrix = GrTest::TestMatrix(random); |
| 2322 GrColor color = GrRandomColor(random); |
| 2323 bool useCoverageAA = random->nextBool(); |
| 2324 SkRect ellipse = GrTest::TestRect(random); |
| 2325 SkRect bounds; // unused |
| 2326 return create_diellipse_batch(color, viewMatrix, useCoverageAA, ellipse, |
| 2327 random_strokerec(random), &bounds); |
| 2328 } |
| 2329 |
| 2330 BATCH_TEST_DEFINE(RRectBatch) { |
| 2331 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); |
| 2332 GrColor color = GrRandomColor(random); |
| 2333 const SkRRect& rrect = GrTest::TestRRectSimple(random); |
| 2334 |
| 2335 static GrIndexBuffer* gStrokeRRectIndexBuffer; |
| 2336 static GrIndexBuffer* gRRectIndexBuffer; |
| 2337 SkRect bounds; |
| 2338 return create_rrect_batch(color, viewMatrix, rrect, random_strokerec(random)
, &bounds, |
| 2339 &gStrokeRRectIndexBuffer, &gRRectIndexBuffer, cont
ext->getGpu()); |
| 2340 } |
| 2341 |
| 2342 #endif |
OLD | NEW |