fiddle_main.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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 <cstdio>
  8. #include <cstdlib>
  9. #include <sstream>
  10. #include <string>
  11. #include "src/core/SkAutoPixmapStorage.h"
  12. #include "src/core/SkMipMap.h"
  13. #include "src/core/SkUtils.h"
  14. #include "tools/flags/CommandLineFlags.h"
  15. #include "tools/fiddle/fiddle_main.h"
  16. static DEFINE_double(duration, 1.0,
  17. "The total duration, in seconds, of the animation we are drawing.");
  18. static DEFINE_double(frame, 1.0,
  19. "A double value in [0, 1] that specifies the point in animation to draw.");
  20. #include "include/gpu/GrBackendSurface.h"
  21. #include "src/gpu/GrContextPriv.h"
  22. #include "src/gpu/GrGpu.h"
  23. #include "tools/gpu/gl/GLTestContext.h"
  24. // Globals externed in fiddle_main.h
  25. sk_sp<GrTexture> backingTexture; // not externed
  26. GrBackendTexture backEndTexture;
  27. sk_sp<GrRenderTarget> backingRenderTarget; // not externed
  28. GrBackendRenderTarget backEndRenderTarget;
  29. sk_sp<GrTexture> backingTextureRenderTarget; // not externed
  30. GrBackendTexture backEndTextureRenderTarget;
  31. SkBitmap source;
  32. sk_sp<SkImage> image;
  33. double duration; // The total duration of the animation in seconds.
  34. double frame; // A value in [0, 1] of where we are in the animation.
  35. // Global used by the local impl of SkDebugf.
  36. std::ostringstream gTextOutput;
  37. // Global to record the GL driver info via create_grcontext().
  38. std::ostringstream gGLDriverInfo;
  39. void SkDebugf(const char * fmt, ...) {
  40. va_list args;
  41. va_start(args, fmt);
  42. char formatbuffer[1024];
  43. int n = vsnprintf(formatbuffer, sizeof(formatbuffer), fmt, args);
  44. va_end(args);
  45. if (n>=0 && n<=int(sizeof(formatbuffer))) {
  46. gTextOutput.write(formatbuffer, n);
  47. }
  48. }
  49. static void encode_to_base64(const void* data, size_t size, FILE* out) {
  50. const uint8_t* input = reinterpret_cast<const uint8_t*>(data);
  51. const uint8_t* end = &input[size];
  52. static const char codes[] =
  53. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  54. "abcdefghijklmnopqrstuvwxyz0123456789+/";
  55. while (input != end) {
  56. uint8_t b = (*input & 0xFC) >> 2;
  57. fputc(codes[b], out);
  58. b = (*input & 0x03) << 4;
  59. ++input;
  60. if (input == end) {
  61. fputc(codes[b], out);
  62. fputs("==", out);
  63. return;
  64. }
  65. b |= (*input & 0xF0) >> 4;
  66. fputc(codes[b], out);
  67. b = (*input & 0x0F) << 2;
  68. ++input;
  69. if (input == end) {
  70. fputc(codes[b], out);
  71. fputc('=', out);
  72. return;
  73. }
  74. b |= (*input & 0xC0) >> 6;
  75. fputc(codes[b], out);
  76. b = *input & 0x3F;
  77. fputc(codes[b], out);
  78. ++input;
  79. }
  80. }
  81. static void dump_output(const void* data, size_t size,
  82. const char* name, bool last = true) {
  83. printf("\t\"%s\": \"", name);
  84. encode_to_base64(data, size, stdout);
  85. fputs(last ? "\"\n" : "\",\n", stdout);
  86. }
  87. static void dump_output(const sk_sp<SkData>& data,
  88. const char* name, bool last = true) {
  89. if (data) {
  90. dump_output(data->data(), data->size(), name, last);
  91. }
  92. }
  93. static sk_sp<SkData> encode_snapshot(const sk_sp<SkSurface>& surface) {
  94. sk_sp<SkImage> img(surface->makeImageSnapshot());
  95. return img ? img->encodeToData() : nullptr;
  96. }
  97. static SkCanvas* prepare_canvas(SkCanvas * canvas) {
  98. canvas->clear(SK_ColorWHITE);
  99. return canvas;
  100. }
  101. static bool setup_backend_objects(GrContext* context,
  102. const SkBitmap& bm,
  103. const DrawOptions& options) {
  104. if (!context) {
  105. return false;
  106. }
  107. auto resourceProvider = context->priv().resourceProvider();
  108. GrSurfaceDesc backingDesc;
  109. backingDesc.fWidth = bm.width();
  110. backingDesc.fHeight = bm.height();
  111. // This config must match the SkColorType used in draw.cpp in the SkImage and Surface factories
  112. backingDesc.fConfig = kRGBA_8888_GrPixelConfig;
  113. if (!bm.empty()) {
  114. SkPixmap originalPixmap;
  115. SkPixmap* pixmap = &originalPixmap;
  116. if (!bm.peekPixels(&originalPixmap)) {
  117. return false;
  118. }
  119. SkAutoPixmapStorage rgbaPixmap;
  120. if (kN32_SkColorType != kRGBA_8888_SkColorType) {
  121. if (!rgbaPixmap.tryAlloc(bm.info().makeColorType(kRGBA_8888_SkColorType))) {
  122. return false;
  123. }
  124. if (!bm.readPixels(rgbaPixmap)) {
  125. return false;
  126. }
  127. pixmap = &rgbaPixmap;
  128. }
  129. int mipLevelCount = GrMipMapped::kYes == options.fMipMapping
  130. ? SkMipMap::ComputeLevelCount(bm.width(), bm.height())
  131. : 1;
  132. std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
  133. texels[0].fPixels = pixmap->addr();
  134. texels[0].fRowBytes = pixmap->rowBytes();
  135. for (int i = 1; i < mipLevelCount; i++) {
  136. texels[i].fPixels = nullptr;
  137. texels[i].fRowBytes = 0;
  138. }
  139. backingTexture =
  140. resourceProvider->createTexture(backingDesc, GrRenderable::kNo, 1, SkBudgeted::kNo,
  141. GrProtected::kNo, texels.get(), mipLevelCount);
  142. if (!backingTexture) {
  143. return false;
  144. }
  145. backEndTexture = backingTexture->getBackendTexture();
  146. if (!backEndTexture.isValid()) {
  147. return false;
  148. }
  149. }
  150. backingDesc.fWidth = options.fOffScreenWidth;
  151. backingDesc.fHeight = options.fOffScreenHeight;
  152. SkAutoTMalloc<uint32_t> data(backingDesc.fWidth * backingDesc.fHeight);
  153. sk_memset32(data.get(), 0, backingDesc.fWidth * backingDesc.fHeight);
  154. {
  155. // This backend object should be renderable but not textureable. Given the limitations
  156. // of how we're creating it though it will wind up being secretly textureable.
  157. // We use this fact to initialize it with data but don't allow mipmaps
  158. GrMipLevel level0 = { data.get(), backingDesc.fWidth*sizeof(uint32_t) };
  159. sk_sp<GrTexture> tmp = resourceProvider->createTexture(
  160. backingDesc, GrRenderable::kYes, options.fOffScreenSampleCount, SkBudgeted::kNo,
  161. GrProtected::kNo, &level0, 1);
  162. if (!tmp || !tmp->asRenderTarget()) {
  163. return false;
  164. }
  165. backingRenderTarget = sk_ref_sp(tmp->asRenderTarget());
  166. backEndRenderTarget = backingRenderTarget->getBackendRenderTarget();
  167. if (!backEndRenderTarget.isValid()) {
  168. return false;
  169. }
  170. }
  171. {
  172. int mipLevelCount = GrMipMapped::kYes == options.fOffScreenMipMapping
  173. ? SkMipMap::ComputeLevelCount(backingDesc.fWidth, backingDesc.fHeight)
  174. : 1;
  175. std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
  176. texels[0].fPixels = data.get();
  177. texels[0].fRowBytes = backingDesc.fWidth*sizeof(uint32_t);
  178. for (int i = 1; i < mipLevelCount; i++) {
  179. texels[i].fPixels = nullptr;
  180. texels[i].fRowBytes = 0;
  181. }
  182. backingTextureRenderTarget =
  183. resourceProvider->createTexture(backingDesc, GrRenderable::kYes,
  184. options.fOffScreenSampleCount, SkBudgeted::kNo, GrProtected::kNo,
  185. texels.get(), mipLevelCount);
  186. if (!backingTextureRenderTarget || !backingTextureRenderTarget->asRenderTarget()) {
  187. return false;
  188. }
  189. backEndTextureRenderTarget = backingTextureRenderTarget->getBackendTexture();
  190. if (!backEndTextureRenderTarget.isValid()) {
  191. return false;
  192. }
  193. }
  194. return true;
  195. }
  196. int main(int argc, char** argv) {
  197. CommandLineFlags::Parse(argc, argv);
  198. duration = FLAGS_duration;
  199. frame = FLAGS_frame;
  200. DrawOptions options = GetDrawOptions();
  201. // If textOnly then only do one type of image, otherwise the text
  202. // output is duplicated for each type.
  203. if (options.textOnly) {
  204. options.raster = true;
  205. options.gpu = false;
  206. options.pdf = false;
  207. options.skp = false;
  208. }
  209. if (options.source) {
  210. sk_sp<SkData> data(SkData::MakeFromFileName(options.source));
  211. if (!data) {
  212. perror(options.source);
  213. return 1;
  214. } else {
  215. image = SkImage::MakeFromEncoded(std::move(data));
  216. if (!image) {
  217. perror("Unable to decode the source image.");
  218. return 1;
  219. }
  220. SkAssertResult(image->asLegacyBitmap(&source));
  221. }
  222. }
  223. sk_sp<SkData> rasterData, gpuData, pdfData, skpData;
  224. SkColorType colorType = kN32_SkColorType;
  225. sk_sp<SkColorSpace> colorSpace = nullptr;
  226. if (options.f16) {
  227. SkASSERT(options.srgb);
  228. colorType = kRGBA_F16_SkColorType;
  229. colorSpace = SkColorSpace::MakeSRGBLinear();
  230. } else if (options.srgb) {
  231. colorSpace = SkColorSpace::MakeSRGB();
  232. }
  233. SkImageInfo info = SkImageInfo::Make(options.size.width(), options.size.height(), colorType,
  234. kPremul_SkAlphaType, colorSpace);
  235. if (options.raster) {
  236. auto rasterSurface = SkSurface::MakeRaster(info);
  237. srand(0);
  238. draw(prepare_canvas(rasterSurface->getCanvas()));
  239. rasterData = encode_snapshot(rasterSurface);
  240. }
  241. if (options.gpu) {
  242. std::unique_ptr<sk_gpu_test::GLTestContext> glContext;
  243. sk_sp<GrContext> grContext = create_grcontext(gGLDriverInfo, &glContext);
  244. if (!grContext) {
  245. fputs("Unable to get GrContext.\n", stderr);
  246. } else {
  247. if (!setup_backend_objects(grContext.get(), source, options)) {
  248. fputs("Unable to create backend objects.\n", stderr);
  249. exit(1);
  250. }
  251. auto surface = SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kNo, info);
  252. if (!surface) {
  253. fputs("Unable to get render surface.\n", stderr);
  254. exit(1);
  255. }
  256. srand(0);
  257. draw(prepare_canvas(surface->getCanvas()));
  258. gpuData = encode_snapshot(surface);
  259. }
  260. }
  261. if (options.pdf) {
  262. SkDynamicMemoryWStream pdfStream;
  263. auto document = SkPDF::MakeDocument(&pdfStream);
  264. if (document) {
  265. srand(0);
  266. draw(prepare_canvas(document->beginPage(options.size.width(), options.size.height())));
  267. document->close();
  268. pdfData = pdfStream.detachAsData();
  269. }
  270. }
  271. if (options.skp) {
  272. SkSize size;
  273. size = options.size;
  274. SkPictureRecorder recorder;
  275. srand(0);
  276. draw(prepare_canvas(recorder.beginRecording(size.width(), size.height())));
  277. auto picture = recorder.finishRecordingAsPicture();
  278. SkDynamicMemoryWStream skpStream;
  279. picture->serialize(&skpStream);
  280. skpData = skpStream.detachAsData();
  281. }
  282. printf("{\n");
  283. if (!options.textOnly) {
  284. dump_output(rasterData, "Raster", false);
  285. dump_output(gpuData, "Gpu", false);
  286. dump_output(pdfData, "Pdf", false);
  287. dump_output(skpData, "Skp", false);
  288. } else {
  289. std::string textoutput = gTextOutput.str();
  290. dump_output(textoutput.c_str(), textoutput.length(), "Text", false);
  291. }
  292. std::string glinfo = gGLDriverInfo.str();
  293. dump_output(glinfo.c_str(), glinfo.length(), "GLInfo", true);
  294. printf("}\n");
  295. return 0;
  296. }