| 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 |