Chromium Code Reviews| 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" |
| 11 | 11 |
| 12 #include "effects/GrSingleTextureEffect.h" | 12 #include "effects/GrSingleTextureEffect.h" |
| 13 #include "effects/GrConfigConversionEffect.h" | 13 #include "effects/GrConfigConversionEffect.h" |
| 14 | 14 |
| 15 #include "GrAARectRenderer.h" | 15 #include "GrAARectRenderer.h" |
| 16 #include "GrBufferAllocPool.h" | 16 #include "GrBufferAllocPool.h" |
| 17 #include "GrGpu.h" | 17 #include "GrGpu.h" |
| 18 #include "GrDrawTargetCaps.h" | 18 #include "GrDrawTargetCaps.h" |
| 19 #include "GrIndexBuffer.h" | 19 #include "GrIndexBuffer.h" |
| 20 #include "GrInOrderDrawBuffer.h" | 20 #include "GrInOrderDrawBuffer.h" |
| 21 #include "GrOvalRenderer.h" | 21 #include "GrOvalRenderer.h" |
| 22 #include "GrPathRenderer.h" | 22 #include "GrPathRenderer.h" |
| 23 #include "GrPathUtils.h" | 23 #include "GrPathUtils.h" |
| 24 #include "GrResourceCache.h" | 24 #include "GrResourceCache.h" |
| 25 #include "GrSoftwarePathRenderer.h" | 25 #include "GrSoftwarePathRenderer.h" |
| 26 #include "GrStencilBuffer.h" | 26 #include "GrStencilBuffer.h" |
| 27 #include "GrTextStrike.h" | 27 #include "GrTextStrike.h" |
| 28 #include "SkDrawProcs.h" | |
| 28 #include "SkRTConf.h" | 29 #include "SkRTConf.h" |
| 29 #include "SkRRect.h" | 30 #include "SkRRect.h" |
| 30 #include "SkStrokeRec.h" | 31 #include "SkStrokeRec.h" |
| 31 #include "SkTLazy.h" | 32 #include "SkTLazy.h" |
| 32 #include "SkTLS.h" | 33 #include "SkTLS.h" |
| 33 #include "SkTrace.h" | 34 #include "SkTrace.h" |
| 34 | 35 |
| 35 SK_DEFINE_INST_COUNT(GrContext) | 36 SK_DEFINE_INST_COUNT(GrContext) |
| 36 SK_DEFINE_INST_COUNT(GrDrawState) | 37 SK_DEFINE_INST_COUNT(GrDrawState) |
| 37 | 38 |
| (...skipping 992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1030 AutoCheckFlush acf(this); | 1031 AutoCheckFlush acf(this); |
| 1031 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf ); | 1032 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf ); |
| 1032 | 1033 |
| 1033 bool useAA = paint.isAntiAlias() && | 1034 bool useAA = paint.isAntiAlias() && |
| 1034 !target->getDrawState().getRenderTarget()->isMultisampled() && | 1035 !target->getDrawState().getRenderTarget()->isMultisampled() && |
| 1035 !disable_coverage_aa_for_blend(target); | 1036 !disable_coverage_aa_for_blend(target); |
| 1036 | 1037 |
| 1037 if (!fOvalRenderer->drawSimpleRRect(target, this, useAA, rect, stroke)) { | 1038 if (!fOvalRenderer->drawSimpleRRect(target, this, useAA, rect, stroke)) { |
| 1038 SkPath path; | 1039 SkPath path; |
| 1039 path.addRRect(rect); | 1040 path.addRRect(rect); |
| 1040 this->internalDrawPath(target, useAA, path, stroke); | 1041 this->internalDrawPath(target, paint, useAA, path, stroke); |
| 1041 } | 1042 } |
| 1042 } | 1043 } |
| 1043 | 1044 |
| 1044 /////////////////////////////////////////////////////////////////////////////// | 1045 /////////////////////////////////////////////////////////////////////////////// |
| 1045 | 1046 |
| 1046 void GrContext::drawOval(const GrPaint& paint, | 1047 void GrContext::drawOval(const GrPaint& paint, |
| 1047 const SkRect& oval, | 1048 const SkRect& oval, |
| 1048 const SkStrokeRec& stroke) { | 1049 const SkStrokeRec& stroke) { |
| 1049 if (oval.isEmpty()) { | 1050 if (oval.isEmpty()) { |
| 1050 return; | 1051 return; |
| 1051 } | 1052 } |
| 1052 | 1053 |
| 1053 AutoRestoreEffects are; | 1054 AutoRestoreEffects are; |
| 1054 AutoCheckFlush acf(this); | 1055 AutoCheckFlush acf(this); |
| 1055 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf ); | 1056 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf ); |
| 1056 | 1057 |
| 1057 bool useAA = paint.isAntiAlias() && | 1058 bool useAA = paint.isAntiAlias() && |
| 1058 !target->getDrawState().getRenderTarget()->isMultisampled() && | 1059 !target->getDrawState().getRenderTarget()->isMultisampled() && |
| 1059 !disable_coverage_aa_for_blend(target); | 1060 !disable_coverage_aa_for_blend(target); |
| 1060 | 1061 |
| 1061 if (!fOvalRenderer->drawOval(target, this, useAA, oval, stroke)) { | 1062 if (!fOvalRenderer->drawOval(target, this, useAA, oval, stroke)) { |
| 1062 SkPath path; | 1063 SkPath path; |
| 1063 path.addOval(oval); | 1064 path.addOval(oval); |
| 1064 this->internalDrawPath(target, useAA, path, stroke); | 1065 this->internalDrawPath(target, paint, useAA, path, stroke); |
| 1065 } | 1066 } |
| 1066 } | 1067 } |
| 1067 | 1068 |
| 1068 // Can 'path' be drawn as a pair of filled nested rectangles? | 1069 // Can 'path' be drawn as a pair of filled nested rectangles? |
| 1069 static bool is_nested_rects(GrDrawTarget* target, | 1070 static bool is_nested_rects(GrDrawTarget* target, |
| 1070 const SkPath& path, | 1071 const SkPath& path, |
| 1071 const SkStrokeRec& stroke, | 1072 const SkStrokeRec& stroke, |
| 1072 SkRect rects[2], | 1073 SkRect rects[2], |
| 1073 bool* useVertexCoverage) { | 1074 bool* useVertexCoverage) { |
| 1074 SkASSERT(stroke.isFillStyle()); | 1075 SkASSERT(stroke.isFillStyle()); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1130 } | 1131 } |
| 1131 | 1132 |
| 1132 // Note that internalDrawPath may sw-rasterize the path into a scratch textu re. | 1133 // Note that internalDrawPath may sw-rasterize the path into a scratch textu re. |
| 1133 // Scratch textures can be recycled after they are returned to the texture | 1134 // Scratch textures can be recycled after they are returned to the texture |
| 1134 // cache. This presents a potential hazard for buffered drawing. However, | 1135 // cache. This presents a potential hazard for buffered drawing. However, |
| 1135 // the writePixels that uploads to the scratch will perform a flush so we're | 1136 // the writePixels that uploads to the scratch will perform a flush so we're |
| 1136 // OK. | 1137 // OK. |
| 1137 AutoRestoreEffects are; | 1138 AutoRestoreEffects are; |
| 1138 AutoCheckFlush acf(this); | 1139 AutoCheckFlush acf(this); |
| 1139 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf ); | 1140 GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf ); |
| 1141 GrDrawState* drawState = target->drawState(); | |
| 1140 | 1142 |
| 1141 bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget( )->isMultisampled(); | 1143 bool useAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisa mpled(); |
| 1144 | |
| 1142 if (useAA && stroke.getWidth() < 0 && !path.isConvex()) { | 1145 if (useAA && stroke.getWidth() < 0 && !path.isConvex()) { |
| 1143 // Concave AA paths are expensive - try to avoid them for special cases | 1146 // Concave AA paths are expensive - try to avoid them for special cases |
| 1144 bool useVertexCoverage; | 1147 bool useVertexCoverage; |
| 1145 SkRect rects[2]; | 1148 SkRect rects[2]; |
| 1146 | 1149 |
| 1147 if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) { | 1150 if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) { |
| 1148 SkMatrix origViewMatrix = target->getDrawState().getViewMatrix(); | 1151 SkMatrix origViewMatrix = drawState->getViewMatrix(); |
| 1149 GrDrawState::AutoViewMatrixRestore avmr; | 1152 GrDrawState::AutoViewMatrixRestore avmr; |
| 1150 if (!avmr.setIdentity(target->drawState())) { | 1153 if (!avmr.setIdentity(target->drawState())) { |
| 1151 return; | 1154 return; |
| 1152 } | 1155 } |
| 1153 | 1156 |
| 1154 fAARectRenderer->fillAANestedRects(this->getGpu(), target, | 1157 fAARectRenderer->fillAANestedRects(this->getGpu(), target, |
| 1155 rects, | 1158 rects, |
| 1156 origViewMatrix, | 1159 origViewMatrix, |
| 1157 useVertexCoverage); | 1160 useVertexCoverage); |
| 1158 return; | 1161 return; |
| 1159 } | 1162 } |
| 1160 } | 1163 } |
| 1161 | 1164 |
| 1162 SkRect ovalRect; | 1165 SkRect ovalRect; |
| 1163 bool isOval = path.isOval(&ovalRect); | 1166 bool isOval = path.isOval(&ovalRect); |
| 1164 | 1167 |
| 1165 if (!isOval || path.isInverseFillType() | 1168 if (!isOval || path.isInverseFillType() |
| 1166 || !fOvalRenderer->drawOval(target, this, useAA, ovalRect, stroke)) { | 1169 || !fOvalRenderer->drawOval(target, this, useAA, ovalRect, stroke)) { |
| 1167 this->internalDrawPath(target, useAA, path, stroke); | 1170 this->internalDrawPath(target, paint, useAA, path, stroke); |
| 1168 } | 1171 } |
| 1169 } | 1172 } |
| 1170 | 1173 |
| 1171 void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path, | 1174 namespace { |
| 1172 const SkStrokeRec& stroke) { | 1175 // See also: SkDrawTreatAsHairline. |
| 1176 static inline bool should_convert_to_hairline(const GrPaint& paint, const SkStro keRec& stroke, | |
| 1177 const SkMatrix& matrix, SkScalar* coverage) { | |
| 1178 | |
| 1179 if (stroke.getStyle() != SkStrokeRec::kStroke_Style) { | |
| 1180 return false; | |
| 1181 } | |
| 1182 | |
| 1183 SkASSERT(0 != stroke.getWidth()); | |
| 1184 | |
| 1185 if (!paint.isAntiAlias()) { | |
|
bsalomon
2013/10/30 14:37:39
Currently GrContext tries to convert the GrPaint t
Kimmo Kinnunen
2013/11/01 14:56:19
Done.
| |
| 1186 return false; | |
| 1187 } | |
| 1188 | |
| 1189 return SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, coverage); | |
| 1190 } | |
| 1191 } | |
| 1192 | |
| 1193 | |
| 1194 void GrContext::internalDrawPath(GrDrawTarget* target, const GrPaint& paint, boo l useAA, | |
| 1195 const SkPath& path, const SkStrokeRec& origStro ke) { | |
| 1173 SkASSERT(!path.isEmpty()); | 1196 SkASSERT(!path.isEmpty()); |
| 1174 | 1197 |
| 1175 // An Assumption here is that path renderer would use some form of tweaking | 1198 // An Assumption here is that path renderer would use some form of tweaking |
| 1176 // the src color (either the input alpha or in the frag shader) to implement | 1199 // the src color (either the input alpha or in the frag shader) to implement |
| 1177 // aa. If we have some future driver-mojo path AA that can do the right | 1200 // aa. If we have some future driver-mojo path AA that can do the right |
| 1178 // thing WRT to the blend then we'll need some query on the PR. | 1201 // thing WRT to the blend then we'll need some query on the PR. |
| 1179 if (disable_coverage_aa_for_blend(target)) { | 1202 if (disable_coverage_aa_for_blend(target)) { |
| 1180 #ifdef SK_DEBUG | 1203 #ifdef SK_DEBUG |
| 1181 //GrPrintf("Turning off AA to correctly apply blend.\n"); | 1204 //GrPrintf("Turning off AA to correctly apply blend.\n"); |
| 1182 #endif | 1205 #endif |
| 1183 useAA = false; | 1206 useAA = false; |
| 1184 } | 1207 } |
| 1185 | 1208 |
| 1209 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); | |
| 1210 // Can we treat a thin stroke as a hairline w/ coverage? If we can, we draw lots faster (raster | |
| 1211 // device does this same test). | |
| 1212 | |
| 1213 // Do not do this if gpu supports path rendering natively and we might be us ing the support (useAA == | |
| 1214 // false). Hairline renderer is likely to be slow due to program switches. | |
| 1215 if (useAA || !fGpu->caps()->pathRenderingSupport()) { | |
| 1216 SkScalar hairlineCoverage; | |
| 1217 if (should_convert_to_hairline(paint, *stroke, this->getMatrix(), &hairl ineCoverage)) { | |
| 1218 target->drawState()->setCoverage(SkScalarRoundToInt(hairlineCoverage * paint.getCoverage())); | |
| 1219 stroke.writable()->setHairlineStyle(); | |
| 1220 } | |
| 1221 } | |
| 1222 | |
| 1186 GrPathRendererChain::DrawType type = useAA ? GrPathRendererChain::kColorAnti Alias_DrawType : | 1223 GrPathRendererChain::DrawType type = useAA ? GrPathRendererChain::kColorAnti Alias_DrawType : |
| 1187 GrPathRendererChain::kColor_Dra wType; | 1224 GrPathRendererChain::kColor_Dra wType; |
| 1188 | 1225 |
| 1189 const SkPath* pathPtr = &path; | 1226 const SkPath* pathPtr = &path; |
| 1190 SkPath tmpPath; | 1227 SkPath tmpPath; |
| 1191 SkStrokeRec strokeRec(stroke); | |
| 1192 | 1228 |
| 1193 // Try a 1st time without stroking the path and without allowing the SW rend erer | 1229 // Try a 1st time without stroking the path and without allowing the SW rend erer |
| 1194 GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, fals e, type); | 1230 GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type); |
| 1195 | 1231 |
| 1196 if (NULL == pr) { | 1232 if (NULL == pr) { |
| 1197 if (!strokeRec.isHairlineStyle()) { | 1233 if (!stroke->isHairlineStyle()) { |
| 1198 // It didn't work the 1st time, so try again with the stroked path | 1234 // It didn't work the 1st time, so try again with the stroked path |
| 1199 if (strokeRec.applyToPath(&tmpPath, *pathPtr)) { | 1235 if (stroke->applyToPath(&tmpPath, *pathPtr)) { |
| 1200 pathPtr = &tmpPath; | 1236 pathPtr = &tmpPath; |
| 1201 strokeRec.setFillStyle(); | 1237 stroke.writable()->setFillStyle(); |
| 1202 } | 1238 } |
| 1203 } | 1239 } |
| 1204 if (pathPtr->isEmpty()) { | 1240 if (pathPtr->isEmpty()) { |
| 1205 return; | 1241 return; |
| 1206 } | 1242 } |
| 1207 | 1243 |
| 1208 // This time, allow SW renderer | 1244 // This time, allow SW renderer |
| 1209 pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type); | 1245 pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type); |
| 1210 } | 1246 } |
| 1211 | 1247 |
| 1212 if (NULL == pr) { | 1248 if (NULL == pr) { |
| 1213 #ifdef SK_DEBUG | 1249 #ifdef SK_DEBUG |
| 1214 GrPrintf("Unable to find path renderer compatible with path.\n"); | 1250 GrPrintf("Unable to find path renderer compatible with path.\n"); |
| 1215 #endif | 1251 #endif |
| 1216 return; | 1252 return; |
| 1217 } | 1253 } |
| 1218 | 1254 |
| 1219 pr->drawPath(*pathPtr, strokeRec, target, useAA); | 1255 pr->drawPath(*pathPtr, *stroke, target, useAA); |
| 1220 } | 1256 } |
| 1221 | 1257 |
| 1222 //////////////////////////////////////////////////////////////////////////////// | 1258 //////////////////////////////////////////////////////////////////////////////// |
| 1223 | 1259 |
| 1224 void GrContext::flush(int flagsBitfield) { | 1260 void GrContext::flush(int flagsBitfield) { |
| 1225 if (NULL == fDrawBuffer) { | 1261 if (NULL == fDrawBuffer) { |
| 1226 return; | 1262 return; |
| 1227 } | 1263 } |
| 1228 | 1264 |
| 1229 if (kDiscard_FlushBit & flagsBitfield) { | 1265 if (kDiscard_FlushBit & flagsBitfield) { |
| (...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1809 return NULL; | 1845 return NULL; |
| 1810 } | 1846 } |
| 1811 } | 1847 } |
| 1812 | 1848 |
| 1813 /////////////////////////////////////////////////////////////////////////////// | 1849 /////////////////////////////////////////////////////////////////////////////// |
| 1814 #if GR_CACHE_STATS | 1850 #if GR_CACHE_STATS |
| 1815 void GrContext::printCacheStats() const { | 1851 void GrContext::printCacheStats() const { |
| 1816 fTextureCache->printStats(); | 1852 fTextureCache->printStats(); |
| 1817 } | 1853 } |
| 1818 #endif | 1854 #endif |
| OLD | NEW |