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