OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 /* | 8 /* |
9 * Code for the "gm" (Golden Master) rendering comparison tool. | 9 * Code for the "gm" (Golden Master) rendering comparison tool. |
10 * | 10 * |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
187 { " cross-process, shared address", SkGPipeWriter::kCrossProcess_Flag | 187 { " cross-process, shared address", SkGPipeWriter::kCrossProcess_Flag |
188 | SkGPipeWriter::kSharedAddressSpace_Flag } | 188 | SkGPipeWriter::kSharedAddressSpace_Flag } |
189 }; | 189 }; |
190 | 190 |
191 class GMMain { | 191 class GMMain { |
192 public: | 192 public: |
193 GMMain() { | 193 GMMain() { |
194 // Set default values of member variables, which tool_main() | 194 // Set default values of member variables, which tool_main() |
195 // may override. | 195 // may override. |
196 fUseFileHierarchy = false; | 196 fUseFileHierarchy = false; |
197 fSimulatePipePlaybackFailure = false; | |
197 fMismatchPath = NULL; | 198 fMismatchPath = NULL; |
198 } | 199 } |
199 | 200 |
200 SkString make_name(const char shortName[], const char configName[]) { | 201 SkString make_name(const char shortName[], const char configName[]) { |
201 SkString name; | 202 SkString name; |
202 if (0 == strlen(configName)) { | 203 if (0 == strlen(configName)) { |
203 name.append(shortName); | 204 name.append(shortName); |
204 } else if (fUseFileHierarchy) { | 205 } else if (fUseFileHierarchy) { |
205 name.appendf("%s%c%s", configName, SkPATH_SEPARATOR, shortName); | 206 name.appendf("%s%c%s", configName, SkPATH_SEPARATOR, shortName); |
206 } else { | 207 } else { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 // The common case: no error means nothing to record. | 255 // The common case: no error means nothing to record. |
255 if (kEmptyErrorBitfield == errorType) { | 256 if (kEmptyErrorBitfield == errorType) { |
256 return; | 257 return; |
257 } | 258 } |
258 | 259 |
259 // If only certain error type(s) were reported, we know we can ignore th em. | 260 // If only certain error type(s) were reported, we know we can ignore th em. |
260 if (errorType == (errorType & kIgnorable_ErrorBitmask)) { | 261 if (errorType == (errorType & kIgnorable_ErrorBitmask)) { |
261 return; | 262 return; |
262 } | 263 } |
263 | 264 |
264 FailRec& rec = fFailedTests.push_back(make_name( | 265 SkString completeName = name; |
265 name.c_str(), renderModeDescriptor)); | 266 completeName.append(renderModeDescriptor); |
267 FailRec& rec = fFailedTests.push_back(completeName); | |
266 rec.fIsPixelError = | 268 rec.fIsPixelError = |
267 (kEmptyErrorBitfield != (errorType & kImageMismatch_ErrorBitmask)); | 269 (kEmptyErrorBitfield != (errorType & kImageMismatch_ErrorBitmask)); |
268 } | 270 } |
269 | 271 |
270 // List contents of fFailedTests via SkDebug. | 272 // List contents of fFailedTests via SkDebug. |
271 void ListErrors() { | 273 void ListErrors() { |
272 for (int i = 0; i < fFailedTests.count(); ++i) { | 274 for (int i = 0; i < fFailedTests.count(); ++i) { |
273 if (fFailedTests[i].fIsPixelError) { | 275 if (fFailedTests[i].fIsPixelError) { |
274 gm_fprintf(stderr, "\t\t%s pixel_error\n", fFailedTests[i].fName .c_str()); | 276 gm_fprintf(stderr, "\t\t%s pixel_error\n", fFailedTests[i].fName .c_str()); |
275 } else { | 277 } else { |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
898 ErrorBitfield errors = kEmptyErrorBitfield; | 900 ErrorBitfield errors = kEmptyErrorBitfield; |
899 for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) { | 901 for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) { |
900 SkBitmap bitmap; | 902 SkBitmap bitmap; |
901 SkISize size = gm->getISize(); | 903 SkISize size = gm->getISize(); |
902 setup_bitmap(gRec, size, &bitmap); | 904 setup_bitmap(gRec, size, &bitmap); |
903 SkCanvas canvas(bitmap); | 905 SkCanvas canvas(bitmap); |
904 PipeController pipeController(&canvas); | 906 PipeController pipeController(&canvas); |
905 SkGPipeWriter writer; | 907 SkGPipeWriter writer; |
906 SkCanvas* pipeCanvas = writer.startRecording( | 908 SkCanvas* pipeCanvas = writer.startRecording( |
907 &pipeController, gPipeWritingFlagCombos[i].flags); | 909 &pipeController, gPipeWritingFlagCombos[i].flags); |
908 invokeGM(gm, pipeCanvas, false, false); | 910 if (!this->fSimulatePipePlaybackFailure) { |
911 invokeGM(gm, pipeCanvas, false, false); | |
912 } | |
909 complete_bitmap(&bitmap); | 913 complete_bitmap(&bitmap); |
910 writer.endRecording(); | 914 writer.endRecording(); |
911 SkString string("-pipe"); | 915 SkString string("-pipe"); |
912 string.append(gPipeWritingFlagCombos[i].name); | 916 string.append(gPipeWritingFlagCombos[i].name); |
913 errors |= compare_test_results_to_reference_bitmap( | 917 errors |= compare_test_results_to_reference_bitmap( |
914 gm, gRec, string.c_str(), bitmap, &referenceBitmap); | 918 gm, gRec, string.c_str(), bitmap, &referenceBitmap); |
915 if (errors != kEmptyErrorBitfield) { | 919 if (errors != kEmptyErrorBitfield) { |
916 break; | 920 break; |
917 } | 921 } |
918 } | 922 } |
(...skipping 25 matching lines...) Expand all Loading... | |
944 } | 948 } |
945 return errors; | 949 return errors; |
946 } | 950 } |
947 | 951 |
948 // | 952 // |
949 // member variables. | 953 // member variables. |
950 // They are public for now, to allow easier setting by tool_main(). | 954 // They are public for now, to allow easier setting by tool_main(). |
951 // | 955 // |
952 | 956 |
953 bool fUseFileHierarchy; | 957 bool fUseFileHierarchy; |
958 bool fSimulatePipePlaybackFailure; | |
954 | 959 |
955 const char* fMismatchPath; | 960 const char* fMismatchPath; |
956 | 961 |
957 // information about all failed tests we have encountered so far | 962 // information about all failed tests we have encountered so far |
958 SkTArray<FailRec> fFailedTests; | 963 SkTArray<FailRec> fFailedTests; |
959 | 964 |
960 // Where to read expectations (expected image checksums, etc.) from. | 965 // Where to read expectations (expected image checksums, etc.) from. |
961 // If unset, we don't do comparisons. | 966 // If unset, we don't do comparisons. |
962 SkAutoTUnref<ExpectationsSource> fExpectationsSource; | 967 SkAutoTUnref<ExpectationsSource> fExpectationsSource; |
963 | 968 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1047 " [--modulo <remainder> <divisor>]: only run tests for which \n" | 1052 " [--modulo <remainder> <divisor>]: only run tests for which \n" |
1048 " testIndex %% divisor == remainder\n" | 1053 " testIndex %% divisor == remainder\n" |
1049 " [--nopdf]: skip the pdf rendering test pass\n" | 1054 " [--nopdf]: skip the pdf rendering test pass\n" |
1050 " [--nopipe]: Skip SkGPipe replay\n" | 1055 " [--nopipe]: Skip SkGPipe replay\n" |
1051 " [--readPath|-r <path>]: read reference images from this dir, and report\n" | 1056 " [--readPath|-r <path>]: read reference images from this dir, and report\n" |
1052 " any differences between those and the newly generated ones\n" | 1057 " any differences between those and the newly generated ones\n" |
1053 " [--noreplay]: do not exercise SkPicture replay\n" | 1058 " [--noreplay]: do not exercise SkPicture replay\n" |
1054 " [--resourcePath|-i <path>]: directory that stores image resources\n" | 1059 " [--resourcePath|-i <path>]: directory that stores image resources\n" |
1055 " [--nortree]: Do not exercise the R-Tree variant of SkPicture\n" | 1060 " [--nortree]: Do not exercise the R-Tree variant of SkPicture\n" |
1056 " [--noserialize]: do not exercise SkPicture serialization & deserialization\ n" | 1061 " [--noserialize]: do not exercise SkPicture serialization & deserialization\ n" |
1062 " [--simulatePipePlaybackFailure]: simulate a rendering failure in pipe mode only\n" | |
1057 " [--tiledPipe]: Exercise tiled SkGPipe replay\n" | 1063 " [--tiledPipe]: Exercise tiled SkGPipe replay\n" |
1058 " [--notileGrid]: Do not exercise the tile grid variant of SkPicture\n" | 1064 " [--notileGrid]: Do not exercise the tile grid variant of SkPicture\n" |
1059 " [--tileGridReplayScales <scales>]: Comma separated list of floating-point s cale\n" | 1065 " [--tileGridReplayScales <scales>]: Comma separated list of floating-point s cale\n" |
1060 " factors to be used for tileGrid playback testing. Default value: 1.0\n" | 1066 " factors to be used for tileGrid playback testing. Default value: 1.0\n" |
1061 " [--writeJsonSummary <path>]: write a JSON-formatted result summary to this file\n" | 1067 " [--writeJsonSummary <path>]: write a JSON-formatted result summary to this file\n" |
1062 " [--verbose] print diagnostics (e.g. list each config to be tested)\n" | 1068 " [--verbose] print diagnostics (e.g. list each config to be tested)\n" |
1063 " [--writePath|-w <path>]: write rendered images into this directory\n" | 1069 " [--writePath|-w <path>]: write rendered images into this directory\n" |
1064 " [--writePicturePath|-wp <path>]: write .skp files into this directory\n" | 1070 " [--writePicturePath|-wp <path>]: write .skp files into this directory\n" |
1065 ); | 1071 ); |
1066 } | 1072 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1129 #endif | 1135 #endif |
1130 } | 1136 } |
1131 | 1137 |
1132 template <typename T> void appendUnique(SkTDArray<T>* array, const T& value) { | 1138 template <typename T> void appendUnique(SkTDArray<T>* array, const T& value) { |
1133 int index = array->find(value); | 1139 int index = array->find(value); |
1134 if (index < 0) { | 1140 if (index < 0) { |
1135 *array->append() = value; | 1141 *array->append() = value; |
1136 } | 1142 } |
1137 } | 1143 } |
1138 | 1144 |
1145 /** | |
1146 * Run this test in a number of different configs (8888, 565, PDF, | |
1147 * etc.), confirming that the resulting bitmaps match expectations | |
1148 * (which may be different for each config). | |
1149 */ | |
1150 ErrorBitfield run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_ t> &configs, | |
epoger
2013/03/14 21:18:02
patchset 2 is a refactoring-only change... it extr
| |
1151 GrContextFactory *grFactory, int gpuCacheSize Bytes, | |
1152 int gpuCacheSizeCount, const char *writePath, bool doPDF, | |
1153 bool doDeferred) { | |
1154 uint32_t gmFlags = gm->getFlags(); | |
1155 ErrorBitfield testErrors = kEmptyErrorBitfield; | |
1156 for (int i = 0; i < configs.count(); i++) { | |
1157 ConfigData config = gRec[configs[i]]; | |
1158 | |
1159 // Skip any tests that we don't even need to try. | |
1160 if ((kPDF_Backend == config.fBackend) && | |
1161 (!doPDF || (gmFlags & GM::kSkipPDF_Flag))) | |
1162 { | |
1163 continue; | |
1164 } | |
1165 if ((gmFlags & GM::kSkip565_Flag) && | |
1166 (kRaster_Backend == config.fBackend) && | |
1167 (SkBitmap::kRGB_565_Config == config.fConfig)) { | |
1168 continue; | |
1169 } | |
1170 if ((gmFlags & GM::kSkipGPU_Flag) && | |
1171 kGPU_Backend == config.fBackend) { | |
1172 continue; | |
1173 } | |
1174 | |
1175 // Now we know that we want to run this test and record its | |
1176 // success or failure. | |
1177 ErrorBitfield renderErrors = kEmptyErrorBitfield; | |
1178 GrRenderTarget* renderTarget = NULL; | |
1179 #if SK_SUPPORT_GPU | |
1180 SkAutoTUnref<GrRenderTarget> rt; | |
1181 AutoResetGr autogr; | |
1182 if ((kEmptyErrorBitfield == renderErrors) && | |
1183 kGPU_Backend == config.fBackend) { | |
1184 GrContext* gr = grFactory->get(config.fGLContextType); | |
1185 bool grSuccess = false; | |
1186 if (gr) { | |
1187 // create a render target to back the device | |
1188 GrTextureDesc desc; | |
1189 desc.fConfig = kSkia8888_GrPixelConfig; | |
1190 desc.fFlags = kRenderTarget_GrTextureFlagBit; | |
1191 desc.fWidth = gm->getISize().width(); | |
1192 desc.fHeight = gm->getISize().height(); | |
1193 desc.fSampleCnt = config.fSampleCnt; | |
1194 GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0); | |
1195 if (tex) { | |
1196 rt.reset(tex->asRenderTarget()); | |
1197 rt.get()->ref(); | |
1198 tex->unref(); | |
1199 autogr.set(gr); | |
1200 renderTarget = rt.get(); | |
1201 grSuccess = NULL != renderTarget; | |
1202 } | |
1203 // Set the user specified cache limits if non-default. | |
1204 size_t bytes; | |
1205 int count; | |
1206 gr->getTextureCacheLimits(&count, &bytes); | |
1207 if (-1 != gpuCacheSizeBytes) { | |
1208 bytes = static_cast<size_t>(gpuCacheSizeBytes); | |
1209 } | |
1210 if (-1 != gpuCacheSizeCount) { | |
1211 count = gpuCacheSizeCount; | |
1212 } | |
1213 gr->setTextureCacheLimits(count, bytes); | |
1214 } | |
1215 if (!grSuccess) { | |
1216 renderErrors |= kNoGpuContext_ErrorBitmask; | |
1217 } | |
1218 } | |
1219 #endif | |
1220 | |
1221 SkBitmap comparisonBitmap; | |
1222 | |
1223 if (kEmptyErrorBitfield == renderErrors) { | |
1224 renderErrors |= gmmain.test_drawing(gm, config, writePath, | |
1225 GetGr(), | |
1226 renderTarget, | |
1227 &comparisonBitmap); | |
1228 } | |
1229 | |
1230 if (doDeferred && !renderErrors && | |
1231 (kGPU_Backend == config.fBackend || | |
1232 kRaster_Backend == config.fBackend)) { | |
1233 renderErrors |= gmmain.test_deferred_drawing(gm, config, | |
1234 comparisonBitmap, | |
1235 GetGr(), | |
1236 renderTarget); | |
1237 } | |
1238 | |
1239 testErrors |= renderErrors; | |
1240 } | |
1241 return testErrors; | |
1242 } | |
1243 | |
1244 /** | |
1245 * Run this test in a number of different drawing modes (pipe, | |
1246 * deferred, tiled, etc.), confirming that the resulting bitmaps are | |
1247 * *exactly* the same in all drawing modes. | |
1248 * | |
1249 * TODO(epoger): Right now, we only run the different drawing modes | |
1250 * with the 8888 config. Would there be value in running all those | |
1251 * different drawing modes in whatever configs (8888, 565, PDF) we are | |
1252 * testing? | |
1253 */ | |
1254 ErrorBitfield run_multiple_drawing_modes(GMMain &gmmain, GM *gm, | |
1255 const char *writePicturePath, bool doRe play, | |
1256 bool doSerialize, bool doRTree, bool do TileGrid, | |
1257 const SkTDArray<SkScalar> &tileGridRepl ayScales, | |
1258 bool doPipe, bool doTiledPipe) { | |
1259 uint32_t gmFlags = gm->getFlags(); | |
1260 SkBitmap comparisonBitmap; | |
1261 const ConfigData compareConfig = | |
1262 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType, 0, | |
1263 kRW_ConfigFlag, "comparison" }; | |
1264 ErrorBitfield testErrors = gmmain.generate_image(gm, compareConfig, NULL, NU LL, | |
1265 &comparisonBitmap, false); | |
1266 | |
1267 // run the picture centric GM steps | |
1268 if (!(gmFlags & GM::kSkipPicture_Flag)) { | |
1269 | |
1270 ErrorBitfield pictErrors = kEmptyErrorBitfield; | |
1271 | |
1272 //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm)); | |
1273 SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0); | |
1274 SkAutoUnref aur(pict); | |
1275 | |
1276 if ((kEmptyErrorBitfield == testErrors) && doReplay) { | |
1277 SkBitmap bitmap; | |
1278 gmmain.generate_image_from_picture(gm, compareConfig, pict, | |
1279 &bitmap); | |
1280 pictErrors |= gmmain.compare_test_results_to_reference_bitmap( | |
1281 gm, compareConfig, "-replay", bitmap, &comparisonBitmap); | |
1282 } | |
1283 | |
1284 if ((kEmptyErrorBitfield == testErrors) && | |
1285 (kEmptyErrorBitfield == pictErrors) && | |
1286 doSerialize) { | |
1287 SkPicture* repict = gmmain.stream_to_new_picture(*pict); | |
1288 SkAutoUnref aurr(repict); | |
1289 | |
1290 SkBitmap bitmap; | |
1291 gmmain.generate_image_from_picture(gm, compareConfig, repict, | |
1292 &bitmap); | |
1293 pictErrors |= gmmain.compare_test_results_to_reference_bitmap( | |
1294 gm, co mpareConfig, "-serialize", bitmap, &comparisonBitmap); | |
1295 } | |
1296 | |
1297 if (writePicturePath) { | |
1298 const char* pictureSuffix = "skp"; | |
1299 SkString path = make_filename(writePicturePath, "", | |
1300 gm->shortName(), | |
1301 pictureSuffix); | |
1302 SkFILEWStream stream(path.c_str()); | |
1303 pict->serialize(&stream); | |
1304 } | |
1305 | |
1306 testErrors |= pictErrors; | |
1307 } | |
1308 | |
1309 // TODO: add a test in which the RTree rendering results in a | |
1310 // different bitmap than the standard rendering. It should | |
1311 // show up as failed in the JSON summary, and should be listed | |
1312 // in the stdout also. | |
1313 if (!(gmFlags & GM::kSkipPicture_Flag) && doRTree) { | |
1314 SkPicture* pict = gmmain.generate_new_picture( | |
1315 gm, kRTree_BbhType, SkPict ure::kUsePathBoundsForClip_RecordingFlag); | |
1316 SkAutoUnref aur(pict); | |
1317 SkBitmap bitmap; | |
1318 gmmain.generate_image_from_picture(gm, compareConfig, pict, | |
1319 &bitmap); | |
1320 testErrors |= gmmain.compare_test_results_to_reference_bitmap( | |
1321 gm, compar eConfig, "-rtree", bitmap, &comparisonBitmap); | |
1322 } | |
1323 | |
1324 if (!(gmFlags & GM::kSkipPicture_Flag) && doTileGrid) { | |
1325 for(int scaleIndex = 0; scaleIndex < tileGridReplayScales.count(); ++sca leIndex) { | |
1326 SkScalar replayScale = tileGridReplayScales[scaleIndex]; | |
1327 if ((gmFlags & GM::kSkipScaledReplay_Flag) && replayScale != 1) | |
1328 continue; | |
1329 // We record with the reciprocal scale to obtain a replay | |
1330 // result that can be validated against comparisonBitmap. | |
1331 SkScalar recordScale = SkScalarInvert(replayScale); | |
1332 SkPicture* pict = gmmain.generate_new_picture( | |
1333 gm, kTileGrid_BbhType, SkPicture::kUsePathBoundsForClip_RecordingFlag, | |
1334 recordScale); | |
1335 SkAutoUnref aur(pict); | |
1336 SkBitmap bitmap; | |
1337 gmmain.generate_image_from_picture(gm, compareConfig, pict, | |
1338 &bitmap, replayScale); | |
1339 SkString suffix("-tilegrid"); | |
1340 if (SK_Scalar1 != replayScale) { | |
1341 suffix += "-scale-"; | |
1342 suffix.appendScalar(replayScale); | |
1343 } | |
1344 testErrors |= gmmain.compare_test_results_to_reference_bitmap( | |
1345 gm, co mpareConfig, suffix.c_str(), bitmap, | |
1346 &compa risonBitmap); | |
1347 } | |
1348 } | |
1349 | |
1350 // run the pipe centric GM steps | |
1351 if (!(gmFlags & GM::kSkipPipe_Flag)) { | |
1352 | |
1353 ErrorBitfield pipeErrors = kEmptyErrorBitfield; | |
1354 | |
1355 if ((kEmptyErrorBitfield == testErrors) && doPipe) { | |
1356 pipeErrors |= gmmain.test_pipe_playback(gm, compareConfig, | |
1357 comparisonBitmap); | |
1358 } | |
1359 | |
1360 if ((kEmptyErrorBitfield == testErrors) && | |
1361 (kEmptyErrorBitfield == pipeErrors) && | |
1362 doTiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) { | |
1363 pipeErrors |= gmmain.test_tiled_pipe_playback(gm, compareConfig, | |
1364 comparisonBitmap); | |
1365 } | |
1366 | |
1367 testErrors |= pipeErrors; | |
1368 } | |
1369 return testErrors; | |
1370 } | |
1371 | |
1139 int tool_main(int argc, char** argv); | 1372 int tool_main(int argc, char** argv); |
1140 int tool_main(int argc, char** argv) { | 1373 int tool_main(int argc, char** argv) { |
1141 | 1374 |
1142 #if SK_ENABLE_INST_COUNT | 1375 #if SK_ENABLE_INST_COUNT |
1143 gPrintInstCount = true; | 1376 gPrintInstCount = true; |
1144 #endif | 1377 #endif |
1145 | 1378 |
1146 SkGraphics::Init(); | 1379 SkGraphics::Init(); |
1147 // we don't need to see this during a run | 1380 // we don't need to see this during a run |
1148 gSkSuppressFontCachePurgeSpew = true; | 1381 gSkSuppressFontCachePurgeSpew = true; |
(...skipping 24 matching lines...) Expand all Loading... | |
1173 | 1406 |
1174 SkTDArray<size_t> configs; | 1407 SkTDArray<size_t> configs; |
1175 SkTDArray<size_t> excludeConfigs; | 1408 SkTDArray<size_t> excludeConfigs; |
1176 SkTDArray<SkScalar> tileGridReplayScales; | 1409 SkTDArray<SkScalar> tileGridReplayScales; |
1177 *tileGridReplayScales.append() = SK_Scalar1; // By default only test at scal e 1.0 | 1410 *tileGridReplayScales.append() = SK_Scalar1; // By default only test at scal e 1.0 |
1178 bool userConfig = false; | 1411 bool userConfig = false; |
1179 | 1412 |
1180 int moduloRemainder = -1; | 1413 int moduloRemainder = -1; |
1181 int moduloDivisor = -1; | 1414 int moduloDivisor = -1; |
1182 | 1415 |
1183 #if SK_SUPPORT_GPU | 1416 int gpuCacheSizeBytes = -1; |
1184 struct { | 1417 int gpuCacheSizeCount = -1; |
1185 int fBytes; | 1418 // -1 means use the default |
1186 int fCount; | |
1187 } gpuCacheSize = { -1, -1 }; // -1s mean use the default | |
1188 #endif | |
1189 | 1419 |
1190 const char* const commandName = argv[0]; | 1420 const char* const commandName = argv[0]; |
1191 char* const* stop = argv + argc; | 1421 char* const* stop = argv + argc; |
1192 for (++argv; argv < stop; ++argv) { | 1422 for (++argv; argv < stop; ++argv) { |
1193 if (strcmp(*argv, "--config") == 0) { | 1423 if (strcmp(*argv, "--config") == 0) { |
1194 argv++; | 1424 argv++; |
1195 if (argv < stop) { | 1425 if (argv < stop) { |
1196 int index = findConfig(*argv); | 1426 int index = findConfig(*argv); |
1197 if (index >= 0) { | 1427 if (index >= 0) { |
1198 appendUnique<size_t>(&configs, index); | 1428 appendUnique<size_t>(&configs, index); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1254 usage(commandName); | 1484 usage(commandName); |
1255 return -1; | 1485 return -1; |
1256 } | 1486 } |
1257 } else if (strcmp(*argv, "--enable-missing-warning") == 0) { | 1487 } else if (strcmp(*argv, "--enable-missing-warning") == 0) { |
1258 notifyMissingReadReference = true; | 1488 notifyMissingReadReference = true; |
1259 } else if (strcmp(*argv, "--forceBWtext") == 0) { | 1489 } else if (strcmp(*argv, "--forceBWtext") == 0) { |
1260 gForceBWtext = true; | 1490 gForceBWtext = true; |
1261 #if SK_SUPPORT_GPU | 1491 #if SK_SUPPORT_GPU |
1262 } else if (strcmp(*argv, "--gpuCacheSize") == 0) { | 1492 } else if (strcmp(*argv, "--gpuCacheSize") == 0) { |
1263 if (stop - argv > 2) { | 1493 if (stop - argv > 2) { |
1264 gpuCacheSize.fBytes = atoi(*++argv); | 1494 gpuCacheSizeBytes = atoi(*++argv); |
1265 gpuCacheSize.fCount = atoi(*++argv); | 1495 gpuCacheSizeCount = atoi(*++argv); |
1266 } else { | 1496 } else { |
1267 gm_fprintf(stderr, "missing arg for --gpuCacheSize\n"); | 1497 gm_fprintf(stderr, "missing arg for --gpuCacheSize\n"); |
1268 usage(commandName); | 1498 usage(commandName); |
1269 return -1; | 1499 return -1; |
1270 } | 1500 } |
1271 #endif | 1501 #endif |
1272 } else if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) { | 1502 } else if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) { |
1273 usage(commandName); | 1503 usage(commandName); |
1274 return -1; | 1504 return -1; |
1275 } else if (strcmp(*argv, "--hierarchy") == 0) { | 1505 } else if (strcmp(*argv, "--hierarchy") == 0) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1313 } else if ((0 == strcmp(*argv, "--resourcePath")) || | 1543 } else if ((0 == strcmp(*argv, "--resourcePath")) || |
1314 (0 == strcmp(*argv, "-i"))) { | 1544 (0 == strcmp(*argv, "-i"))) { |
1315 argv++; | 1545 argv++; |
1316 if (argv < stop && **argv) { | 1546 if (argv < stop && **argv) { |
1317 resourcePath = *argv; | 1547 resourcePath = *argv; |
1318 } | 1548 } |
1319 } else if (strcmp(*argv, "--serialize") == 0) { | 1549 } else if (strcmp(*argv, "--serialize") == 0) { |
1320 doSerialize = true; | 1550 doSerialize = true; |
1321 } else if (strcmp(*argv, "--noserialize") == 0) { | 1551 } else if (strcmp(*argv, "--noserialize") == 0) { |
1322 doSerialize = false; | 1552 doSerialize = false; |
1553 } else if (strcmp(*argv, "--simulatePipePlaybackFailure") == 0) { | |
1554 gmmain.fSimulatePipePlaybackFailure = true; | |
1323 } else if (strcmp(*argv, "--tiledPipe") == 0) { | 1555 } else if (strcmp(*argv, "--tiledPipe") == 0) { |
1324 doTiledPipe = true; | 1556 doTiledPipe = true; |
1325 } else if (!strcmp(*argv, "--verbose") || !strcmp(*argv, "-v")) { | 1557 } else if (!strcmp(*argv, "--verbose") || !strcmp(*argv, "-v")) { |
1326 doVerbose = true; | 1558 doVerbose = true; |
1327 } else if ((0 == strcmp(*argv, "--writePath")) || | 1559 } else if ((0 == strcmp(*argv, "--writePath")) || |
1328 (0 == strcmp(*argv, "-w"))) { | 1560 (0 == strcmp(*argv, "-w"))) { |
1329 argv++; | 1561 argv++; |
1330 if (argv < stop && **argv) { | 1562 if (argv < stop && **argv) { |
1331 writePath = *argv; | 1563 writePath = *argv; |
1332 } | 1564 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1458 if (skip_name(fMatches, shortName)) { | 1690 if (skip_name(fMatches, shortName)) { |
1459 SkDELETE(gm); | 1691 SkDELETE(gm); |
1460 continue; | 1692 continue; |
1461 } | 1693 } |
1462 | 1694 |
1463 SkISize size = gm->getISize(); | 1695 SkISize size = gm->getISize(); |
1464 gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), short Name, | 1696 gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), short Name, |
1465 size.width(), size.height()); | 1697 size.width(), size.height()); |
1466 | 1698 |
1467 ErrorBitfield testErrors = kEmptyErrorBitfield; | 1699 ErrorBitfield testErrors = kEmptyErrorBitfield; |
1468 uint32_t gmFlags = gm->getFlags(); | 1700 testErrors |= run_multiple_configs(gmmain, gm, configs, grFactory, gpuCa cheSizeBytes, |
1469 | 1701 gpuCacheSizeCount, writePath, doPDF, doDeferred); |
1470 for (int i = 0; i < configs.count(); i++) { | 1702 testErrors |= run_multiple_drawing_modes(gmmain, gm, writePicturePath, d oReplay, |
1471 ConfigData config = gRec[configs[i]]; | 1703 doSerialize, doRTree, doTileGri d, |
1472 | 1704 tileGridReplayScales, doPipe, d oTiledPipe); |
1473 // Skip any tests that we don't even need to try. | |
1474 if ((kPDF_Backend == config.fBackend) && | |
1475 (!doPDF || (gmFlags & GM::kSkipPDF_Flag))) | |
1476 { | |
1477 continue; | |
1478 } | |
1479 if ((gmFlags & GM::kSkip565_Flag) && | |
1480 (kRaster_Backend == config.fBackend) && | |
1481 (SkBitmap::kRGB_565_Config == config.fConfig)) { | |
1482 continue; | |
1483 } | |
1484 if ((gmFlags & GM::kSkipGPU_Flag) && | |
1485 kGPU_Backend == config.fBackend) { | |
1486 continue; | |
1487 } | |
1488 | |
1489 // Now we know that we want to run this test and record its | |
1490 // success or failure. | |
1491 ErrorBitfield renderErrors = kEmptyErrorBitfield; | |
1492 GrRenderTarget* renderTarget = NULL; | |
1493 #if SK_SUPPORT_GPU | |
1494 SkAutoTUnref<GrRenderTarget> rt; | |
1495 AutoResetGr autogr; | |
1496 if ((kEmptyErrorBitfield == renderErrors) && | |
1497 kGPU_Backend == config.fBackend) { | |
1498 GrContext* gr = grFactory->get(config.fGLContextType); | |
1499 bool grSuccess = false; | |
1500 if (gr) { | |
1501 // create a render target to back the device | |
1502 GrTextureDesc desc; | |
1503 desc.fConfig = kSkia8888_GrPixelConfig; | |
1504 desc.fFlags = kRenderTarget_GrTextureFlagBit; | |
1505 desc.fWidth = gm->getISize().width(); | |
1506 desc.fHeight = gm->getISize().height(); | |
1507 desc.fSampleCnt = config.fSampleCnt; | |
1508 GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0); | |
1509 if (tex) { | |
1510 rt.reset(tex->asRenderTarget()); | |
1511 rt.get()->ref(); | |
1512 tex->unref(); | |
1513 autogr.set(gr); | |
1514 renderTarget = rt.get(); | |
1515 grSuccess = NULL != renderTarget; | |
1516 } | |
1517 // Set the user specified cache limits if non-default. | |
1518 size_t bytes; | |
1519 int count; | |
1520 gr->getTextureCacheLimits(&count, &bytes); | |
1521 if (-1 != gpuCacheSize.fBytes) { | |
1522 bytes = static_cast<size_t>(gpuCacheSize.fBytes); | |
1523 } | |
1524 if (-1 != gpuCacheSize.fCount) { | |
1525 count = gpuCacheSize.fCount; | |
1526 } | |
1527 gr->setTextureCacheLimits(count, bytes); | |
1528 } | |
1529 if (!grSuccess) { | |
1530 renderErrors |= kNoGpuContext_ErrorBitmask; | |
1531 } | |
1532 } | |
1533 #endif | |
1534 | |
1535 SkBitmap comparisonBitmap; | |
1536 | |
1537 if (kEmptyErrorBitfield == renderErrors) { | |
1538 renderErrors |= gmmain.test_drawing(gm, config, writePath, | |
1539 GetGr(), | |
1540 renderTarget, | |
1541 &comparisonBitmap); | |
1542 } | |
1543 | |
1544 if (doDeferred && !renderErrors && | |
1545 (kGPU_Backend == config.fBackend || | |
1546 kRaster_Backend == config.fBackend)) { | |
1547 renderErrors |= gmmain.test_deferred_drawing(gm, config, | |
1548 comparisonBitmap, | |
1549 GetGr(), | |
1550 renderTarget); | |
1551 } | |
1552 | |
1553 testErrors |= renderErrors; | |
1554 } | |
1555 | |
1556 SkBitmap comparisonBitmap; | |
1557 const ConfigData compareConfig = | |
1558 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextT ype, 0, kRW_ConfigFlag, "comparison" }; | |
1559 testErrors |= gmmain.generate_image(gm, compareConfig, NULL, NULL, &comp arisonBitmap, false); | |
1560 | |
1561 // run the picture centric GM steps | |
1562 if (!(gmFlags & GM::kSkipPicture_Flag)) { | |
1563 | |
1564 ErrorBitfield pictErrors = kEmptyErrorBitfield; | |
1565 | |
1566 //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm)); | |
1567 SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0); | |
1568 SkAutoUnref aur(pict); | |
1569 | |
1570 if ((kEmptyErrorBitfield == testErrors) && doReplay) { | |
1571 SkBitmap bitmap; | |
1572 gmmain.generate_image_from_picture(gm, compareConfig, pict, | |
1573 &bitmap); | |
1574 pictErrors |= gmmain.compare_test_results_to_reference_bitmap( | |
1575 gm, compareConfig, "-replay", bitmap, &comparisonBitmap); | |
1576 } | |
1577 | |
1578 if ((kEmptyErrorBitfield == testErrors) && | |
1579 (kEmptyErrorBitfield == pictErrors) && | |
1580 doSerialize) { | |
1581 SkPicture* repict = gmmain.stream_to_new_picture(*pict); | |
1582 SkAutoUnref aurr(repict); | |
1583 | |
1584 SkBitmap bitmap; | |
1585 gmmain.generate_image_from_picture(gm, compareConfig, repict, | |
1586 &bitmap); | |
1587 pictErrors |= gmmain.compare_test_results_to_reference_bitmap( | |
1588 gm, compareConfig, "-serialize", bitmap, &comparisonBitmap); | |
1589 } | |
1590 | |
1591 if (writePicturePath) { | |
1592 const char* pictureSuffix = "skp"; | |
1593 SkString path = make_filename(writePicturePath, "", | |
1594 gm->shortName(), | |
1595 pictureSuffix); | |
1596 SkFILEWStream stream(path.c_str()); | |
1597 pict->serialize(&stream); | |
1598 } | |
1599 | |
1600 testErrors |= pictErrors; | |
1601 } | |
1602 | |
1603 // TODO: add a test in which the RTree rendering results in a | |
1604 // different bitmap than the standard rendering. It should | |
1605 // show up as failed in the JSON summary, and should be listed | |
1606 // in the stdout also. | |
1607 if (!(gmFlags & GM::kSkipPicture_Flag) && doRTree) { | |
1608 SkPicture* pict = gmmain.generate_new_picture( | |
1609 gm, kRTree_BbhType, SkPicture::kUsePathBoundsForClip_RecordingFl ag); | |
1610 SkAutoUnref aur(pict); | |
1611 SkBitmap bitmap; | |
1612 gmmain.generate_image_from_picture(gm, compareConfig, pict, | |
1613 &bitmap); | |
1614 testErrors |= gmmain.compare_test_results_to_reference_bitmap( | |
1615 gm, compareConfig, "-rtree", bitmap, &comparisonBitmap); | |
1616 } | |
1617 | |
1618 if (!(gmFlags & GM::kSkipPicture_Flag) && doTileGrid) { | |
1619 for(int scaleIndex = 0; scaleIndex < tileGridReplayScales.count(); + +scaleIndex) { | |
1620 SkScalar replayScale = tileGridReplayScales[scaleIndex]; | |
1621 if ((gmFlags & GM::kSkipScaledReplay_Flag) && replayScale != 1) | |
1622 continue; | |
1623 // We record with the reciprocal scale to obtain a replay | |
1624 // result that can be validated against comparisonBitmap. | |
1625 SkScalar recordScale = SkScalarInvert(replayScale); | |
1626 SkPicture* pict = gmmain.generate_new_picture( | |
1627 gm, kTileGrid_BbhType, SkPicture::kUsePathBoundsForClip_Reco rdingFlag, | |
1628 recordScale); | |
1629 SkAutoUnref aur(pict); | |
1630 SkBitmap bitmap; | |
1631 gmmain.generate_image_from_picture(gm, compareConfig, pict, | |
1632 &bitmap, replayScale); | |
1633 SkString suffix("-tilegrid"); | |
1634 if (SK_Scalar1 != replayScale) { | |
1635 suffix += "-scale-"; | |
1636 suffix.appendScalar(replayScale); | |
1637 } | |
1638 testErrors |= gmmain.compare_test_results_to_reference_bitmap( | |
1639 gm, compareConfig, suffix.c_str(), bitmap, | |
1640 &comparisonBitmap); | |
1641 } | |
1642 } | |
1643 | |
1644 // run the pipe centric GM steps | |
1645 if (!(gmFlags & GM::kSkipPipe_Flag)) { | |
1646 | |
1647 ErrorBitfield pipeErrors = kEmptyErrorBitfield; | |
1648 | |
1649 if ((kEmptyErrorBitfield == testErrors) && doPipe) { | |
1650 pipeErrors |= gmmain.test_pipe_playback(gm, compareConfig, | |
1651 comparisonBitmap); | |
1652 } | |
1653 | |
1654 if ((kEmptyErrorBitfield == testErrors) && | |
1655 (kEmptyErrorBitfield == pipeErrors) && | |
1656 doTiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) { | |
1657 pipeErrors |= gmmain.test_tiled_pipe_playback(gm, compareConfig, | |
1658 comparisonBitmap); | |
1659 } | |
1660 | |
1661 testErrors |= pipeErrors; | |
1662 } | |
1663 | 1705 |
1664 // Update overall results. | 1706 // Update overall results. |
1665 // We only tabulate the particular error types that we currently | 1707 // We only tabulate the particular error types that we currently |
1666 // care about (e.g., missing reference images). Later on, if we | 1708 // care about (e.g., missing reference images). Later on, if we |
1667 // want to also tabulate other error types, we can do so. | 1709 // want to also tabulate other error types, we can do so. |
1668 testsRun++; | 1710 testsRun++; |
1669 if (!gmmain.fExpectationsSource.get() || | 1711 if (!gmmain.fExpectationsSource.get() || |
1670 (kEmptyErrorBitfield != (kMissingExpectations_ErrorBitmask & testErr ors))) { | 1712 (kEmptyErrorBitfield != (kMissingExpectations_ErrorBitmask & testErr ors))) { |
1671 testsMissingReferenceImages++; | 1713 testsMissingReferenceImages++; |
1672 } | 1714 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1720 SkGraphics::Term(); | 1762 SkGraphics::Term(); |
1721 | 1763 |
1722 return (0 == testsFailed) ? 0 : -1; | 1764 return (0 == testsFailed) ? 0 : -1; |
1723 } | 1765 } |
1724 | 1766 |
1725 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 1767 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
1726 int main(int argc, char * const argv[]) { | 1768 int main(int argc, char * const argv[]) { |
1727 return tool_main(argc, (char**) argv); | 1769 return tool_main(argc, (char**) argv); |
1728 } | 1770 } |
1729 #endif | 1771 #endif |
OLD | NEW |