DMSrcSink.cpp 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009
  1. /*
  2. * Copyright 2015 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "dm/DMSrcSink.h"
  8. #include "include/codec/SkAndroidCodec.h"
  9. #include "include/codec/SkCodec.h"
  10. #include "include/core/SkColorSpace.h"
  11. #include "include/core/SkData.h"
  12. #include "include/core/SkDeferredDisplayListRecorder.h"
  13. #include "include/core/SkDocument.h"
  14. #include "include/core/SkExecutor.h"
  15. #include "include/core/SkImageGenerator.h"
  16. #include "include/core/SkMallocPixelRef.h"
  17. #include "include/core/SkMultiPictureDraw.h"
  18. #include "include/core/SkPictureRecorder.h"
  19. #include "include/core/SkStream.h"
  20. #include "include/core/SkSurface.h"
  21. #include "include/core/SkSurfaceCharacterization.h"
  22. #include "include/docs/SkPDFDocument.h"
  23. #include "include/gpu/GrBackendSurface.h"
  24. #include "include/ports/SkImageGeneratorCG.h"
  25. #include "include/ports/SkImageGeneratorWIC.h"
  26. #include "include/private/SkImageInfoPriv.h"
  27. #include "include/private/SkTLogic.h"
  28. #include "include/third_party/skcms/skcms.h"
  29. #include "include/utils/SkNullCanvas.h"
  30. #include "include/utils/SkRandom.h"
  31. #include "src/codec/SkCodecImageGenerator.h"
  32. #include "src/codec/SkSwizzler.h"
  33. #include "src/core/SkAutoMalloc.h"
  34. #include "src/core/SkAutoPixmapStorage.h"
  35. #include "src/core/SkMakeUnique.h"
  36. #include "src/core/SkOSFile.h"
  37. #include "src/core/SkOpts.h"
  38. #include "src/core/SkPictureCommon.h"
  39. #include "src/core/SkPictureData.h"
  40. #include "src/core/SkRecordDraw.h"
  41. #include "src/core/SkRecorder.h"
  42. #include "src/core/SkTaskGroup.h"
  43. #include "src/gpu/GrContextPriv.h"
  44. #include "src/gpu/GrGpu.h"
  45. #include "src/utils/SkMultiPictureDocumentPriv.h"
  46. #include "src/utils/SkOSPath.h"
  47. #include "tools/DDLPromiseImageHelper.h"
  48. #include "tools/DDLTileHelper.h"
  49. #include "tools/Resources.h"
  50. #include "tools/debugger/DebugCanvas.h"
  51. #include "tools/gpu/MemoryCache.h"
  52. #if defined(SK_BUILD_FOR_WIN)
  53. #include "include/docs/SkXPSDocument.h"
  54. #include "src/utils/win/SkAutoCoInitialize.h"
  55. #include "src/utils/win/SkHRESULT.h"
  56. #include "src/utils/win/SkTScopedComPtr.h"
  57. #include <XpsObjectModel.h>
  58. #endif
  59. #if defined(SK_ENABLE_SKOTTIE)
  60. #include "modules/skottie/include/Skottie.h"
  61. #include "modules/skottie/utils/SkottieUtils.h"
  62. #endif
  63. #if defined(SK_XML)
  64. #include "experimental/svg/model/SkSVGDOM.h"
  65. #include "include/svg/SkSVGCanvas.h"
  66. #include "src/xml/SkXMLWriter.h"
  67. #endif
  68. #include "tests/TestUtils.h"
  69. #include <cmath>
  70. #include <functional>
  71. static DEFINE_bool(multiPage, false,
  72. "For document-type backends, render the source into multiple pages");
  73. static DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?");
  74. DECLARE_int(gpuThreads);
  75. using sk_gpu_test::GrContextFactory;
  76. namespace DM {
  77. GMSrc::GMSrc(skiagm::GMFactory factory) : fFactory(factory) {}
  78. Error GMSrc::draw(SkCanvas* canvas) const {
  79. std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
  80. SkString errorMsg;
  81. skiagm::DrawResult drawResult = gm->draw(canvas, &errorMsg);
  82. if (skiagm::DrawResult::kSkip == drawResult) {
  83. return Error::Nonfatal(std::move(errorMsg)); // Cause this test to be skipped.
  84. }
  85. return errorMsg;
  86. }
  87. SkISize GMSrc::size() const {
  88. std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
  89. return gm->getISize();
  90. }
  91. Name GMSrc::name() const {
  92. std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
  93. return gm->getName();
  94. }
  95. void GMSrc::modifyGrContextOptions(GrContextOptions* options) const {
  96. std::unique_ptr<skiagm::GM> gm(fFactory(nullptr));
  97. gm->modifyGrContextOptions(options);
  98. }
  99. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  100. BRDSrc::BRDSrc(Path path, Mode mode, CodecSrc::DstColorType dstColorType, uint32_t sampleSize)
  101. : fPath(path)
  102. , fMode(mode)
  103. , fDstColorType(dstColorType)
  104. , fSampleSize(sampleSize)
  105. {}
  106. bool BRDSrc::veto(SinkFlags flags) const {
  107. // No need to test to non-raster or indirect backends.
  108. return flags.type != SinkFlags::kRaster
  109. || flags.approach != SinkFlags::kDirect;
  110. }
  111. static SkBitmapRegionDecoder* create_brd(Path path) {
  112. sk_sp<SkData> encoded(SkData::MakeFromFileName(path.c_str()));
  113. if (!encoded) {
  114. return nullptr;
  115. }
  116. return SkBitmapRegionDecoder::Create(encoded, SkBitmapRegionDecoder::kAndroidCodec_Strategy);
  117. }
  118. static inline void alpha8_to_gray8(SkBitmap* bitmap) {
  119. // Android requires kGray8 bitmaps to be tagged as kAlpha8. Here we convert
  120. // them back to kGray8 so our test framework can draw them correctly.
  121. if (kAlpha_8_SkColorType == bitmap->info().colorType()) {
  122. SkImageInfo newInfo = bitmap->info().makeColorType(kGray_8_SkColorType)
  123. .makeAlphaType(kOpaque_SkAlphaType);
  124. *const_cast<SkImageInfo*>(&bitmap->info()) = newInfo;
  125. }
  126. }
  127. Error BRDSrc::draw(SkCanvas* canvas) const {
  128. SkColorType colorType = canvas->imageInfo().colorType();
  129. if (kRGB_565_SkColorType == colorType &&
  130. CodecSrc::kGetFromCanvas_DstColorType != fDstColorType) {
  131. return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
  132. }
  133. switch (fDstColorType) {
  134. case CodecSrc::kGetFromCanvas_DstColorType:
  135. break;
  136. case CodecSrc::kGrayscale_Always_DstColorType:
  137. colorType = kGray_8_SkColorType;
  138. break;
  139. default:
  140. SkASSERT(false);
  141. break;
  142. }
  143. std::unique_ptr<SkBitmapRegionDecoder> brd(create_brd(fPath));
  144. if (nullptr == brd.get()) {
  145. return Error::Nonfatal(SkStringPrintf("Could not create brd for %s.", fPath.c_str()));
  146. }
  147. auto recommendedCT = brd->computeOutputColorType(colorType);
  148. if (kRGB_565_SkColorType == colorType && recommendedCT != colorType) {
  149. return Error::Nonfatal("Skip decoding non-opaque to 565.");
  150. }
  151. colorType = recommendedCT;
  152. auto colorSpace = brd->computeOutputColorSpace(colorType, nullptr);
  153. const uint32_t width = brd->width();
  154. const uint32_t height = brd->height();
  155. // Visually inspecting very small output images is not necessary.
  156. if ((width / fSampleSize <= 10 || height / fSampleSize <= 10) && 1 != fSampleSize) {
  157. return Error::Nonfatal("Scaling very small images is uninteresting.");
  158. }
  159. switch (fMode) {
  160. case kFullImage_Mode: {
  161. SkBitmap bitmap;
  162. if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, width, height),
  163. fSampleSize, colorType, false, colorSpace)) {
  164. return "Cannot decode (full) region.";
  165. }
  166. alpha8_to_gray8(&bitmap);
  167. canvas->drawBitmap(bitmap, 0, 0);
  168. return "";
  169. }
  170. case kDivisor_Mode: {
  171. const uint32_t divisor = 2;
  172. if (width < divisor || height < divisor) {
  173. return Error::Nonfatal("Divisor is larger than image dimension.");
  174. }
  175. // Use a border to test subsets that extend outside the image.
  176. // We will not allow the border to be larger than the image dimensions. Allowing
  177. // these large borders causes off by one errors that indicate a problem with the
  178. // test suite, not a problem with the implementation.
  179. const uint32_t maxBorder = SkTMin(width, height) / (fSampleSize * divisor);
  180. const uint32_t scaledBorder = SkTMin(5u, maxBorder);
  181. const uint32_t unscaledBorder = scaledBorder * fSampleSize;
  182. // We may need to clear the canvas to avoid uninitialized memory.
  183. // Assume we are scaling a 780x780 image with sampleSize = 8.
  184. // The output image should be 97x97.
  185. // Each subset will be 390x390.
  186. // Each scaled subset be 48x48.
  187. // Four scaled subsets will only fill a 96x96 image.
  188. // The bottom row and last column will not be touched.
  189. // This is an unfortunate result of our rounding rules when scaling.
  190. // Maybe we need to consider testing scaled subsets without trying to
  191. // combine them to match the full scaled image? Or maybe this is the
  192. // best we can do?
  193. canvas->clear(0);
  194. for (uint32_t x = 0; x < divisor; x++) {
  195. for (uint32_t y = 0; y < divisor; y++) {
  196. // Calculate the subset dimensions
  197. uint32_t subsetWidth = width / divisor;
  198. uint32_t subsetHeight = height / divisor;
  199. const int left = x * subsetWidth;
  200. const int top = y * subsetHeight;
  201. // Increase the size of the last subset in each row or column, when the
  202. // divisor does not divide evenly into the image dimensions
  203. subsetWidth += (x + 1 == divisor) ? (width % divisor) : 0;
  204. subsetHeight += (y + 1 == divisor) ? (height % divisor) : 0;
  205. // Increase the size of the subset in order to have a border on each side
  206. const int decodeLeft = left - unscaledBorder;
  207. const int decodeTop = top - unscaledBorder;
  208. const uint32_t decodeWidth = subsetWidth + unscaledBorder * 2;
  209. const uint32_t decodeHeight = subsetHeight + unscaledBorder * 2;
  210. SkBitmap bitmap;
  211. if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(decodeLeft,
  212. decodeTop, decodeWidth, decodeHeight), fSampleSize, colorType, false,
  213. colorSpace)) {
  214. return "Cannot decode region.";
  215. }
  216. alpha8_to_gray8(&bitmap);
  217. canvas->drawBitmapRect(bitmap,
  218. SkRect::MakeXYWH((SkScalar) scaledBorder, (SkScalar) scaledBorder,
  219. (SkScalar) (subsetWidth / fSampleSize),
  220. (SkScalar) (subsetHeight / fSampleSize)),
  221. SkRect::MakeXYWH((SkScalar) (left / fSampleSize),
  222. (SkScalar) (top / fSampleSize),
  223. (SkScalar) (subsetWidth / fSampleSize),
  224. (SkScalar) (subsetHeight / fSampleSize)),
  225. nullptr);
  226. }
  227. }
  228. return "";
  229. }
  230. default:
  231. SkASSERT(false);
  232. return "Error: Should not be reached.";
  233. }
  234. }
  235. SkISize BRDSrc::size() const {
  236. std::unique_ptr<SkBitmapRegionDecoder> brd(create_brd(fPath));
  237. if (brd) {
  238. return {SkTMax(1, brd->width() / (int)fSampleSize),
  239. SkTMax(1, brd->height() / (int)fSampleSize)};
  240. }
  241. return {0, 0};
  242. }
  243. static SkString get_scaled_name(const Path& path, float scale) {
  244. return SkStringPrintf("%s_%.3f", SkOSPath::Basename(path.c_str()).c_str(), scale);
  245. }
  246. Name BRDSrc::name() const {
  247. // We will replicate the names used by CodecSrc so that images can
  248. // be compared in Gold.
  249. if (1 == fSampleSize) {
  250. return SkOSPath::Basename(fPath.c_str());
  251. }
  252. return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
  253. }
  254. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  255. static bool serial_from_path_name(const SkString& path) {
  256. if (!FLAGS_RAW_threading) {
  257. static const char* const exts[] = {
  258. "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw",
  259. "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW",
  260. };
  261. const char* actualExt = strrchr(path.c_str(), '.');
  262. if (actualExt) {
  263. actualExt++;
  264. for (auto* ext : exts) {
  265. if (0 == strcmp(ext, actualExt)) {
  266. return true;
  267. }
  268. }
  269. }
  270. }
  271. return false;
  272. }
  273. CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, SkAlphaType dstAlphaType,
  274. float scale)
  275. : fPath(path)
  276. , fMode(mode)
  277. , fDstColorType(dstColorType)
  278. , fDstAlphaType(dstAlphaType)
  279. , fScale(scale)
  280. , fRunSerially(serial_from_path_name(path))
  281. {}
  282. bool CodecSrc::veto(SinkFlags flags) const {
  283. // Test to direct raster backends (8888 and 565).
  284. return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
  285. }
  286. // Allows us to test decodes to non-native 8888.
  287. static void swap_rb_if_necessary(SkBitmap& bitmap, CodecSrc::DstColorType dstColorType) {
  288. if (CodecSrc::kNonNative8888_Always_DstColorType != dstColorType) {
  289. return;
  290. }
  291. for (int y = 0; y < bitmap.height(); y++) {
  292. uint32_t* row = (uint32_t*) bitmap.getAddr(0, y);
  293. SkOpts::RGBA_to_BGRA(row, row, bitmap.width());
  294. }
  295. }
  296. static bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType,
  297. CodecSrc::DstColorType dstColorType, SkAlphaType dstAlphaType) {
  298. switch (dstColorType) {
  299. case CodecSrc::kGrayscale_Always_DstColorType:
  300. if (kRGB_565_SkColorType == canvasColorType) {
  301. return false;
  302. }
  303. *decodeInfo = decodeInfo->makeColorType(kGray_8_SkColorType);
  304. break;
  305. case CodecSrc::kNonNative8888_Always_DstColorType:
  306. if (kRGB_565_SkColorType == canvasColorType
  307. || kRGBA_F16_SkColorType == canvasColorType) {
  308. return false;
  309. }
  310. #ifdef SK_PMCOLOR_IS_RGBA
  311. *decodeInfo = decodeInfo->makeColorType(kBGRA_8888_SkColorType);
  312. #else
  313. *decodeInfo = decodeInfo->makeColorType(kRGBA_8888_SkColorType);
  314. #endif
  315. break;
  316. default:
  317. if (kRGB_565_SkColorType == canvasColorType &&
  318. kOpaque_SkAlphaType != decodeInfo->alphaType()) {
  319. return false;
  320. }
  321. *decodeInfo = decodeInfo->makeColorType(canvasColorType);
  322. break;
  323. }
  324. *decodeInfo = decodeInfo->makeAlphaType(dstAlphaType);
  325. return true;
  326. }
  327. static void draw_to_canvas(SkCanvas* canvas, const SkImageInfo& info, void* pixels, size_t rowBytes,
  328. CodecSrc::DstColorType dstColorType,
  329. SkScalar left = 0, SkScalar top = 0) {
  330. SkBitmap bitmap;
  331. bitmap.installPixels(info, pixels, rowBytes);
  332. swap_rb_if_necessary(bitmap, dstColorType);
  333. canvas->drawBitmap(bitmap, left, top);
  334. }
  335. // For codec srcs, we want the "draw" step to be a memcpy. Any interesting color space or
  336. // color format conversions should be performed by the codec. Sometimes the output of the
  337. // decode will be in an interesting color space. On our srgb and f16 backends, we need to
  338. // "pretend" that the color space is standard sRGB to avoid triggering color conversion
  339. // at draw time.
  340. static void set_bitmap_color_space(SkImageInfo* info) {
  341. *info = info->makeColorSpace(SkColorSpace::MakeSRGB());
  342. }
  343. Error CodecSrc::draw(SkCanvas* canvas) const {
  344. sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
  345. if (!encoded) {
  346. return SkStringPrintf("Couldn't read %s.", fPath.c_str());
  347. }
  348. std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
  349. if (nullptr == codec.get()) {
  350. return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
  351. }
  352. SkImageInfo decodeInfo = codec->getInfo();
  353. if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType,
  354. fDstAlphaType)) {
  355. return Error::Nonfatal("Skipping uninteresting test.");
  356. }
  357. // Try to scale the image if it is desired
  358. SkISize size = codec->getScaledDimensions(fScale);
  359. if (size == decodeInfo.dimensions() && 1.0f != fScale) {
  360. return Error::Nonfatal("Test without scaling is uninteresting.");
  361. }
  362. // Visually inspecting very small output images is not necessary. We will
  363. // cover these cases in unit testing.
  364. if ((size.width() <= 10 || size.height() <= 10) && 1.0f != fScale) {
  365. return Error::Nonfatal("Scaling very small images is uninteresting.");
  366. }
  367. decodeInfo = decodeInfo.makeWH(size.width(), size.height());
  368. const int bpp = decodeInfo.bytesPerPixel();
  369. const size_t rowBytes = size.width() * bpp;
  370. const size_t safeSize = decodeInfo.computeByteSize(rowBytes);
  371. SkAutoMalloc pixels(safeSize);
  372. SkCodec::Options options;
  373. if (kCodecZeroInit_Mode == fMode) {
  374. memset(pixels.get(), 0, size.height() * rowBytes);
  375. options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
  376. }
  377. SkImageInfo bitmapInfo = decodeInfo;
  378. set_bitmap_color_space(&bitmapInfo);
  379. if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
  380. kBGRA_8888_SkColorType == decodeInfo.colorType()) {
  381. bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
  382. }
  383. switch (fMode) {
  384. case kAnimated_Mode: {
  385. std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
  386. if (frameInfos.size() <= 1) {
  387. return SkStringPrintf("%s is not an animated image.", fPath.c_str());
  388. }
  389. // As in CodecSrc::size(), compute a roughly square grid to draw the frames
  390. // into. "factor" is the number of frames to draw on one row. There will be
  391. // up to "factor" rows as well.
  392. const float root = sqrt((float) frameInfos.size());
  393. const int factor = sk_float_ceil2int(root);
  394. // Used to cache a frame that future frames will depend on.
  395. SkAutoMalloc priorFramePixels;
  396. int cachedFrame = SkCodec::kNoFrame;
  397. for (int i = 0; static_cast<size_t>(i) < frameInfos.size(); i++) {
  398. options.fFrameIndex = i;
  399. // Check for a prior frame
  400. const int reqFrame = frameInfos[i].fRequiredFrame;
  401. if (reqFrame != SkCodec::kNoFrame && reqFrame == cachedFrame
  402. && priorFramePixels.get()) {
  403. // Copy into pixels
  404. memcpy(pixels.get(), priorFramePixels.get(), safeSize);
  405. options.fPriorFrame = reqFrame;
  406. } else {
  407. options.fPriorFrame = SkCodec::kNoFrame;
  408. }
  409. SkCodec::Result result = codec->getPixels(decodeInfo, pixels.get(),
  410. rowBytes, &options);
  411. if (SkCodec::kInvalidInput == result && i > 0) {
  412. // Some of our test images have truncated later frames. Treat that
  413. // the same as incomplete.
  414. result = SkCodec::kIncompleteInput;
  415. }
  416. switch (result) {
  417. case SkCodec::kSuccess:
  418. case SkCodec::kErrorInInput:
  419. case SkCodec::kIncompleteInput: {
  420. // If the next frame depends on this one, store it in priorFrame.
  421. // It is possible that we may discard a frame that future frames depend on,
  422. // but the codec will simply redecode the discarded frame.
  423. // Do this before calling draw_to_canvas, which premultiplies in place. If
  424. // we're decoding to unpremul, we want to pass the unmodified frame to the
  425. // codec for decoding the next frame.
  426. if (static_cast<size_t>(i+1) < frameInfos.size()
  427. && frameInfos[i+1].fRequiredFrame == i) {
  428. memcpy(priorFramePixels.reset(safeSize), pixels.get(), safeSize);
  429. cachedFrame = i;
  430. }
  431. SkAutoCanvasRestore acr(canvas, true);
  432. const int xTranslate = (i % factor) * decodeInfo.width();
  433. const int yTranslate = (i / factor) * decodeInfo.height();
  434. canvas->translate(SkIntToScalar(xTranslate), SkIntToScalar(yTranslate));
  435. draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
  436. if (result != SkCodec::kSuccess) {
  437. return "";
  438. }
  439. break;
  440. }
  441. case SkCodec::kInvalidConversion:
  442. if (i > 0 && (decodeInfo.colorType() == kRGB_565_SkColorType)) {
  443. return Error::Nonfatal(SkStringPrintf(
  444. "Cannot decode frame %i to 565 (%s).", i, fPath.c_str()));
  445. }
  446. // Fall through.
  447. default:
  448. return SkStringPrintf("Couldn't getPixels for frame %i in %s.",
  449. i, fPath.c_str());
  450. }
  451. }
  452. break;
  453. }
  454. case kCodecZeroInit_Mode:
  455. case kCodec_Mode: {
  456. switch (codec->getPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
  457. case SkCodec::kSuccess:
  458. // We consider these to be valid, since we should still decode what is
  459. // available.
  460. case SkCodec::kErrorInInput:
  461. case SkCodec::kIncompleteInput:
  462. break;
  463. default:
  464. // Everything else is considered a failure.
  465. return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
  466. }
  467. draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
  468. break;
  469. }
  470. case kScanline_Mode: {
  471. void* dst = pixels.get();
  472. uint32_t height = decodeInfo.height();
  473. const bool useIncremental = [this]() {
  474. auto exts = { "png", "PNG", "gif", "GIF" };
  475. for (auto ext : exts) {
  476. if (fPath.endsWith(ext)) {
  477. return true;
  478. }
  479. }
  480. return false;
  481. }();
  482. // ico may use the old scanline method or the new one, depending on whether it
  483. // internally holds a bmp or a png.
  484. const bool ico = fPath.endsWith("ico");
  485. bool useOldScanlineMethod = !useIncremental && !ico;
  486. if (useIncremental || ico) {
  487. if (SkCodec::kSuccess == codec->startIncrementalDecode(decodeInfo, dst,
  488. rowBytes, &options)) {
  489. int rowsDecoded;
  490. auto result = codec->incrementalDecode(&rowsDecoded);
  491. if (SkCodec::kIncompleteInput == result || SkCodec::kErrorInInput == result) {
  492. codec->fillIncompleteImage(decodeInfo, dst, rowBytes,
  493. SkCodec::kNo_ZeroInitialized, height,
  494. rowsDecoded);
  495. }
  496. } else {
  497. if (useIncremental) {
  498. // Error: These should support incremental decode.
  499. return "Could not start incremental decode";
  500. }
  501. // Otherwise, this is an ICO. Since incremental failed, it must contain a BMP,
  502. // which should work via startScanlineDecode
  503. useOldScanlineMethod = true;
  504. }
  505. }
  506. if (useOldScanlineMethod) {
  507. if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)) {
  508. return "Could not start scanline decoder";
  509. }
  510. // We do not need to check the return value. On an incomplete
  511. // image, memory will be filled with a default value.
  512. codec->getScanlines(dst, height, rowBytes);
  513. }
  514. draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, fDstColorType);
  515. break;
  516. }
  517. case kStripe_Mode: {
  518. const int height = decodeInfo.height();
  519. // This value is chosen arbitrarily. We exercise more cases by choosing a value that
  520. // does not align with image blocks.
  521. const int stripeHeight = 37;
  522. const int numStripes = (height + stripeHeight - 1) / stripeHeight;
  523. void* dst = pixels.get();
  524. // Decode odd stripes
  525. if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &options)) {
  526. return "Could not start scanline decoder";
  527. }
  528. // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
  529. // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
  530. // to run this test for image types that do not have this scanline ordering.
  531. // We only run this on Jpeg, which is always kTopDown.
  532. SkASSERT(SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder());
  533. for (int i = 0; i < numStripes; i += 2) {
  534. // Skip a stripe
  535. const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight);
  536. codec->skipScanlines(linesToSkip);
  537. // Read a stripe
  538. const int startY = (i + 1) * stripeHeight;
  539. const int linesToRead = SkTMin(stripeHeight, height - startY);
  540. if (linesToRead > 0) {
  541. codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
  542. rowBytes);
  543. }
  544. }
  545. // Decode even stripes
  546. const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo);
  547. if (SkCodec::kSuccess != startResult) {
  548. return "Failed to restart scanline decoder with same parameters.";
  549. }
  550. for (int i = 0; i < numStripes; i += 2) {
  551. // Read a stripe
  552. const int startY = i * stripeHeight;
  553. const int linesToRead = SkTMin(stripeHeight, height - startY);
  554. codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
  555. rowBytes);
  556. // Skip a stripe
  557. const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
  558. if (linesToSkip > 0) {
  559. codec->skipScanlines(linesToSkip);
  560. }
  561. }
  562. draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, fDstColorType);
  563. break;
  564. }
  565. case kCroppedScanline_Mode: {
  566. const int width = decodeInfo.width();
  567. const int height = decodeInfo.height();
  568. // This value is chosen because, as we move across the image, it will sometimes
  569. // align with the jpeg block sizes and it will sometimes not. This allows us
  570. // to test interestingly different code paths in the implementation.
  571. const int tileSize = 36;
  572. SkIRect subset;
  573. for (int x = 0; x < width; x += tileSize) {
  574. subset = SkIRect::MakeXYWH(x, 0, SkTMin(tileSize, width - x), height);
  575. options.fSubset = &subset;
  576. if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &options)) {
  577. return "Could not start scanline decoder.";
  578. }
  579. codec->getScanlines(SkTAddOffset<void>(pixels.get(), x * bpp), height, rowBytes);
  580. }
  581. draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
  582. break;
  583. }
  584. case kSubset_Mode: {
  585. // Arbitrarily choose a divisor.
  586. int divisor = 2;
  587. // Total width/height of the image.
  588. const int W = codec->getInfo().width();
  589. const int H = codec->getInfo().height();
  590. if (divisor > W || divisor > H) {
  591. return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divisor %d is too big "
  592. "for %s with dimensions (%d x %d)", divisor,
  593. fPath.c_str(), W, H));
  594. }
  595. // subset dimensions
  596. // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
  597. const int w = SkAlign2(W / divisor);
  598. const int h = SkAlign2(H / divisor);
  599. SkIRect subset;
  600. options.fSubset = &subset;
  601. SkBitmap subsetBm;
  602. // We will reuse pixel memory from bitmap.
  603. void* dst = pixels.get();
  604. // Keep track of left and top (for drawing subsetBm into canvas). We could use
  605. // fScale * x and fScale * y, but we want integers such that the next subset will start
  606. // where the last one ended. So we'll add decodeInfo.width() and height().
  607. int left = 0;
  608. for (int x = 0; x < W; x += w) {
  609. int top = 0;
  610. for (int y = 0; y < H; y+= h) {
  611. // Do not make the subset go off the edge of the image.
  612. const int preScaleW = SkTMin(w, W - x);
  613. const int preScaleH = SkTMin(h, H - y);
  614. subset.setXYWH(x, y, preScaleW, preScaleH);
  615. // And scale
  616. // FIXME: Should we have a version of getScaledDimensions that takes a subset
  617. // into account?
  618. const int scaledW = SkTMax(1, SkScalarRoundToInt(preScaleW * fScale));
  619. const int scaledH = SkTMax(1, SkScalarRoundToInt(preScaleH * fScale));
  620. decodeInfo = decodeInfo.makeWH(scaledW, scaledH);
  621. SkImageInfo subsetBitmapInfo = bitmapInfo.makeWH(scaledW, scaledH);
  622. size_t subsetRowBytes = subsetBitmapInfo.minRowBytes();
  623. const SkCodec::Result result = codec->getPixels(decodeInfo, dst, subsetRowBytes,
  624. &options);
  625. switch (result) {
  626. case SkCodec::kSuccess:
  627. case SkCodec::kErrorInInput:
  628. case SkCodec::kIncompleteInput:
  629. break;
  630. default:
  631. return SkStringPrintf("subset codec failed to decode (%d, %d, %d, %d) "
  632. "from %s with dimensions (%d x %d)\t error %d",
  633. x, y, decodeInfo.width(), decodeInfo.height(),
  634. fPath.c_str(), W, H, result);
  635. }
  636. draw_to_canvas(canvas, subsetBitmapInfo, dst, subsetRowBytes, fDstColorType,
  637. SkIntToScalar(left), SkIntToScalar(top));
  638. // translate by the scaled height.
  639. top += decodeInfo.height();
  640. }
  641. // translate by the scaled width.
  642. left += decodeInfo.width();
  643. }
  644. return "";
  645. }
  646. default:
  647. SkASSERT(false);
  648. return "Invalid fMode";
  649. }
  650. return "";
  651. }
  652. SkISize CodecSrc::size() const {
  653. sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
  654. std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
  655. if (nullptr == codec) {
  656. return {0, 0};
  657. }
  658. auto imageSize = codec->getScaledDimensions(fScale);
  659. if (fMode == kAnimated_Mode) {
  660. // We'll draw one of each frame, so make it big enough to hold them all
  661. // in a grid. The grid will be roughly square, with "factor" frames per
  662. // row and up to "factor" rows.
  663. const size_t count = codec->getFrameInfo().size();
  664. const float root = sqrt((float) count);
  665. const int factor = sk_float_ceil2int(root);
  666. imageSize.fWidth = imageSize.fWidth * factor;
  667. imageSize.fHeight = imageSize.fHeight * sk_float_ceil2int((float) count / (float) factor);
  668. }
  669. return imageSize;
  670. }
  671. Name CodecSrc::name() const {
  672. if (1.0f == fScale) {
  673. Name name = SkOSPath::Basename(fPath.c_str());
  674. if (fMode == kAnimated_Mode) {
  675. name.append("_animated");
  676. }
  677. return name;
  678. }
  679. SkASSERT(fMode != kAnimated_Mode);
  680. return get_scaled_name(fPath, fScale);
  681. }
  682. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  683. AndroidCodecSrc::AndroidCodecSrc(Path path, CodecSrc::DstColorType dstColorType,
  684. SkAlphaType dstAlphaType, int sampleSize)
  685. : fPath(path)
  686. , fDstColorType(dstColorType)
  687. , fDstAlphaType(dstAlphaType)
  688. , fSampleSize(sampleSize)
  689. , fRunSerially(serial_from_path_name(path))
  690. {}
  691. bool AndroidCodecSrc::veto(SinkFlags flags) const {
  692. // No need to test decoding to non-raster or indirect backend.
  693. return flags.type != SinkFlags::kRaster
  694. || flags.approach != SinkFlags::kDirect;
  695. }
  696. Error AndroidCodecSrc::draw(SkCanvas* canvas) const {
  697. sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
  698. if (!encoded) {
  699. return SkStringPrintf("Couldn't read %s.", fPath.c_str());
  700. }
  701. std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromData(encoded));
  702. if (nullptr == codec) {
  703. return SkStringPrintf("Couldn't create android codec for %s.", fPath.c_str());
  704. }
  705. SkImageInfo decodeInfo = codec->getInfo();
  706. if (!get_decode_info(&decodeInfo, canvas->imageInfo().colorType(), fDstColorType,
  707. fDstAlphaType)) {
  708. return Error::Nonfatal("Skipping uninteresting test.");
  709. }
  710. // Scale the image if it is desired.
  711. SkISize size = codec->getSampledDimensions(fSampleSize);
  712. // Visually inspecting very small output images is not necessary. We will
  713. // cover these cases in unit testing.
  714. if ((size.width() <= 10 || size.height() <= 10) && 1 != fSampleSize) {
  715. return Error::Nonfatal("Scaling very small images is uninteresting.");
  716. }
  717. decodeInfo = decodeInfo.makeWH(size.width(), size.height());
  718. int bpp = decodeInfo.bytesPerPixel();
  719. size_t rowBytes = size.width() * bpp;
  720. SkAutoMalloc pixels(size.height() * rowBytes);
  721. SkBitmap bitmap;
  722. SkImageInfo bitmapInfo = decodeInfo;
  723. set_bitmap_color_space(&bitmapInfo);
  724. if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
  725. kBGRA_8888_SkColorType == decodeInfo.colorType()) {
  726. bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
  727. }
  728. // Create options for the codec.
  729. SkAndroidCodec::AndroidOptions options;
  730. options.fSampleSize = fSampleSize;
  731. switch (codec->getAndroidPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
  732. case SkCodec::kSuccess:
  733. case SkCodec::kErrorInInput:
  734. case SkCodec::kIncompleteInput:
  735. break;
  736. default:
  737. return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
  738. }
  739. draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, fDstColorType);
  740. return "";
  741. }
  742. SkISize AndroidCodecSrc::size() const {
  743. sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
  744. std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::MakeFromData(encoded));
  745. if (nullptr == codec) {
  746. return {0, 0};
  747. }
  748. return codec->getSampledDimensions(fSampleSize);
  749. }
  750. Name AndroidCodecSrc::name() const {
  751. // We will replicate the names used by CodecSrc so that images can
  752. // be compared in Gold.
  753. if (1 == fSampleSize) {
  754. return SkOSPath::Basename(fPath.c_str());
  755. }
  756. return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
  757. }
  758. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  759. ImageGenSrc::ImageGenSrc(Path path, Mode mode, SkAlphaType alphaType, bool isGpu)
  760. : fPath(path)
  761. , fMode(mode)
  762. , fDstAlphaType(alphaType)
  763. , fIsGpu(isGpu)
  764. , fRunSerially(serial_from_path_name(path))
  765. {}
  766. bool ImageGenSrc::veto(SinkFlags flags) const {
  767. if (fIsGpu) {
  768. // MSAA runs tend to run out of memory and tests the same code paths as regular gpu configs.
  769. return flags.type != SinkFlags::kGPU || flags.approach != SinkFlags::kDirect ||
  770. flags.multisampled == SinkFlags::kMultisampled;
  771. }
  772. return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
  773. }
  774. Error ImageGenSrc::draw(SkCanvas* canvas) const {
  775. if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
  776. return Error::Nonfatal("Uninteresting to test image generator to 565.");
  777. }
  778. sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
  779. if (!encoded) {
  780. return SkStringPrintf("Couldn't read %s.", fPath.c_str());
  781. }
  782. #if defined(SK_BUILD_FOR_WIN)
  783. // Initialize COM in order to test with WIC.
  784. SkAutoCoInitialize com;
  785. if (!com.succeeded()) {
  786. return "Could not initialize COM.";
  787. }
  788. #endif
  789. std::unique_ptr<SkImageGenerator> gen(nullptr);
  790. switch (fMode) {
  791. case kCodec_Mode:
  792. gen = SkCodecImageGenerator::MakeFromEncodedCodec(encoded);
  793. if (!gen) {
  794. return "Could not create codec image generator.";
  795. }
  796. break;
  797. case kPlatform_Mode: {
  798. #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
  799. gen = SkImageGeneratorCG::MakeFromEncodedCG(encoded);
  800. #elif defined(SK_BUILD_FOR_WIN)
  801. gen = SkImageGeneratorWIC::MakeFromEncodedWIC(encoded);
  802. #endif
  803. if (!gen) {
  804. return "Could not create platform image generator.";
  805. }
  806. break;
  807. }
  808. default:
  809. SkASSERT(false);
  810. return "Invalid image generator mode";
  811. }
  812. // Test deferred decoding path on GPU
  813. if (fIsGpu) {
  814. sk_sp<SkImage> image(SkImage::MakeFromGenerator(std::move(gen), nullptr));
  815. if (!image) {
  816. return "Could not create image from codec image generator.";
  817. }
  818. canvas->drawImage(image, 0, 0);
  819. return "";
  820. }
  821. // Test various color and alpha types on CPU
  822. SkImageInfo decodeInfo = gen->getInfo().makeAlphaType(fDstAlphaType);
  823. int bpp = decodeInfo.bytesPerPixel();
  824. size_t rowBytes = decodeInfo.width() * bpp;
  825. SkAutoMalloc pixels(decodeInfo.height() * rowBytes);
  826. if (!gen->getPixels(decodeInfo, pixels.get(), rowBytes)) {
  827. SkString err =
  828. SkStringPrintf("Image generator could not getPixels() for %s\n", fPath.c_str());
  829. #if defined(SK_BUILD_FOR_WIN)
  830. if (kPlatform_Mode == fMode) {
  831. // Do not issue a fatal error for WIC flakiness.
  832. return Error::Nonfatal(err);
  833. }
  834. #endif
  835. return err;
  836. }
  837. set_bitmap_color_space(&decodeInfo);
  838. draw_to_canvas(canvas, decodeInfo, pixels.get(), rowBytes,
  839. CodecSrc::kGetFromCanvas_DstColorType);
  840. return "";
  841. }
  842. SkISize ImageGenSrc::size() const {
  843. sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
  844. std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
  845. if (nullptr == codec) {
  846. return {0, 0};
  847. }
  848. return codec->getInfo().dimensions();
  849. }
  850. Name ImageGenSrc::name() const {
  851. return SkOSPath::Basename(fPath.c_str());
  852. }
  853. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  854. ColorCodecSrc::ColorCodecSrc(Path path, bool decode_to_dst) : fPath(path)
  855. , fDecodeToDst(decode_to_dst) {}
  856. bool ColorCodecSrc::veto(SinkFlags flags) const {
  857. // Test to direct raster backends (8888 and 565).
  858. return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
  859. }
  860. Error ColorCodecSrc::draw(SkCanvas* canvas) const {
  861. sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
  862. if (!encoded) {
  863. return SkStringPrintf("Couldn't read %s.", fPath.c_str());
  864. }
  865. std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
  866. if (nullptr == codec) {
  867. return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
  868. }
  869. SkImageInfo info = codec->getInfo();
  870. if (fDecodeToDst) {
  871. info = canvas->imageInfo().makeWH(info.width(),
  872. info.height());
  873. }
  874. SkBitmap bitmap;
  875. if (!bitmap.tryAllocPixels(info)) {
  876. return SkStringPrintf("Image(%s) is too large (%d x %d)",
  877. fPath.c_str(), info.width(), info.height());
  878. }
  879. switch (auto r = codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes())) {
  880. case SkCodec::kSuccess:
  881. case SkCodec::kErrorInInput:
  882. case SkCodec::kIncompleteInput:
  883. canvas->drawBitmap(bitmap, 0,0);
  884. return "";
  885. case SkCodec::kInvalidConversion:
  886. // TODO(mtklein): why are there formats we can't decode to?
  887. return Error::Nonfatal("SkCodec can't decode to this format.");
  888. default:
  889. return SkStringPrintf("Couldn't getPixels %s. Error code %d", fPath.c_str(), r);
  890. }
  891. }
  892. SkISize ColorCodecSrc::size() const {
  893. sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
  894. std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(encoded));
  895. if (nullptr == codec) {
  896. return {0, 0};
  897. }
  898. return {codec->getInfo().width(), codec->getInfo().height()};
  899. }
  900. Name ColorCodecSrc::name() const {
  901. return SkOSPath::Basename(fPath.c_str());
  902. }
  903. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  904. static DEFINE_int(skpViewportSize, 1000,
  905. "Width & height of the viewport used to crop skp rendering.");
  906. SKPSrc::SKPSrc(Path path) : fPath(path) { }
  907. Error SKPSrc::draw(SkCanvas* canvas) const {
  908. std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(fPath.c_str());
  909. if (!stream) {
  910. return SkStringPrintf("Couldn't read %s.", fPath.c_str());
  911. }
  912. sk_sp<SkPicture> pic(SkPicture::MakeFromStream(stream.get()));
  913. if (!pic) {
  914. return SkStringPrintf("Couldn't parse file %s.", fPath.c_str());
  915. }
  916. stream = nullptr; // Might as well drop this when we're done with it.
  917. canvas->clipRect(SkRect::MakeWH(FLAGS_skpViewportSize, FLAGS_skpViewportSize));
  918. canvas->drawPicture(pic);
  919. return "";
  920. }
  921. static SkRect get_cull_rect_for_skp(const char* path) {
  922. std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(path);
  923. if (!stream) {
  924. return SkRect::MakeEmpty();
  925. }
  926. SkPictInfo info;
  927. if (!SkPicture_StreamIsSKP(stream.get(), &info)) {
  928. return SkRect::MakeEmpty();
  929. }
  930. return info.fCullRect;
  931. }
  932. SkISize SKPSrc::size() const {
  933. SkRect viewport = get_cull_rect_for_skp(fPath.c_str());
  934. if (!viewport.intersect((SkRect::MakeWH(FLAGS_skpViewportSize, FLAGS_skpViewportSize)))) {
  935. return {0, 0};
  936. }
  937. return viewport.roundOut().size();
  938. }
  939. Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
  940. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  941. BisectSrc::BisectSrc(Path path, const char* trail) : INHERITED(path), fTrail(trail) {}
  942. Error BisectSrc::draw(SkCanvas* canvas) const {
  943. struct FoundPath {
  944. SkPath fPath;
  945. SkPaint fPaint;
  946. SkMatrix fViewMatrix;
  947. };
  948. // This subclass of SkCanvas just extracts all the SkPaths (drawn via drawPath) from an SKP.
  949. class PathFindingCanvas : public SkCanvas {
  950. public:
  951. PathFindingCanvas(int width, int height) : SkCanvas(width, height, nullptr) {}
  952. const SkTArray<FoundPath>& foundPaths() const { return fFoundPaths; }
  953. private:
  954. void onDrawPath(const SkPath& path, const SkPaint& paint) override {
  955. fFoundPaths.push_back() = {path, paint, this->getTotalMatrix()};
  956. }
  957. SkTArray<FoundPath> fFoundPaths;
  958. };
  959. PathFindingCanvas pathFinder(canvas->getBaseLayerSize().width(),
  960. canvas->getBaseLayerSize().height());
  961. Error err = this->INHERITED::draw(&pathFinder);
  962. if (!err.isEmpty()) {
  963. return err;
  964. }
  965. int start = 0, end = pathFinder.foundPaths().count();
  966. for (const char* ch = fTrail.c_str(); *ch; ++ch) {
  967. int midpt = (start + end) / 2;
  968. if ('l' == *ch) {
  969. start = midpt;
  970. } else if ('r' == *ch) {
  971. end = midpt;
  972. }
  973. }
  974. for (int i = start; i < end; ++i) {
  975. const FoundPath& path = pathFinder.foundPaths()[i];
  976. SkAutoCanvasRestore acr(canvas, true);
  977. canvas->concat(path.fViewMatrix);
  978. canvas->drawPath(path.fPath, path.fPaint);
  979. }
  980. return "";
  981. }
  982. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  983. #if defined(SK_ENABLE_SKOTTIE)
  984. SkottieSrc::SkottieSrc(Path path) : fPath(std::move(path)) {}
  985. Error SkottieSrc::draw(SkCanvas* canvas) const {
  986. auto animation = skottie::Animation::Builder()
  987. .setResourceProvider(
  988. skottie_utils::FileResourceProvider::Make(SkOSPath::Dirname(fPath.c_str())))
  989. .makeFromFile(fPath.c_str());
  990. if (!animation) {
  991. return SkStringPrintf("Unable to parse file: %s", fPath.c_str());
  992. }
  993. canvas->drawColor(SK_ColorWHITE);
  994. const auto t_rate = 1.0f / (kTileCount * kTileCount - 1);
  995. // Draw the frames in a shuffled order to exercise non-linear
  996. // frame progression. The film strip will still be in order left-to-right,
  997. // top-down, just not drawn in that order.
  998. static constexpr int frameOrder[] = { 4, 0, 3, 1, 2 };
  999. static_assert(SK_ARRAY_COUNT(frameOrder) == kTileCount, "");
  1000. for (int i = 0; i < kTileCount; ++i) {
  1001. const SkScalar y = frameOrder[i] * kTileSize;
  1002. for (int j = 0; j < kTileCount; ++j) {
  1003. const SkScalar x = frameOrder[j] * kTileSize;
  1004. SkRect dest = SkRect::MakeXYWH(x, y, kTileSize, kTileSize);
  1005. const auto t = t_rate * (frameOrder[i] * kTileCount + frameOrder[j]);
  1006. {
  1007. SkAutoCanvasRestore acr(canvas, true);
  1008. canvas->clipRect(dest, true);
  1009. canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(animation->size()),
  1010. dest,
  1011. SkMatrix::kCenter_ScaleToFit));
  1012. animation->seek(t);
  1013. animation->render(canvas);
  1014. }
  1015. }
  1016. }
  1017. return "";
  1018. }
  1019. SkISize SkottieSrc::size() const {
  1020. return SkISize::Make(kTargetSize, kTargetSize);
  1021. }
  1022. Name SkottieSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
  1023. bool SkottieSrc::veto(SinkFlags flags) const {
  1024. // No need to test to non-(raster||gpu||vector) or indirect backends.
  1025. bool type_ok = flags.type == SinkFlags::kRaster
  1026. || flags.type == SinkFlags::kGPU
  1027. || flags.type == SinkFlags::kVector;
  1028. return !type_ok || flags.approach != SinkFlags::kDirect;
  1029. }
  1030. #endif
  1031. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1032. #if defined(SK_XML)
  1033. // Used when the image doesn't have an intrinsic size.
  1034. static const SkSize kDefaultSVGSize = {1000, 1000};
  1035. // Used to force-scale tiny fixed-size images.
  1036. static const SkSize kMinimumSVGSize = {128, 128};
  1037. SVGSrc::SVGSrc(Path path)
  1038. : fName(SkOSPath::Basename(path.c_str()))
  1039. , fScale(1) {
  1040. sk_sp<SkData> data(SkData::MakeFromFileName(path.c_str()));
  1041. if (!data) {
  1042. return;
  1043. }
  1044. SkMemoryStream stream(std::move(data));
  1045. fDom = SkSVGDOM::MakeFromStream(stream);
  1046. if (!fDom) {
  1047. return;
  1048. }
  1049. const SkSize& sz = fDom->containerSize();
  1050. if (sz.isEmpty()) {
  1051. // no intrinsic size
  1052. fDom->setContainerSize(kDefaultSVGSize);
  1053. } else {
  1054. fScale = SkTMax(1.f, SkTMax(kMinimumSVGSize.width() / sz.width(),
  1055. kMinimumSVGSize.height() / sz.height()));
  1056. }
  1057. }
  1058. Error SVGSrc::draw(SkCanvas* canvas) const {
  1059. if (!fDom) {
  1060. return SkStringPrintf("Unable to parse file: %s", fName.c_str());
  1061. }
  1062. SkAutoCanvasRestore acr(canvas, true);
  1063. canvas->scale(fScale, fScale);
  1064. fDom->render(canvas);
  1065. return "";
  1066. }
  1067. SkISize SVGSrc::size() const {
  1068. if (!fDom) {
  1069. return {0, 0};
  1070. }
  1071. return SkSize{fDom->containerSize().width() * fScale, fDom->containerSize().height() * fScale}
  1072. .toRound();
  1073. }
  1074. Name SVGSrc::name() const { return fName; }
  1075. bool SVGSrc::veto(SinkFlags flags) const {
  1076. // No need to test to non-(raster||gpu||vector) or indirect backends.
  1077. bool type_ok = flags.type == SinkFlags::kRaster
  1078. || flags.type == SinkFlags::kGPU
  1079. || flags.type == SinkFlags::kVector;
  1080. return !type_ok || flags.approach != SinkFlags::kDirect;
  1081. }
  1082. #endif // defined(SK_XML)
  1083. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1084. MSKPSrc::MSKPSrc(Path path) : fPath(path) {
  1085. std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(fPath.c_str());
  1086. int count = SkMultiPictureDocumentReadPageCount(stream.get());
  1087. if (count > 0) {
  1088. fPages.reset(count);
  1089. (void)SkMultiPictureDocumentReadPageSizes(stream.get(), &fPages[0], fPages.count());
  1090. }
  1091. }
  1092. int MSKPSrc::pageCount() const { return fPages.count(); }
  1093. SkISize MSKPSrc::size() const { return this->size(0); }
  1094. SkISize MSKPSrc::size(int i) const {
  1095. return i >= 0 && i < fPages.count() ? fPages[i].fSize.toCeil() : SkISize{0, 0};
  1096. }
  1097. Error MSKPSrc::draw(SkCanvas* c) const { return this->draw(0, c); }
  1098. Error MSKPSrc::draw(int i, SkCanvas* canvas) const {
  1099. if (this->pageCount() == 0) {
  1100. return SkStringPrintf("Unable to parse MultiPictureDocument file: %s", fPath.c_str());
  1101. }
  1102. if (i >= fPages.count() || i < 0) {
  1103. return SkStringPrintf("MultiPictureDocument page number out of range: %d", i);
  1104. }
  1105. SkPicture* page = fPages[i].fPicture.get();
  1106. if (!page) {
  1107. std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(fPath.c_str());
  1108. if (!stream) {
  1109. return SkStringPrintf("Unable to open file: %s", fPath.c_str());
  1110. }
  1111. if (!SkMultiPictureDocumentRead(stream.get(), &fPages[0], fPages.count())) {
  1112. return SkStringPrintf("SkMultiPictureDocument reader failed on page %d: %s", i,
  1113. fPath.c_str());
  1114. }
  1115. page = fPages[i].fPicture.get();
  1116. }
  1117. canvas->drawPicture(page);
  1118. return "";
  1119. }
  1120. Name MSKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
  1121. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1122. Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
  1123. return src.draw(SkMakeNullCanvas().get());
  1124. }
  1125. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1126. static Error compare_bitmaps(const SkBitmap& reference, const SkBitmap& bitmap) {
  1127. // The dimensions are a property of the Src only, and so should be identical.
  1128. SkASSERT(reference.computeByteSize() == bitmap.computeByteSize());
  1129. if (reference.computeByteSize() != bitmap.computeByteSize()) {
  1130. return "Dimensions don't match reference";
  1131. }
  1132. // All SkBitmaps in DM are tight, so this comparison is easy.
  1133. if (0 != memcmp(reference.getPixels(), bitmap.getPixels(), reference.computeByteSize())) {
  1134. SkString encoded;
  1135. SkString errString("Pixels don't match reference");
  1136. if (bitmap_to_base64_data_uri(reference, &encoded)) {
  1137. errString.append("\nExpected: ");
  1138. errString.append(encoded);
  1139. } else {
  1140. errString.append("\nExpected image failed to encode: ");
  1141. errString.append(encoded);
  1142. }
  1143. if (bitmap_to_base64_data_uri(bitmap, &encoded)) {
  1144. errString.append("\nActual: ");
  1145. errString.append(encoded);
  1146. } else {
  1147. errString.append("\nActual image failed to encode: ");
  1148. errString.append(encoded);
  1149. }
  1150. return errString;
  1151. }
  1152. return "";
  1153. }
  1154. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1155. static DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
  1156. static DEFINE_bool(preAbandonGpuContext, false,
  1157. "Test abandoning the GrContext before running the test.");
  1158. static DEFINE_bool(abandonGpuContext, false,
  1159. "Test abandoning the GrContext after running each test.");
  1160. static DEFINE_bool(releaseAndAbandonGpuContext, false,
  1161. "Test releasing all gpu resources and abandoning the GrContext "
  1162. "after running each test");
  1163. static DEFINE_bool(drawOpClip, false, "Clip each GrDrawOp to its device bounds for testing.");
  1164. static DEFINE_bool(programBinaryCache, true, "Use in-memory program binary cache");
  1165. GPUSink::GPUSink(GrContextFactory::ContextType ct,
  1166. GrContextFactory::ContextOverrides overrides,
  1167. SkCommandLineConfigGpu::SurfType surfType,
  1168. int samples,
  1169. bool diText,
  1170. SkColorType colorType,
  1171. SkAlphaType alphaType,
  1172. sk_sp<SkColorSpace> colorSpace,
  1173. bool threaded,
  1174. const GrContextOptions& grCtxOptions)
  1175. : fContextType(ct)
  1176. , fContextOverrides(overrides)
  1177. , fSurfType(surfType)
  1178. , fSampleCount(samples)
  1179. , fUseDIText(diText)
  1180. , fColorType(colorType)
  1181. , fAlphaType(alphaType)
  1182. , fColorSpace(std::move(colorSpace))
  1183. , fThreaded(threaded)
  1184. , fBaseContextOptions(grCtxOptions) {
  1185. if (FLAGS_programBinaryCache) {
  1186. fBaseContextOptions.fPersistentCache = &fMemoryCache;
  1187. }
  1188. }
  1189. Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream* dstStream, SkString* log) const {
  1190. return this->onDraw(src, dst, dstStream, log, fBaseContextOptions);
  1191. }
  1192. Error GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
  1193. const GrContextOptions& baseOptions) const {
  1194. GrContextOptions grOptions = baseOptions;
  1195. // We don't expect the src to mess with the persistent cache or the executor.
  1196. SkDEBUGCODE(auto cache = grOptions.fPersistentCache);
  1197. SkDEBUGCODE(auto exec = grOptions.fExecutor);
  1198. src.modifyGrContextOptions(&grOptions);
  1199. SkASSERT(cache == grOptions.fPersistentCache);
  1200. SkASSERT(exec == grOptions.fExecutor);
  1201. GrContextFactory factory(grOptions);
  1202. const SkISize size = src.size();
  1203. SkImageInfo info =
  1204. SkImageInfo::Make(size.width(), size.height(), fColorType, fAlphaType, fColorSpace);
  1205. sk_sp<SkSurface> surface;
  1206. GrContext* context = factory.getContextInfo(fContextType, fContextOverrides).grContext();
  1207. const int maxDimension = context->priv().caps()->maxTextureSize();
  1208. if (maxDimension < SkTMax(size.width(), size.height())) {
  1209. return Error::Nonfatal("Src too large to create a texture.\n");
  1210. }
  1211. uint32_t flags = fUseDIText ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag : 0;
  1212. SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
  1213. GrBackendTexture backendTexture;
  1214. GrBackendRenderTarget backendRT;
  1215. switch (fSurfType) {
  1216. case SkCommandLineConfigGpu::SurfType::kDefault:
  1217. surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, fSampleCount,
  1218. &props);
  1219. break;
  1220. case SkCommandLineConfigGpu::SurfType::kBackendTexture:
  1221. backendTexture = context->createBackendTexture(
  1222. info.width(), info.height(), info.colorType(), SkColors::kTransparent,
  1223. GrMipMapped::kNo, GrRenderable::kYes, GrProtected::kNo);
  1224. surface = SkSurface::MakeFromBackendTexture(context, backendTexture,
  1225. kTopLeft_GrSurfaceOrigin, fSampleCount,
  1226. fColorType, info.refColorSpace(), &props);
  1227. break;
  1228. case SkCommandLineConfigGpu::SurfType::kBackendRenderTarget:
  1229. if (1 == fSampleCount) {
  1230. auto colorType = SkColorTypeToGrColorType(info.colorType());
  1231. backendRT = context->priv().getGpu()->createTestingOnlyBackendRenderTarget(
  1232. info.width(), info.height(), colorType);
  1233. surface = SkSurface::MakeFromBackendRenderTarget(
  1234. context, backendRT, kBottomLeft_GrSurfaceOrigin, info.colorType(),
  1235. info.refColorSpace(), &props);
  1236. }
  1237. break;
  1238. }
  1239. if (!surface) {
  1240. return "Could not create a surface.";
  1241. }
  1242. if (FLAGS_preAbandonGpuContext) {
  1243. factory.abandonContexts();
  1244. }
  1245. SkCanvas* canvas = surface->getCanvas();
  1246. Error err = src.draw(canvas);
  1247. if (!err.isEmpty()) {
  1248. return err;
  1249. }
  1250. surface->flush();
  1251. if (FLAGS_gpuStats) {
  1252. canvas->getGrContext()->priv().dumpCacheStats(log);
  1253. canvas->getGrContext()->priv().dumpGpuStats(log);
  1254. }
  1255. if (info.colorType() == kRGB_565_SkColorType || info.colorType() == kARGB_4444_SkColorType ||
  1256. info.colorType() == kRGB_888x_SkColorType) {
  1257. // We don't currently support readbacks into these formats on the GPU backend. Convert to
  1258. // 32 bit.
  1259. info = SkImageInfo::Make(size.width(), size.height(), kRGBA_8888_SkColorType,
  1260. kPremul_SkAlphaType, fColorSpace);
  1261. }
  1262. dst->allocPixels(info);
  1263. canvas->readPixels(*dst, 0, 0);
  1264. if (FLAGS_abandonGpuContext) {
  1265. factory.abandonContexts();
  1266. } else if (FLAGS_releaseAndAbandonGpuContext) {
  1267. factory.releaseResourcesAndAbandonContexts();
  1268. }
  1269. if (!context->abandoned()) {
  1270. surface.reset();
  1271. if (backendTexture.isValid()) {
  1272. context->deleteBackendTexture(backendTexture);
  1273. }
  1274. if (backendRT.isValid()) {
  1275. context->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
  1276. }
  1277. }
  1278. if (grOptions.fPersistentCache) {
  1279. context->storeVkPipelineCacheData();
  1280. }
  1281. return "";
  1282. }
  1283. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1284. GPUThreadTestingSink::GPUThreadTestingSink(GrContextFactory::ContextType ct,
  1285. GrContextFactory::ContextOverrides overrides,
  1286. SkCommandLineConfigGpu::SurfType surfType,
  1287. int samples,
  1288. bool diText,
  1289. SkColorType colorType,
  1290. SkAlphaType alphaType,
  1291. sk_sp<SkColorSpace> colorSpace,
  1292. bool threaded,
  1293. const GrContextOptions& grCtxOptions)
  1294. : INHERITED(ct, overrides, surfType, samples, diText, colorType, alphaType,
  1295. std::move(colorSpace), threaded, grCtxOptions)
  1296. , fExecutor(SkExecutor::MakeFIFOThreadPool(FLAGS_gpuThreads)) {
  1297. SkASSERT(fExecutor);
  1298. }
  1299. Error GPUThreadTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStream,
  1300. SkString* log) const {
  1301. // Draw twice, once with worker threads, and once without. Verify that we get the same result.
  1302. // Also, force us to only use the software path renderer, so we really stress-test the threaded
  1303. // version of that code.
  1304. GrContextOptions contextOptions = this->baseContextOptions();
  1305. contextOptions.fGpuPathRenderers = GpuPathRenderers::kNone;
  1306. contextOptions.fExecutor = fExecutor.get();
  1307. Error err = this->onDraw(src, dst, wStream, log, contextOptions);
  1308. if (!err.isEmpty() || !dst) {
  1309. return err;
  1310. }
  1311. SkBitmap reference;
  1312. SkString refLog;
  1313. SkDynamicMemoryWStream refStream;
  1314. contextOptions.fExecutor = nullptr;
  1315. Error refErr = this->onDraw(src, &reference, &refStream, &refLog, contextOptions);
  1316. if (!refErr.isEmpty()) {
  1317. return refErr;
  1318. }
  1319. return compare_bitmaps(reference, *dst);
  1320. }
  1321. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1322. GPUPersistentCacheTestingSink::GPUPersistentCacheTestingSink(
  1323. GrContextFactory::ContextType ct,
  1324. GrContextFactory::ContextOverrides overrides,
  1325. SkCommandLineConfigGpu::SurfType surfType,
  1326. int samples,
  1327. bool diText,
  1328. SkColorType colorType,
  1329. SkAlphaType alphaType,
  1330. sk_sp<SkColorSpace> colorSpace,
  1331. bool threaded,
  1332. const GrContextOptions& grCtxOptions,
  1333. int cacheType)
  1334. : INHERITED(ct, overrides, surfType, samples, diText, colorType, alphaType,
  1335. std::move(colorSpace), threaded, grCtxOptions)
  1336. , fCacheType(cacheType) {}
  1337. Error GPUPersistentCacheTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStream,
  1338. SkString* log) const {
  1339. // Draw twice, once with a cold cache, and again with a warm cache. Verify that we get the same
  1340. // result.
  1341. sk_gpu_test::MemoryCache memoryCache;
  1342. GrContextOptions contextOptions = this->baseContextOptions();
  1343. contextOptions.fPersistentCache = &memoryCache;
  1344. contextOptions.fDisallowGLSLBinaryCaching = (fCacheType == 2);
  1345. // anglebug.com/3619
  1346. contextOptions.fGpuPathRenderers =
  1347. contextOptions.fGpuPathRenderers & ~GpuPathRenderers::kStencilAndCover;
  1348. Error err = this->onDraw(src, dst, wStream, log, contextOptions);
  1349. if (!err.isEmpty() || !dst) {
  1350. return err;
  1351. }
  1352. SkBitmap reference;
  1353. SkString refLog;
  1354. SkDynamicMemoryWStream refStream;
  1355. memoryCache.resetNumCacheMisses();
  1356. Error refErr = this->onDraw(src, &reference, &refStream, &refLog, contextOptions);
  1357. if (!refErr.isEmpty()) {
  1358. return refErr;
  1359. }
  1360. SkASSERT(!memoryCache.numCacheMisses());
  1361. return compare_bitmaps(reference, *dst);
  1362. }
  1363. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1364. static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
  1365. if (src.size().isEmpty()) {
  1366. return "Source has empty dimensions";
  1367. }
  1368. SkASSERT(doc);
  1369. int pageCount = src.pageCount();
  1370. for (int i = 0; i < pageCount; ++i) {
  1371. int width = src.size(i).width(), height = src.size(i).height();
  1372. SkCanvas* canvas =
  1373. doc->beginPage(SkIntToScalar(width), SkIntToScalar(height));
  1374. if (!canvas) {
  1375. return "SkDocument::beginPage(w,h) returned nullptr";
  1376. }
  1377. Error err = src.draw(i, canvas);
  1378. if (!err.isEmpty()) {
  1379. return err;
  1380. }
  1381. doc->endPage();
  1382. }
  1383. doc->close();
  1384. dst->flush();
  1385. return "";
  1386. }
  1387. Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
  1388. SkPDF::Metadata metadata;
  1389. metadata.fTitle = src.name();
  1390. metadata.fSubject = "rendering correctness test";
  1391. metadata.fCreator = "Skia/DM";
  1392. metadata.fRasterDPI = fRasterDpi;
  1393. metadata.fPDFA = fPDFA;
  1394. #if SK_PDF_TEST_EXECUTOR
  1395. std::unique_ptr<SkExecutor> executor = SkExecutor::MakeFIFOThreadPool();
  1396. metadata.fExecutor = executor.get();
  1397. #endif
  1398. auto doc = SkPDF::MakeDocument(dst, metadata);
  1399. if (!doc) {
  1400. return "SkPDF::MakeDocument() returned nullptr";
  1401. }
  1402. return draw_skdocument(src, doc.get(), dst);
  1403. }
  1404. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1405. XPSSink::XPSSink() {}
  1406. #ifdef SK_BUILD_FOR_WIN
  1407. static SkTScopedComPtr<IXpsOMObjectFactory> make_xps_factory() {
  1408. IXpsOMObjectFactory* factory;
  1409. HRN(CoCreateInstance(CLSID_XpsOMObjectFactory,
  1410. nullptr,
  1411. CLSCTX_INPROC_SERVER,
  1412. IID_PPV_ARGS(&factory)));
  1413. return SkTScopedComPtr<IXpsOMObjectFactory>(factory);
  1414. }
  1415. Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
  1416. SkAutoCoInitialize com;
  1417. if (!com.succeeded()) {
  1418. return "Could not initialize COM.";
  1419. }
  1420. SkTScopedComPtr<IXpsOMObjectFactory> factory = make_xps_factory();
  1421. if (!factory) {
  1422. return "Failed to create XPS Factory.";
  1423. }
  1424. auto doc = SkXPS::MakeDocument(dst, factory.get());
  1425. if (!doc) {
  1426. return "SkXPS::MakeDocument() returned nullptr";
  1427. }
  1428. return draw_skdocument(src, doc.get(), dst);
  1429. }
  1430. #else
  1431. Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
  1432. return "XPS not supported on this platform.";
  1433. }
  1434. #endif
  1435. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1436. SKPSink::SKPSink() {}
  1437. Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
  1438. SkSize size;
  1439. size = src.size();
  1440. SkPictureRecorder recorder;
  1441. Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
  1442. if (!err.isEmpty()) {
  1443. return err;
  1444. }
  1445. recorder.finishRecordingAsPicture()->serialize(dst);
  1446. return "";
  1447. }
  1448. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1449. Error DebugSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
  1450. DebugCanvas debugCanvas(src.size().width(), src.size().height());
  1451. Error err = src.draw(&debugCanvas);
  1452. if (!err.isEmpty()) {
  1453. return err;
  1454. }
  1455. std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
  1456. UrlDataManager dataManager(SkString("data"));
  1457. SkJSONWriter writer(dst, SkJSONWriter::Mode::kPretty);
  1458. writer.beginObject(); // root
  1459. debugCanvas.toJSON(writer, dataManager, debugCanvas.getSize(), nullCanvas.get());
  1460. writer.endObject(); // root
  1461. writer.flush();
  1462. return "";
  1463. }
  1464. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1465. SVGSink::SVGSink(int pageIndex) : fPageIndex(pageIndex) {}
  1466. Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
  1467. #if defined(SK_XML)
  1468. if (src.pageCount() > 1) {
  1469. int pageCount = src.pageCount();
  1470. if (fPageIndex > pageCount - 1) {
  1471. return Error(SkStringPrintf("Page index %d too high for document with only %d pages.",
  1472. fPageIndex, pageCount));
  1473. }
  1474. }
  1475. return src.draw(fPageIndex,
  1476. SkSVGCanvas::Make(SkRect::MakeWH(SkIntToScalar(src.size().width()),
  1477. SkIntToScalar(src.size().height())),
  1478. dst)
  1479. .get());
  1480. #else
  1481. (void)fPageIndex;
  1482. return Error("SVG sink is disabled.");
  1483. #endif // SK_XML
  1484. }
  1485. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1486. RasterSink::RasterSink(SkColorType colorType, sk_sp<SkColorSpace> colorSpace)
  1487. : fColorType(colorType)
  1488. , fColorSpace(std::move(colorSpace)) {}
  1489. Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
  1490. const SkISize size = src.size();
  1491. // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
  1492. SkAlphaType alphaType = kPremul_SkAlphaType;
  1493. (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
  1494. dst->allocPixelsFlags(SkImageInfo::Make(size.width(), size.height(),
  1495. fColorType, alphaType, fColorSpace),
  1496. SkBitmap::kZeroPixels_AllocFlag);
  1497. SkCanvas canvas(*dst);
  1498. return src.draw(&canvas);
  1499. }
  1500. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1501. // Handy for front-patching a Src. Do whatever up-front work you need, then call draw_to_canvas(),
  1502. // passing the Sink draw() arguments, a size, and a function draws into an SkCanvas.
  1503. // Several examples below.
  1504. template <typename Fn>
  1505. static Error draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, SkString* log,
  1506. SkISize size, const Fn& draw) {
  1507. class ProxySrc : public Src {
  1508. public:
  1509. ProxySrc(SkISize size, const Fn& draw) : fSize(size), fDraw(draw) {}
  1510. Error draw(SkCanvas* canvas) const override { return fDraw(canvas); }
  1511. Name name() const override { return "ProxySrc"; }
  1512. SkISize size() const override { return fSize; }
  1513. private:
  1514. SkISize fSize;
  1515. const Fn& fDraw;
  1516. };
  1517. return sink->draw(ProxySrc(size, draw), bitmap, stream, log);
  1518. }
  1519. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1520. static DEFINE_bool(check, true, "If true, have most Via- modes fail if they affect the output.");
  1521. // Is *bitmap identical to what you get drawing src into sink?
  1522. static Error check_against_reference(const SkBitmap* bitmap, const Src& src, Sink* sink) {
  1523. // We can only check raster outputs.
  1524. // (Non-raster outputs like .pdf, .skp, .svg may differ but still draw identically.)
  1525. if (FLAGS_check && bitmap) {
  1526. SkBitmap reference;
  1527. SkString log;
  1528. SkDynamicMemoryWStream wStream;
  1529. Error err = sink->draw(src, &reference, &wStream, &log);
  1530. // If we can draw into this Sink via some pipeline, we should be able to draw directly.
  1531. SkASSERT(err.isEmpty());
  1532. if (!err.isEmpty()) {
  1533. return err;
  1534. }
  1535. return compare_bitmaps(reference, *bitmap);
  1536. }
  1537. return "";
  1538. }
  1539. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1540. static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
  1541. SkRect bounds = SkRect::MakeIWH(srcW, srcH);
  1542. matrix->mapRect(&bounds);
  1543. matrix->postTranslate(-bounds.x(), -bounds.y());
  1544. return {SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height())};
  1545. }
  1546. ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
  1547. Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
  1548. SkMatrix matrix = fMatrix;
  1549. SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
  1550. return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) {
  1551. canvas->concat(matrix);
  1552. return src.draw(canvas);
  1553. });
  1554. }
  1555. // Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
  1556. // This should be pixel-preserving.
  1557. ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
  1558. Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
  1559. Error err = fSink->draw(src, bitmap, stream, log);
  1560. if (!err.isEmpty()) {
  1561. return err;
  1562. }
  1563. SkMatrix inverse;
  1564. if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) {
  1565. return "Cannot upright --matrix.";
  1566. }
  1567. SkMatrix upright = SkMatrix::I();
  1568. upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX()));
  1569. upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY()));
  1570. upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX()));
  1571. upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY()));
  1572. SkBitmap uprighted;
  1573. SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height());
  1574. uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height()));
  1575. SkCanvas canvas(uprighted);
  1576. canvas.concat(upright);
  1577. SkPaint paint;
  1578. paint.setBlendMode(SkBlendMode::kSrc);
  1579. canvas.drawBitmap(*bitmap, 0, 0, &paint);
  1580. *bitmap = uprighted;
  1581. return "";
  1582. }
  1583. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1584. Error ViaSerialization::draw(
  1585. const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
  1586. // Record our Src into a picture.
  1587. auto size = src.size();
  1588. SkPictureRecorder recorder;
  1589. Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
  1590. SkIntToScalar(size.height())));
  1591. if (!err.isEmpty()) {
  1592. return err;
  1593. }
  1594. sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
  1595. // Serialize it and then deserialize it.
  1596. sk_sp<SkPicture> deserialized(SkPicture::MakeFromData(pic->serialize().get()));
  1597. err = draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) {
  1598. canvas->drawPicture(deserialized);
  1599. return "";
  1600. });
  1601. if (!err.isEmpty()) {
  1602. return err;
  1603. }
  1604. return check_against_reference(bitmap, src, fSink.get());
  1605. }
  1606. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1607. ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
  1608. : Via(sink)
  1609. , fW(w)
  1610. , fH(h)
  1611. , fFactory(factory) {}
  1612. Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
  1613. auto size = src.size();
  1614. SkPictureRecorder recorder;
  1615. Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
  1616. SkIntToScalar(size.height()),
  1617. fFactory.get()));
  1618. if (!err.isEmpty()) {
  1619. return err;
  1620. }
  1621. sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
  1622. return draw_to_canvas(fSink.get(), bitmap, stream, log, src.size(), [&](SkCanvas* canvas) {
  1623. const int xTiles = (size.width() + fW - 1) / fW,
  1624. yTiles = (size.height() + fH - 1) / fH;
  1625. SkMultiPictureDraw mpd(xTiles*yTiles);
  1626. SkTArray<sk_sp<SkSurface>> surfaces;
  1627. // surfaces.setReserve(xTiles*yTiles);
  1628. SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
  1629. for (int j = 0; j < yTiles; j++) {
  1630. for (int i = 0; i < xTiles; i++) {
  1631. // This lets our ultimate Sink determine the best kind of surface.
  1632. // E.g., if it's a GpuSink, the surfaces and images are textures.
  1633. auto s = canvas->makeSurface(info);
  1634. if (!s) {
  1635. s = SkSurface::MakeRaster(info); // Some canvases can't create surfaces.
  1636. }
  1637. surfaces.push_back(s);
  1638. SkCanvas* c = s->getCanvas();
  1639. c->translate(SkIntToScalar(-i * fW),
  1640. SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
  1641. mpd.add(c, pic.get());
  1642. }
  1643. }
  1644. mpd.draw();
  1645. for (int j = 0; j < yTiles; j++) {
  1646. for (int i = 0; i < xTiles; i++) {
  1647. sk_sp<SkImage> image(surfaces[i+xTiles*j]->makeImageSnapshot());
  1648. canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
  1649. }
  1650. }
  1651. return "";
  1652. });
  1653. }
  1654. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1655. ViaDDL::ViaDDL(int numReplays, int numDivisions, Sink* sink)
  1656. : Via(sink), fNumReplays(numReplays), fNumDivisions(numDivisions) {}
  1657. Error ViaDDL::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
  1658. auto size = src.size();
  1659. SkPictureRecorder recorder;
  1660. Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
  1661. SkIntToScalar(size.height())));
  1662. if (!err.isEmpty()) {
  1663. return err;
  1664. }
  1665. sk_sp<SkPicture> inputPicture(recorder.finishRecordingAsPicture());
  1666. // this is our ultimate final drawing area/rect
  1667. SkIRect viewport = SkIRect::MakeWH(size.fWidth, size.fHeight);
  1668. DDLPromiseImageHelper promiseImageHelper;
  1669. sk_sp<SkData> compressedPictureData = promiseImageHelper.deflateSKP(inputPicture.get());
  1670. if (!compressedPictureData) {
  1671. return SkStringPrintf("ViaDDL: Couldn't deflate SkPicture");
  1672. }
  1673. auto draw = [&](SkCanvas* canvas) -> Error {
  1674. GrContext* context = canvas->getGrContext();
  1675. if (!context || !context->priv().getGpu()) {
  1676. return SkStringPrintf("DDLs are GPU only");
  1677. }
  1678. // This is here bc this is the first point where we have access to the context
  1679. promiseImageHelper.uploadAllToGPU(context);
  1680. // We draw N times, with a clear between.
  1681. for (int replay = 0; replay < fNumReplays; ++replay) {
  1682. if (replay > 0) {
  1683. // Clear the drawing of the previous replay
  1684. canvas->clear(SK_ColorTRANSPARENT);
  1685. }
  1686. // First, create all the tiles (including their individual dest surfaces)
  1687. DDLTileHelper tiles(canvas, viewport, fNumDivisions);
  1688. // Second, reinflate the compressed picture individually for each thread
  1689. // This recreates the promise SkImages on each replay iteration. We are currently
  1690. // relying on this to test using a SkPromiseImageTexture to fulfill different
  1691. // SkImages. On each replay the promise SkImages are recreated in createSKPPerTile.
  1692. tiles.createSKPPerTile(compressedPictureData.get(), promiseImageHelper);
  1693. // Third, create the DDLs in parallel
  1694. tiles.createDDLsInParallel();
  1695. if (replay == fNumReplays - 1) {
  1696. // This drops the promiseImageHelper's refs on all the promise images if we're in
  1697. // the last run.
  1698. promiseImageHelper.reset();
  1699. }
  1700. // Fourth, synchronously render the display lists into the dest tiles
  1701. // TODO: it would be cool to not wait until all the tiles are drawn to begin
  1702. // drawing to the GPU and composing to the final surface
  1703. tiles.drawAllTilesAndFlush(context, false);
  1704. // Finally, compose the drawn tiles into the result
  1705. // Note: the separation between the tiles and the final composition better
  1706. // matches Chrome but costs us a copy
  1707. tiles.composeAllTiles(canvas);
  1708. context->flush();
  1709. }
  1710. return "";
  1711. };
  1712. return draw_to_canvas(fSink.get(), bitmap, stream, log, size, draw);
  1713. }
  1714. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1715. Error ViaPicture::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
  1716. auto size = src.size();
  1717. Error err = draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) {
  1718. SkPictureRecorder recorder;
  1719. sk_sp<SkPicture> pic;
  1720. Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
  1721. SkIntToScalar(size.height())));
  1722. if (!err.isEmpty()) {
  1723. return err;
  1724. }
  1725. pic = recorder.finishRecordingAsPicture();
  1726. canvas->drawPicture(pic);
  1727. return err;
  1728. });
  1729. if (!err.isEmpty()) {
  1730. return err;
  1731. }
  1732. return check_against_reference(bitmap, src, fSink.get());
  1733. }
  1734. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1735. #ifdef TEST_VIA_SVG
  1736. #include "experimental/svg/model/SkSVGDOM.h"
  1737. #include "include/svg/SkSVGCanvas.h"
  1738. #include "src/xml/SkXMLWriter.h"
  1739. Error ViaSVG::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
  1740. auto size = src.size();
  1741. return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
  1742. SkDynamicMemoryWStream wstream;
  1743. SkXMLStreamWriter writer(&wstream);
  1744. Error err = src.draw(SkSVGCanvas::Make(SkRect::Make(size), &writer).get());
  1745. if (!err.isEmpty()) {
  1746. return err;
  1747. }
  1748. std::unique_ptr<SkStream> rstream(wstream.detachAsStream());
  1749. auto dom = SkSVGDOM::MakeFromStream(*rstream);
  1750. if (dom) {
  1751. dom->setContainerSize(SkSize::Make(size));
  1752. dom->render(canvas);
  1753. }
  1754. return "";
  1755. });
  1756. }
  1757. #endif
  1758. } // namespace DM