Chromium Code Reviews| 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 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1522 } | 1522 } |
| 1523 | 1523 |
| 1524 template <typename T> void appendUnique(SkTDArray<T>* array, const T& value) { | 1524 template <typename T> void appendUnique(SkTDArray<T>* array, const T& value) { |
| 1525 int index = array->find(value); | 1525 int index = array->find(value); |
| 1526 if (index < 0) { | 1526 if (index < 0) { |
| 1527 *array->append() = value; | 1527 *array->append() = value; |
| 1528 } | 1528 } |
| 1529 } | 1529 } |
| 1530 | 1530 |
| 1531 /** | 1531 /** |
| 1532 * Run this test in a number of different configs (8888, 565, PDF, | |
| 1533 * etc.), confirming that the resulting bitmaps match expectations | |
| 1534 * (which may be different for each config). | |
| 1535 * | |
| 1536 * Returns all errors encountered while doing so. | |
| 1537 */ | |
| 1538 ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, | |
| 1539 const SkTDArray<size_t> &configs, | |
| 1540 const SkTDArray<const PDFRasterizerData*> &pdfRasterizers, | |
| 1541 GrContextFactory *grFactory); | |
| 1542 ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, | |
| 1543 const SkTDArray<size_t> &configs, | |
| 1544 const SkTDArray<const PDFRasterizerData*> &pdfRasterizers, | |
| 1545 GrContextFactory *grFactory) { | |
| 1546 const char renderModeDescriptor[] = ""; | |
| 1547 ErrorCombination errorsForAllConfigs; | |
| 1548 uint32_t gmFlags = gm->getFlags(); | |
| 1549 | |
| 1550 for (int i = 0; i < configs.count(); i++) { | |
| 1551 ConfigData config = gRec[configs[i]]; | |
| 1552 const SkString shortNamePlusConfig = gmmain.make_shortname_plus_config(g m->shortName(), | |
| 1553 c onfig.fName); | |
| 1554 | |
| 1555 // Skip any tests that we don't even need to try. | |
| 1556 // If any of these were skipped on a per-GM basis, record them as | |
| 1557 // kIntentionallySkipped. | |
| 1558 if (kPDF_Backend == config.fBackend) { | |
| 1559 if (gmFlags & GM::kSkipPDF_Flag) { | |
| 1560 gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortN amePlusConfig, | |
| 1561 renderModeDescriptor); | |
| 1562 errorsForAllConfigs.add(kIntentionallySkipped_ErrorType); | |
| 1563 continue; | |
| 1564 } | |
| 1565 } | |
| 1566 if ((gmFlags & GM::kSkip565_Flag) && | |
| 1567 (kRaster_Backend == config.fBackend) && | |
| 1568 (SkBitmap::kRGB_565_Config == config.fConfig)) { | |
| 1569 gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNameP lusConfig, | |
| 1570 renderModeDescriptor); | |
| 1571 errorsForAllConfigs.add(kIntentionallySkipped_ErrorType); | |
| 1572 continue; | |
| 1573 } | |
| 1574 if (((gmFlags & GM::kSkipGPU_Flag) && kGPU_Backend == config.fBackend) | | | |
| 1575 ((gmFlags & GM::kGPUOnly_Flag) && kGPU_Backend != config.fBackend)) { | |
| 1576 gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNameP lusConfig, | |
| 1577 renderModeDescriptor); | |
| 1578 errorsForAllConfigs.add(kIntentionallySkipped_ErrorType); | |
| 1579 continue; | |
| 1580 } | |
| 1581 | |
| 1582 // Now we know that we want to run this test and record its | |
| 1583 // success or failure. | |
| 1584 ErrorCombination errorsForThisConfig; | |
| 1585 GrSurface* gpuTarget = NULL; | |
| 1586 #if SK_SUPPORT_GPU | |
| 1587 SkAutoTUnref<GrSurface> auGpuTarget; | |
| 1588 if ((errorsForThisConfig.isEmpty()) && (kGPU_Backend == config.fBackend) ) { | |
| 1589 if (FLAGS_resetGpuContext) { | |
| 1590 grFactory->destroyContexts(); | |
| 1591 } | |
| 1592 GrContext* gr = grFactory->get(config.fGLContextType); | |
| 1593 bool grSuccess = false; | |
| 1594 if (gr) { | |
| 1595 // create a render target to back the device | |
| 1596 GrTextureDesc desc; | |
| 1597 desc.fConfig = kSkia8888_GrPixelConfig; | |
| 1598 desc.fFlags = kRenderTarget_GrTextureFlagBit; | |
| 1599 desc.fWidth = gm->getISize().width(); | |
| 1600 desc.fHeight = gm->getISize().height(); | |
| 1601 desc.fSampleCnt = config.fSampleCnt; | |
| 1602 auGpuTarget.reset(gr->createUncachedTexture(desc, NULL, 0)); | |
| 1603 if (NULL != auGpuTarget) { | |
| 1604 gpuTarget = auGpuTarget; | |
| 1605 grSuccess = true; | |
| 1606 // Set the user specified cache limits if non-default. | |
| 1607 size_t bytes; | |
| 1608 int count; | |
| 1609 gr->getTextureCacheLimits(&count, &bytes); | |
| 1610 if (DEFAULT_CACHE_VALUE != gGpuCacheSizeBytes) { | |
| 1611 bytes = static_cast<size_t>(gGpuCacheSizeBytes); | |
| 1612 } | |
| 1613 if (DEFAULT_CACHE_VALUE != gGpuCacheSizeCount) { | |
| 1614 count = gGpuCacheSizeCount; | |
| 1615 } | |
| 1616 gr->setTextureCacheLimits(count, bytes); | |
| 1617 } | |
| 1618 } | |
| 1619 if (!grSuccess) { | |
| 1620 errorsForThisConfig.add(kNoGpuContext_ErrorType); | |
| 1621 } | |
| 1622 } | |
| 1623 #endif | |
| 1624 | |
| 1625 SkBitmap comparisonBitmap; | |
| 1626 | |
| 1627 const char* writePath; | |
| 1628 if (FLAGS_writePath.count() == 1) { | |
| 1629 writePath = FLAGS_writePath[0]; | |
| 1630 } else { | |
| 1631 writePath = NULL; | |
| 1632 } | |
| 1633 | |
| 1634 if (errorsForThisConfig.isEmpty()) { | |
| 1635 errorsForThisConfig.add(gmmain.test_drawing(gm, config, pdfRasterize rs, | |
| 1636 writePath, gpuTarget, | |
| 1637 &comparisonBitmap)); | |
| 1638 gmmain.RecordTestResults(errorsForThisConfig, shortNamePlusConfig, " "); | |
| 1639 } | |
| 1640 | |
| 1641 if (FLAGS_deferred && errorsForThisConfig.isEmpty() && | |
| 1642 (kGPU_Backend == config.fBackend || kRaster_Backend == config.fBacke nd)) { | |
| 1643 errorsForThisConfig.add(gmmain.test_deferred_drawing(gm, config, com parisonBitmap, | |
| 1644 gpuTarget)); | |
| 1645 } | |
| 1646 | |
| 1647 errorsForAllConfigs.add(errorsForThisConfig); | |
| 1648 } | |
| 1649 return errorsForAllConfigs; | |
| 1650 } | |
| 1651 | |
| 1652 /** | |
| 1653 * Run this test in a number of different drawing modes (pipe, | 1532 * Run this test in a number of different drawing modes (pipe, |
| 1654 * deferred, tiled, etc.), confirming that the resulting bitmaps all | 1533 * deferred, tiled, etc.), confirming that the resulting bitmaps all |
| 1655 * *exactly* match comparisonBitmap. | 1534 * *exactly* match comparisonBitmap. |
| 1656 * | 1535 * |
| 1657 * Returns all errors encountered while doing so. | 1536 * Returns all errors encountered while doing so. |
| 1658 */ | 1537 */ |
| 1659 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co mpareConfig, | 1538 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co mpareConfig, |
| 1660 const SkBitmap &comparisonBitmap, | 1539 const SkBitmap &comparisonBitmap, |
| 1661 const SkTDArray<SkScalar> &tileGridReplaySca les); | 1540 const SkTDArray<SkScalar> &tileGridReplaySca les); |
| 1662 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co mpareConfig, | 1541 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co mpareConfig, |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1775 errorsForAllModes.add(gmmain.test_pipe_playback(gm, compareConfig, compa risonBitmap, | 1654 errorsForAllModes.add(gmmain.test_pipe_playback(gm, compareConfig, compa risonBitmap, |
| 1776 FLAGS_simulatePipePlayba ckFailure)); | 1655 FLAGS_simulatePipePlayba ckFailure)); |
| 1777 if (FLAGS_tiledPipe) { | 1656 if (FLAGS_tiledPipe) { |
| 1778 errorsForAllModes.add(gmmain.test_tiled_pipe_playback(gm, compareCon fig, | 1657 errorsForAllModes.add(gmmain.test_tiled_pipe_playback(gm, compareCon fig, |
| 1779 comparisonBitm ap)); | 1658 comparisonBitm ap)); |
| 1780 } | 1659 } |
| 1781 } | 1660 } |
| 1782 return errorsForAllModes; | 1661 return errorsForAllModes; |
| 1783 } | 1662 } |
| 1784 | 1663 |
| 1664 | |
| 1665 /** | |
| 1666 * Run this test in a number of different configs (8888, 565, PDF, | |
| 1667 * etc.), confirming that the resulting bitmaps match expectations | |
| 1668 * (which may be different for each config). | |
| 1669 * | |
| 1670 * Returns all errors encountered while doing so. | |
| 1671 */ | |
| 1672 ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, | |
| 1673 const SkTDArray<size_t> &configs, | |
| 1674 const SkTDArray<const PDFRasterizerData*> &pdfRasterizers, | |
| 1675 const SkTDArray<SkScalar> &tileGridReplayS cales, | |
| 1676 GrContextFactory *grFactory); | |
| 1677 ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, | |
| 1678 const SkTDArray<size_t> &configs, | |
| 1679 const SkTDArray<const PDFRasterizerData*> &pdfRasterizers, | |
| 1680 const SkTDArray<SkScalar> &tileGridReplayS cales, | |
| 1681 GrContextFactory *grFactory) { | |
| 1682 const char renderModeDescriptor[] = ""; | |
| 1683 ErrorCombination errorsForAllConfigs; | |
| 1684 uint32_t gmFlags = gm->getFlags(); | |
| 1685 | |
| 1686 for (int i = 0; i < configs.count(); i++) { | |
| 1687 ConfigData config = gRec[configs[i]]; | |
| 1688 const SkString shortNamePlusConfig = gmmain.make_shortname_plus_config(g m->shortName(), | |
| 1689 c onfig.fName); | |
| 1690 | |
| 1691 // Skip any tests that we don't even need to try. | |
| 1692 // If any of these were skipped on a per-GM basis, record them as | |
| 1693 // kIntentionallySkipped. | |
| 1694 if (kPDF_Backend == config.fBackend) { | |
| 1695 if (gmFlags & GM::kSkipPDF_Flag) { | |
| 1696 gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortN amePlusConfig, | |
| 1697 renderModeDescriptor); | |
| 1698 errorsForAllConfigs.add(kIntentionallySkipped_ErrorType); | |
| 1699 continue; | |
| 1700 } | |
| 1701 } | |
| 1702 if ((gmFlags & GM::kSkip565_Flag) && | |
| 1703 (kRaster_Backend == config.fBackend) && | |
| 1704 (SkBitmap::kRGB_565_Config == config.fConfig)) { | |
| 1705 gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNameP lusConfig, | |
| 1706 renderModeDescriptor); | |
| 1707 errorsForAllConfigs.add(kIntentionallySkipped_ErrorType); | |
| 1708 continue; | |
| 1709 } | |
| 1710 if (((gmFlags & GM::kSkipGPU_Flag) && kGPU_Backend == config.fBackend) | | | |
| 1711 ((gmFlags & GM::kGPUOnly_Flag) && kGPU_Backend != config.fBackend)) { | |
| 1712 gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNameP lusConfig, | |
| 1713 renderModeDescriptor); | |
| 1714 errorsForAllConfigs.add(kIntentionallySkipped_ErrorType); | |
| 1715 continue; | |
| 1716 } | |
| 1717 | |
| 1718 // Now we know that we want to run this test and record its | |
| 1719 // success or failure. | |
| 1720 ErrorCombination errorsForThisConfig; | |
| 1721 GrSurface* gpuTarget = NULL; | |
| 1722 #if SK_SUPPORT_GPU | |
| 1723 SkAutoTUnref<GrSurface> auGpuTarget; | |
| 1724 if ((errorsForThisConfig.isEmpty()) && (kGPU_Backend == config.fBackend) ) { | |
| 1725 if (FLAGS_resetGpuContext) { | |
| 1726 grFactory->destroyContexts(); | |
| 1727 } | |
| 1728 GrContext* gr = grFactory->get(config.fGLContextType); | |
| 1729 bool grSuccess = false; | |
| 1730 if (gr) { | |
| 1731 // create a render target to back the device | |
| 1732 GrTextureDesc desc; | |
| 1733 desc.fConfig = kSkia8888_GrPixelConfig; | |
| 1734 desc.fFlags = kRenderTarget_GrTextureFlagBit; | |
| 1735 desc.fWidth = gm->getISize().width(); | |
| 1736 desc.fHeight = gm->getISize().height(); | |
| 1737 desc.fSampleCnt = config.fSampleCnt; | |
| 1738 auGpuTarget.reset(gr->createUncachedTexture(desc, NULL, 0)); | |
| 1739 if (NULL != auGpuTarget) { | |
| 1740 gpuTarget = auGpuTarget; | |
| 1741 grSuccess = true; | |
| 1742 // Set the user specified cache limits if non-default. | |
| 1743 size_t bytes; | |
| 1744 int count; | |
| 1745 gr->getTextureCacheLimits(&count, &bytes); | |
| 1746 if (DEFAULT_CACHE_VALUE != gGpuCacheSizeBytes) { | |
| 1747 bytes = static_cast<size_t>(gGpuCacheSizeBytes); | |
| 1748 } | |
| 1749 if (DEFAULT_CACHE_VALUE != gGpuCacheSizeCount) { | |
| 1750 count = gGpuCacheSizeCount; | |
| 1751 } | |
| 1752 gr->setTextureCacheLimits(count, bytes); | |
| 1753 } | |
| 1754 } | |
| 1755 if (!grSuccess) { | |
| 1756 errorsForThisConfig.add(kNoGpuContext_ErrorType); | |
| 1757 } | |
| 1758 } | |
| 1759 #endif | |
| 1760 | |
| 1761 SkBitmap comparisonBitmap; | |
| 1762 | |
| 1763 const char* writePath; | |
| 1764 if (FLAGS_writePath.count() == 1) { | |
| 1765 writePath = FLAGS_writePath[0]; | |
| 1766 } else { | |
| 1767 writePath = NULL; | |
| 1768 } | |
| 1769 | |
| 1770 if (errorsForThisConfig.isEmpty()) { | |
| 1771 errorsForThisConfig.add(gmmain.test_drawing(gm, config, pdfRasterize rs, | |
| 1772 writePath, gpuTarget, | |
| 1773 &comparisonBitmap)); | |
| 1774 gmmain.RecordTestResults(errorsForThisConfig, shortNamePlusConfig, " "); | |
| 1775 } | |
| 1776 | |
| 1777 // TODO: run only if gmmain.test_drawing succeeded. | |
|
mtklein
2014/01/08 20:05:53
The diff is weird, but what's happened here is:
epoger
2014/01/08 20:48:55
Thanks for the explanation.
One way of avoiding t
| |
| 1778 if (kRaster_Backend == config.fBackend) { | |
| 1779 run_multiple_modes(gmmain, gm, config, comparisonBitmap, tileGridRep layScales); | |
| 1780 } | |
| 1781 | |
| 1782 if (FLAGS_deferred && errorsForThisConfig.isEmpty() && | |
| 1783 (kGPU_Backend == config.fBackend || kRaster_Backend == config.fBacke nd)) { | |
| 1784 errorsForThisConfig.add(gmmain.test_deferred_drawing(gm, config, com parisonBitmap, | |
| 1785 gpuTarget)); | |
| 1786 } | |
| 1787 | |
| 1788 errorsForAllConfigs.add(errorsForThisConfig); | |
| 1789 } | |
| 1790 return errorsForAllConfigs; | |
| 1791 } | |
| 1792 | |
| 1793 | |
| 1785 /** | 1794 /** |
| 1786 * Read individual lines from a file, pushing them into the given array. | 1795 * Read individual lines from a file, pushing them into the given array. |
| 1787 * | 1796 * |
| 1788 * @param filename path to the file to read | 1797 * @param filename path to the file to read |
| 1789 * @param lines array of strings to add the lines to | 1798 * @param lines array of strings to add the lines to |
| 1790 * @returns true if able to read lines from the file | 1799 * @returns true if able to read lines from the file |
| 1791 */ | 1800 */ |
| 1792 static bool read_lines_from_file(const char* filename, SkTArray<SkString> &lines ) { | 1801 static bool read_lines_from_file(const char* filename, SkTArray<SkString> &lines ) { |
| 1793 SkAutoTUnref<SkStream> streamWrapper(SkStream::NewFromFile(filename)); | 1802 SkAutoTUnref<SkStream> streamWrapper(SkStream::NewFromFile(filename)); |
| 1794 SkStream *stream = streamWrapper.get(); | 1803 SkStream *stream = streamWrapper.get(); |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2292 | 2301 |
| 2293 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, shortName)) { | 2302 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, shortName)) { |
| 2294 continue; | 2303 continue; |
| 2295 } | 2304 } |
| 2296 | 2305 |
| 2297 gmsRun++; | 2306 gmsRun++; |
| 2298 SkISize size = gm->getISize(); | 2307 SkISize size = gm->getISize(); |
| 2299 gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), short Name, | 2308 gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), short Name, |
| 2300 size.width(), size.height()); | 2309 size.width(), size.height()); |
| 2301 | 2310 |
| 2302 run_multiple_configs(gmmain, gm, configs, pdfRasterizers, grFactory); | 2311 run_multiple_configs(gmmain, gm, configs, pdfRasterizers, tileGridReplay Scales, grFactory); |
| 2303 | |
| 2304 SkBitmap comparisonBitmap; | |
| 2305 const ConfigData compareConfig = | |
| 2306 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextT ype, 0, kRW_ConfigFlag, "comparison", false }; | |
| 2307 gmmain.generate_image(gm, compareConfig, NULL, &comparisonBitmap, false) ; | |
| 2308 | |
| 2309 // TODO(epoger): only run this if gmmain.generate_image() succeeded? | |
| 2310 // Otherwise, what are we comparing against? | |
| 2311 run_multiple_modes(gmmain, gm, compareConfig, comparisonBitmap, tileGrid ReplayScales); | |
| 2312 } | 2312 } |
| 2313 | 2313 |
| 2314 SkTArray<SkString> modes; | 2314 SkTArray<SkString> modes; |
| 2315 gmmain.GetRenderModesEncountered(modes); | 2315 gmmain.GetRenderModesEncountered(modes); |
| 2316 bool reportError = false; | 2316 bool reportError = false; |
| 2317 if (gmmain.NumSignificantErrors() > 0) { | 2317 if (gmmain.NumSignificantErrors() > 0) { |
| 2318 reportError = true; | 2318 reportError = true; |
| 2319 } | 2319 } |
| 2320 int expectedNumberOfTests = gmsRun * (configs.count() + modes.count()); | 2320 int expectedNumberOfTests = gmsRun * (configs.count() + modes.count()); |
|
epoger
2014/01/08 20:48:55
expectedNumberOfTests should now be calculated dif
| |
| 2321 | 2321 |
| 2322 // Output summary to stdout. | 2322 // Output summary to stdout. |
|
epoger
2014/01/08 20:48:55
As expectedNumberOfTests indicates, this change wi
| |
| 2323 if (FLAGS_verbose) { | 2323 if (FLAGS_verbose) { |
| 2324 gm_fprintf(stdout, "Ran %d GMs\n", gmsRun); | 2324 gm_fprintf(stdout, "Ran %d GMs\n", gmsRun); |
|
epoger
2014/01/08 20:48:55
This change will modify the gm self-test results.
| |
| 2325 gm_fprintf(stdout, "... over %2d configs [%s]\n", configs.count(), | 2325 gm_fprintf(stdout, "... over %2d configs [%s]\n", configs.count(), |
| 2326 list_all_config_names(configs).c_str()); | 2326 list_all_config_names(configs).c_str()); |
| 2327 gm_fprintf(stdout, "... and %2d modes [%s]\n", modes.count(), list_al l(modes).c_str()); | 2327 gm_fprintf(stdout, "... and %2d modes [%s]\n", modes.count(), list_al l(modes).c_str()); |
| 2328 gm_fprintf(stdout, "... so there should be a total of %d tests.\n", expe ctedNumberOfTests); | 2328 gm_fprintf(stdout, "... so there should be a total of %d tests.\n", expe ctedNumberOfTests); |
| 2329 } | 2329 } |
| 2330 gmmain.ListErrors(FLAGS_verbose); | 2330 gmmain.ListErrors(FLAGS_verbose); |
| 2331 | 2331 |
| 2332 // TODO(epoger): Enable this check for Android, too, once we resolve | 2332 // TODO(epoger): Enable this check for Android, too, once we resolve |
| 2333 // https://code.google.com/p/skia/issues/detail?id=1222 | 2333 // https://code.google.com/p/skia/issues/detail?id=1222 |
| 2334 // ('GM is unexpectedly skipping tests on Android') | 2334 // ('GM is unexpectedly skipping tests on Android') |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2376 if (FLAGS_forceBWtext) { | 2376 if (FLAGS_forceBWtext) { |
| 2377 canvas->setDrawFilter(SkNEW(BWTextDrawFilter))->unref(); | 2377 canvas->setDrawFilter(SkNEW(BWTextDrawFilter))->unref(); |
| 2378 } | 2378 } |
| 2379 } | 2379 } |
| 2380 | 2380 |
| 2381 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 2381 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
| 2382 int main(int argc, char * const argv[]) { | 2382 int main(int argc, char * const argv[]) { |
| 2383 return tool_main(argc, (char**) argv); | 2383 return tool_main(argc, (char**) argv); |
| 2384 } | 2384 } |
| 2385 #endif | 2385 #endif |
| OLD | NEW |