OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "GrContext.h" | 10 #include "GrContext.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 SK_DEFINE_INST_COUNT(GrDrawState) | 36 SK_DEFINE_INST_COUNT(GrDrawState) |
37 | 37 |
38 // It can be useful to set this to false to test whether a bug is caused by usin
g the | 38 // It can be useful to set this to false to test whether a bug is caused by usin
g the |
39 // InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffe
r, or to make | 39 // InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffe
r, or to make |
40 // debugging simpler. | 40 // debugging simpler. |
41 SK_CONF_DECLARE(bool, c_Defer, "gpu.deferContext", true, | 41 SK_CONF_DECLARE(bool, c_Defer, "gpu.deferContext", true, |
42 "Defers rendering in GrContext via GrInOrderDrawBuffer."); | 42 "Defers rendering in GrContext via GrInOrderDrawBuffer."); |
43 | 43 |
44 #define BUFFERED_DRAW (c_Defer ? kYes_BufferedDraw : kNo_BufferedDraw) | 44 #define BUFFERED_DRAW (c_Defer ? kYes_BufferedDraw : kNo_BufferedDraw) |
45 | 45 |
46 // When we're using coverage AA but the blend is incompatible (given gpu | |
47 // limitations) should we disable AA or draw wrong? | |
48 #define DISABLE_COVERAGE_AA_FOR_BLEND 1 | |
49 | |
50 #ifdef SK_DEBUG | 46 #ifdef SK_DEBUG |
51 // change this to a 1 to see notifications when partial coverage fails | 47 // change this to a 1 to see notifications when partial coverage fails |
52 #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0 | 48 #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0 |
53 #else | 49 #else |
54 #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0 | 50 #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0 |
55 #endif | 51 #endif |
56 | 52 |
57 static const size_t MAX_RESOURCE_CACHE_COUNT = GR_DEFAULT_RESOURCE_CACHE_COUNT_L
IMIT; | 53 static const size_t MAX_RESOURCE_CACHE_COUNT = GR_DEFAULT_RESOURCE_CACHE_COUNT_L
IMIT; |
58 static const size_t MAX_RESOURCE_CACHE_BYTES = GR_DEFAULT_RESOURCE_CACHE_MB_LIMI
T * 1024 * 1024; | 54 static const size_t MAX_RESOURCE_CACHE_BYTES = GR_DEFAULT_RESOURCE_CACHE_MB_LIMI
T * 1024 * 1024; |
59 | 55 |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 } | 684 } |
689 | 685 |
690 #ifdef SK_DEVELOPER | 686 #ifdef SK_DEVELOPER |
691 void GrContext::dumpFontCache() const { | 687 void GrContext::dumpFontCache() const { |
692 fFontCache->dump(); | 688 fFontCache->dump(); |
693 } | 689 } |
694 #endif | 690 #endif |
695 | 691 |
696 //////////////////////////////////////////////////////////////////////////////// | 692 //////////////////////////////////////////////////////////////////////////////// |
697 | 693 |
698 namespace { | |
699 inline bool disable_coverage_aa_for_blend(GrDrawTarget* target) { | |
700 return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage(); | |
701 } | |
702 } | |
703 | |
704 //////////////////////////////////////////////////////////////////////////////// | |
705 | |
706 /* create a triangle strip that strokes the specified triangle. There are 8 | 694 /* create a triangle strip that strokes the specified triangle. There are 8 |
707 unique vertices, but we repreat the last 2 to close up. Alternatively we | 695 unique vertices, but we repreat the last 2 to close up. Alternatively we |
708 could use an indices array, and then only send 8 verts, but not sure that | 696 could use an indices array, and then only send 8 verts, but not sure that |
709 would be faster. | 697 would be faster. |
710 */ | 698 */ |
711 static void setStrokeRectStrip(GrPoint verts[10], SkRect rect, | 699 static void setStrokeRectStrip(GrPoint verts[10], SkRect rect, |
712 SkScalar width) { | 700 SkScalar width) { |
713 const SkScalar rad = SkScalarHalf(width); | 701 const SkScalar rad = SkScalarHalf(width); |
714 rect.sort(); | 702 rect.sort(); |
715 | 703 |
(...skipping 23 matching lines...) Expand all Loading... |
739 // we use a simple coverage ramp to do aa on axis-aligned rects | 727 // we use a simple coverage ramp to do aa on axis-aligned rects |
740 // we check if the rect will be axis-aligned, and the rect won't land on | 728 // we check if the rect will be axis-aligned, and the rect won't land on |
741 // integer coords. | 729 // integer coords. |
742 | 730 |
743 // we are keeping around the "tweak the alpha" trick because | 731 // we are keeping around the "tweak the alpha" trick because |
744 // it is our only hope for the fixed-pipe implementation. | 732 // it is our only hope for the fixed-pipe implementation. |
745 // In a shader implementation we can give a separate coverage input | 733 // In a shader implementation we can give a separate coverage input |
746 // TODO: remove this ugliness when we drop the fixed-pipe impl | 734 // TODO: remove this ugliness when we drop the fixed-pipe impl |
747 *useVertexCoverage = false; | 735 *useVertexCoverage = false; |
748 if (!target->getDrawState().canTweakAlphaForCoverage()) { | 736 if (!target->getDrawState().canTweakAlphaForCoverage()) { |
749 if (disable_coverage_aa_for_blend(target)) { | 737 if (target->shouldDisableCoverageAAForBlend()) { |
750 #ifdef SK_DEBUG | 738 #ifdef SK_DEBUG |
751 //GrPrintf("Turning off AA to correctly apply blend.\n"); | 739 //GrPrintf("Turning off AA to correctly apply blend.\n"); |
752 #endif | 740 #endif |
753 return false; | 741 return false; |
754 } else { | 742 } else { |
755 *useVertexCoverage = true; | 743 *useVertexCoverage = true; |
756 } | 744 } |
757 } | 745 } |
758 const GrDrawState& drawState = target->getDrawState(); | 746 const GrDrawState& drawState = target->getDrawState(); |
759 if (drawState.getRenderTarget()->isMultisampled()) { | 747 if (drawState.getRenderTarget()->isMultisampled()) { |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 const SkRRect& rect, | 1015 const SkRRect& rect, |
1028 const SkStrokeRec& stroke) { | 1016 const SkStrokeRec& stroke) { |
1029 if (rect.isEmpty()) { | 1017 if (rect.isEmpty()) { |
1030 return; | 1018 return; |
1031 } | 1019 } |
1032 | 1020 |
1033 AutoRestoreEffects are; | 1021 AutoRestoreEffects are; |
1034 AutoCheckFlush acf(this); | 1022 AutoCheckFlush acf(this); |
1035 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf
); | 1023 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf
); |
1036 | 1024 |
1037 bool useAA = paint.isAntiAlias() && | 1025 if (!fOvalRenderer->drawSimpleRRect(target, this, paint.isAntiAlias(), rect,
stroke)) { |
1038 !target->getDrawState().getRenderTarget()->isMultisampled() && | |
1039 !disable_coverage_aa_for_blend(target); | |
1040 | |
1041 if (!fOvalRenderer->drawSimpleRRect(target, this, useAA, rect, stroke)) { | |
1042 SkPath path; | 1026 SkPath path; |
1043 path.addRRect(rect); | 1027 path.addRRect(rect); |
1044 this->internalDrawPath(target, useAA, path, stroke); | 1028 this->internalDrawPath(target, paint.isAntiAlias(), path, stroke); |
1045 } | 1029 } |
1046 } | 1030 } |
1047 | 1031 |
1048 /////////////////////////////////////////////////////////////////////////////// | 1032 /////////////////////////////////////////////////////////////////////////////// |
1049 | 1033 |
1050 void GrContext::drawOval(const GrPaint& paint, | 1034 void GrContext::drawOval(const GrPaint& paint, |
1051 const SkRect& oval, | 1035 const SkRect& oval, |
1052 const SkStrokeRec& stroke) { | 1036 const SkStrokeRec& stroke) { |
1053 if (oval.isEmpty()) { | 1037 if (oval.isEmpty()) { |
1054 return; | 1038 return; |
1055 } | 1039 } |
1056 | 1040 |
1057 AutoRestoreEffects are; | 1041 AutoRestoreEffects are; |
1058 AutoCheckFlush acf(this); | 1042 AutoCheckFlush acf(this); |
1059 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf
); | 1043 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf
); |
1060 | 1044 |
1061 bool useAA = paint.isAntiAlias() && | 1045 if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, stroke
)) { |
1062 !target->getDrawState().getRenderTarget()->isMultisampled() && | |
1063 !disable_coverage_aa_for_blend(target); | |
1064 | |
1065 if (!fOvalRenderer->drawOval(target, this, useAA, oval, stroke)) { | |
1066 SkPath path; | 1046 SkPath path; |
1067 path.addOval(oval); | 1047 path.addOval(oval); |
1068 this->internalDrawPath(target, useAA, path, stroke); | 1048 this->internalDrawPath(target, paint.isAntiAlias(), path, stroke); |
1069 } | 1049 } |
1070 } | 1050 } |
1071 | 1051 |
1072 // Can 'path' be drawn as a pair of filled nested rectangles? | 1052 // Can 'path' be drawn as a pair of filled nested rectangles? |
1073 static bool is_nested_rects(GrDrawTarget* target, | 1053 static bool is_nested_rects(GrDrawTarget* target, |
1074 const SkPath& path, | 1054 const SkPath& path, |
1075 const SkStrokeRec& stroke, | 1055 const SkStrokeRec& stroke, |
1076 SkRect rects[2], | 1056 SkRect rects[2], |
1077 bool* useVertexCoverage) { | 1057 bool* useVertexCoverage) { |
1078 SkASSERT(stroke.isFillStyle()); | 1058 SkASSERT(stroke.isFillStyle()); |
1079 | 1059 |
1080 if (path.isInverseFillType()) { | 1060 if (path.isInverseFillType()) { |
1081 return false; | 1061 return false; |
1082 } | 1062 } |
1083 | 1063 |
1084 const GrDrawState& drawState = target->getDrawState(); | 1064 const GrDrawState& drawState = target->getDrawState(); |
1085 | 1065 |
1086 // TODO: this restriction could be lifted if we were willing to apply | 1066 // TODO: this restriction could be lifted if we were willing to apply |
1087 // the matrix to all the points individually rather than just to the rect | 1067 // the matrix to all the points individually rather than just to the rect |
1088 if (!drawState.getViewMatrix().preservesAxisAlignment()) { | 1068 if (!drawState.getViewMatrix().preservesAxisAlignment()) { |
1089 return false; | 1069 return false; |
1090 } | 1070 } |
1091 | 1071 |
1092 *useVertexCoverage = false; | 1072 *useVertexCoverage = false; |
1093 if (!target->getDrawState().canTweakAlphaForCoverage()) { | 1073 if (!target->getDrawState().canTweakAlphaForCoverage()) { |
1094 if (disable_coverage_aa_for_blend(target)) { | 1074 if (target->shouldDisableCoverageAAForBlend()) { |
1095 return false; | 1075 return false; |
1096 } else { | 1076 } else { |
1097 *useVertexCoverage = true; | 1077 *useVertexCoverage = true; |
1098 } | 1078 } |
1099 } | 1079 } |
1100 | 1080 |
1101 SkPath::Direction dirs[2]; | 1081 SkPath::Direction dirs[2]; |
1102 if (!path.isNestedRects(rects, dirs)) { | 1082 if (!path.isNestedRects(rects, dirs)) { |
1103 return false; | 1083 return false; |
1104 } | 1084 } |
(...skipping 29 matching lines...) Expand all Loading... |
1134 } | 1114 } |
1135 | 1115 |
1136 // Note that internalDrawPath may sw-rasterize the path into a scratch textu
re. | 1116 // Note that internalDrawPath may sw-rasterize the path into a scratch textu
re. |
1137 // Scratch textures can be recycled after they are returned to the texture | 1117 // Scratch textures can be recycled after they are returned to the texture |
1138 // cache. This presents a potential hazard for buffered drawing. However, | 1118 // cache. This presents a potential hazard for buffered drawing. However, |
1139 // the writePixels that uploads to the scratch will perform a flush so we're | 1119 // the writePixels that uploads to the scratch will perform a flush so we're |
1140 // OK. | 1120 // OK. |
1141 AutoRestoreEffects are; | 1121 AutoRestoreEffects are; |
1142 AutoCheckFlush acf(this); | 1122 AutoCheckFlush acf(this); |
1143 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf
); | 1123 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf
); |
| 1124 GrDrawState* drawState = target->drawState(); |
1144 | 1125 |
1145 bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget(
)->isMultisampled(); | 1126 bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->i
sMultisampled(); |
1146 if (useAA && stroke.getWidth() < 0 && !path.isConvex()) { | 1127 |
| 1128 if (useCoverageAA && stroke.getWidth() < 0 && !path.isConvex()) { |
1147 // Concave AA paths are expensive - try to avoid them for special cases | 1129 // Concave AA paths are expensive - try to avoid them for special cases |
1148 bool useVertexCoverage; | 1130 bool useVertexCoverage; |
1149 SkRect rects[2]; | 1131 SkRect rects[2]; |
1150 | 1132 |
1151 if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) { | 1133 if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) { |
1152 SkMatrix origViewMatrix = target->getDrawState().getViewMatrix(); | 1134 SkMatrix origViewMatrix = drawState->getViewMatrix(); |
1153 GrDrawState::AutoViewMatrixRestore avmr; | 1135 GrDrawState::AutoViewMatrixRestore avmr; |
1154 if (!avmr.setIdentity(target->drawState())) { | 1136 if (!avmr.setIdentity(target->drawState())) { |
1155 return; | 1137 return; |
1156 } | 1138 } |
1157 | 1139 |
1158 fAARectRenderer->fillAANestedRects(this->getGpu(), target, | 1140 fAARectRenderer->fillAANestedRects(this->getGpu(), target, |
1159 rects, | 1141 rects, |
1160 origViewMatrix, | 1142 origViewMatrix, |
1161 useVertexCoverage); | 1143 useVertexCoverage); |
1162 return; | 1144 return; |
1163 } | 1145 } |
1164 } | 1146 } |
1165 | 1147 |
1166 SkRect ovalRect; | 1148 SkRect ovalRect; |
1167 bool isOval = path.isOval(&ovalRect); | 1149 bool isOval = path.isOval(&ovalRect); |
1168 | 1150 |
1169 if (!isOval || path.isInverseFillType() | 1151 if (!isOval || path.isInverseFillType() |
1170 || !fOvalRenderer->drawOval(target, this, useAA, ovalRect, stroke)) { | 1152 || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect,
stroke)) { |
1171 this->internalDrawPath(target, useAA, path, stroke); | 1153 this->internalDrawPath(target, paint.isAntiAlias(), path, stroke); |
1172 } | 1154 } |
1173 } | 1155 } |
1174 | 1156 |
1175 void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath&
path, | 1157 void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath&
path, |
1176 const SkStrokeRec& stroke) { | 1158 const SkStrokeRec& stroke) { |
1177 SkASSERT(!path.isEmpty()); | 1159 SkASSERT(!path.isEmpty()); |
1178 | 1160 |
1179 // An Assumption here is that path renderer would use some form of tweaking | 1161 // An Assumption here is that path renderer would use some form of tweaking |
1180 // the src color (either the input alpha or in the frag shader) to implement | 1162 // the src color (either the input alpha or in the frag shader) to implement |
1181 // aa. If we have some future driver-mojo path AA that can do the right | 1163 // aa. If we have some future driver-mojo path AA that can do the right |
1182 // thing WRT to the blend then we'll need some query on the PR. | 1164 // thing WRT to the blend then we'll need some query on the PR. |
1183 if (disable_coverage_aa_for_blend(target)) { | 1165 bool useCoverageAA = useAA && |
1184 #ifdef SK_DEBUG | 1166 !target->getDrawState().getRenderTarget()->isMultisampled() && |
1185 //GrPrintf("Turning off AA to correctly apply blend.\n"); | 1167 !target->shouldDisableCoverageAAForBlend(); |
1186 #endif | |
1187 useAA = false; | |
1188 } | |
1189 | 1168 |
1190 GrPathRendererChain::DrawType type = useAA ? GrPathRendererChain::kColorAnti
Alias_DrawType : | 1169 |
1191 GrPathRendererChain::kColor_Dra
wType; | 1170 GrPathRendererChain::DrawType type = |
| 1171 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType : |
| 1172 GrPathRendererChain::kColor_DrawType; |
1192 | 1173 |
1193 const SkPath* pathPtr = &path; | 1174 const SkPath* pathPtr = &path; |
1194 SkPath tmpPath; | 1175 SkPath tmpPath; |
1195 SkStrokeRec strokeRec(stroke); | 1176 SkStrokeRec strokeRec(stroke); |
1196 | 1177 |
1197 // Try a 1st time without stroking the path and without allowing the SW rend
erer | 1178 // Try a 1st time without stroking the path and without allowing the SW rend
erer |
1198 GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, fals
e, type); | 1179 GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, fals
e, type); |
1199 | 1180 |
1200 if (NULL == pr) { | 1181 if (NULL == pr) { |
1201 if (!strokeRec.isHairlineStyle()) { | 1182 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(strokeRec, this->getMa
trix(), NULL)) { |
1202 // It didn't work the 1st time, so try again with the stroked path | 1183 // It didn't work the 1st time, so try again with the stroked path |
1203 if (strokeRec.applyToPath(&tmpPath, *pathPtr)) { | 1184 if (strokeRec.applyToPath(&tmpPath, *pathPtr)) { |
1204 pathPtr = &tmpPath; | 1185 pathPtr = &tmpPath; |
1205 strokeRec.setFillStyle(); | 1186 strokeRec.setFillStyle(); |
| 1187 if (pathPtr->isEmpty()) { |
| 1188 return; |
| 1189 } |
1206 } | 1190 } |
1207 } | 1191 } |
1208 if (pathPtr->isEmpty()) { | |
1209 return; | |
1210 } | |
1211 | 1192 |
1212 // This time, allow SW renderer | 1193 // This time, allow SW renderer |
1213 pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type); | 1194 pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type); |
1214 } | 1195 } |
1215 | 1196 |
1216 if (NULL == pr) { | 1197 if (NULL == pr) { |
1217 #ifdef SK_DEBUG | 1198 #ifdef SK_DEBUG |
1218 GrPrintf("Unable to find path renderer compatible with path.\n"); | 1199 GrPrintf("Unable to find path renderer compatible with path.\n"); |
1219 #endif | 1200 #endif |
1220 return; | 1201 return; |
1221 } | 1202 } |
1222 | 1203 |
1223 pr->drawPath(*pathPtr, strokeRec, target, useAA); | 1204 pr->drawPath(*pathPtr, strokeRec, target, useCoverageAA); |
1224 } | 1205 } |
1225 | 1206 |
1226 //////////////////////////////////////////////////////////////////////////////// | 1207 //////////////////////////////////////////////////////////////////////////////// |
1227 | 1208 |
1228 void GrContext::flush(int flagsBitfield) { | 1209 void GrContext::flush(int flagsBitfield) { |
1229 if (NULL == fDrawBuffer) { | 1210 if (NULL == fDrawBuffer) { |
1230 return; | 1211 return; |
1231 } | 1212 } |
1232 | 1213 |
1233 if (kDiscard_FlushBit & flagsBitfield) { | 1214 if (kDiscard_FlushBit & flagsBitfield) { |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1829 } | 1810 } |
1830 return path; | 1811 return path; |
1831 } | 1812 } |
1832 | 1813 |
1833 /////////////////////////////////////////////////////////////////////////////// | 1814 /////////////////////////////////////////////////////////////////////////////// |
1834 #if GR_CACHE_STATS | 1815 #if GR_CACHE_STATS |
1835 void GrContext::printCacheStats() const { | 1816 void GrContext::printCacheStats() const { |
1836 fTextureCache->printStats(); | 1817 fTextureCache->printStats(); |
1837 } | 1818 } |
1838 #endif | 1819 #endif |
OLD | NEW |