SkString GrAtlasTextBatch::dumpInfo() const { SkString str; for (int i = 0; i < fGeoCount; ++i) { str.appendf("%d: Color: 0x%08x Trans: %.2f,%.2f Runs: %d\n", i, fGeoData[i].fColor, fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fBlob->runCount()); } str.append(INHERITED::dumpInfo()); return str; }
static void saveFile(const char name[], const char config[], const char dir[], const SkImage* image) { SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100)); if (NULL == data.get()) { return; } SkString filename; make_filename(name, &filename); filename.appendf("_%s.png", config); SkString path = SkOSPath::SkPathJoin(dir, filename.c_str()); ::remove(path.c_str()); SkFILEWStream stream(path.c_str()); stream.write(data->data(), data->size()); }
virtual const char* onGetName() { fName.set("bitmap"); fName.appendf("_%s%s", sk_tool_utils::colortype_name(fColorType), kOpaque_SkAlphaType == fAlphaType ? "" : "_A"); if (fDoScale) { fName.append("_scale"); } if (fForceUpdate) { fName.append("_update"); } if (fIsVolatile) { fName.append("_volatile"); } return fName.c_str(); }
static void push_brd_src(Path path, SkBitmapRegionDecoder::Strategy strategy, CodecSrc::DstColorType dstColorType, BRDSrc::Mode mode, uint32_t sampleSize) { SkString folder; switch (strategy) { case SkBitmapRegionDecoder::kCanvas_Strategy: folder.append("brd_canvas"); break; case SkBitmapRegionDecoder::kAndroidCodec_Strategy: folder.append("brd_android_codec"); break; default: SkASSERT(false); return; } switch (mode) { case BRDSrc::kFullImage_Mode: break; case BRDSrc::kDivisor_Mode: folder.append("_divisor"); break; default: SkASSERT(false); return; } switch (dstColorType) { case CodecSrc::kGetFromCanvas_DstColorType: break; case CodecSrc::kIndex8_Always_DstColorType: folder.append("_kIndex"); break; case CodecSrc::kGrayscale_Always_DstColorType: folder.append("_kGray"); break; default: SkASSERT(false); return; } if (1 != sampleSize) { folder.appendf("_%.3f", 1.0f / (float) sampleSize); } BRDSrc* src = new BRDSrc(path, strategy, mode, dstColorType, sampleSize); push_src("image", folder, src); }
SkString dumpInfo() const override { SkString str; for (int i = 0; i < fGeoData.count(); ++i) { str.appendf("%d: Color: 0x%08x Center [L: %d, T: %d, R: %d, B: %d], " "Dst [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i, fGeoData[i].fColor, fGeoData[i].fCenter.fLeft, fGeoData[i].fCenter.fTop, fGeoData[i].fCenter.fRight, fGeoData[i].fCenter.fBottom, fGeoData[i].fDst.fLeft, fGeoData[i].fDst.fTop, fGeoData[i].fDst.fRight, fGeoData[i].fDst.fBottom); } str.append(INHERITED::dumpInfo()); return str; }
void iterateFamily(SkCanvas* canvas, const SkPaint& paint, SkFontStyleSet* fset) { SkPaint p(paint); SkScalar y = 0; for (int j = 0; j < fset->count(); ++j) { SkString sname; SkFontStyle fs; fset->getStyle(j, &fs, &sname); sname.appendf(" [%d %d]", fs.weight(), fs.width()); SkSafeUnref(p.setTypeface(fset->createTypeface(j))); (void)drawString(canvas, sname, 0, y, p); y += 24; } }
static void forever(void*) { for (;;) { static const int kSec = 300; #if defined(SK_BUILD_FOR_WIN) Sleep(kSec * 1000); #else sleep(kSec); #endif SkString running; { SkAutoMutexAcquire lock(gRunningMutex); for (int i = 0; i < gRunning.count(); i++) { running.appendf("\n\t%s", gRunning[i].c_str()); } } SkDebugf("\nCurrently running:%s\n", running.c_str()); } }
static void push_android_codec_src(Path path, AndroidCodecSrc::Mode mode, CodecSrc::DstColorType dstColorType, SkAlphaType dstAlphaType, int sampleSize) { SkString folder; switch (mode) { case AndroidCodecSrc::kFullImage_Mode: folder.append("scaled_codec"); break; case AndroidCodecSrc::kDivisor_Mode: folder.append("scaled_codec_divisor"); break; } switch (dstColorType) { case CodecSrc::kGrayscale_Always_DstColorType: folder.append("_kGray8"); break; case CodecSrc::kIndex8_Always_DstColorType: folder.append("_kIndex8"); break; default: break; } switch (dstAlphaType) { case kOpaque_SkAlphaType: folder.append("_opaque"); break; case kPremul_SkAlphaType: folder.append("_premul"); break; case kUnpremul_SkAlphaType: folder.append("_unpremul"); break; default: break; } if (1 != sampleSize) { folder.appendf("_%.3f", 1.0f / (float) sampleSize); } AndroidCodecSrc* src = new AndroidCodecSrc(path, mode, dstColorType, dstAlphaType, sampleSize); push_src("image", folder, src); }
static void generate_index(const char* defaultName, FILE* out) { int fontCount = gWritten.count(); fprintf(out, "static SkTestFontData gTestFonts[] = {\n"); int fontIndex; for (fontIndex = 0; fontIndex < fontCount; ++fontIndex) { const FontWritten& writ = gWritten[fontIndex]; const char* name = writ.fName; SkString strippedStr = strip_spaces(SkString(name)); strippedStr.appendf("%s", gStyleName[writ.fStyle]); const char* strip = strippedStr.c_str(); fprintf(out, " { %sPoints, %sVerbs, %sCharCodes,\n" " %sCharCodesCount, %sWidths,\n" " %sMetrics, \"%s\", SkTypeface::%s, NULL\n" " },\n", strip, strip, strip, strip, strip, strip, name, gStyleName[writ.fStyle]); } fprintf(out, "};\n\n"); fprintf(out, "const int gTestFontsCount = (int) SK_ARRAY_COUNT(gTestFonts);\n\n"); fprintf(out, "struct SubFont {\n" " const char* fName;\n" " SkTypeface::Style fStyle;\n" " SkTestFontData& fFont;\n" " const char* fFile;\n" "};\n\n" "const SubFont gSubFonts[] = {\n"); int defaultIndex = -1; for (int subIndex = 0; subIndex < gFontsCount; subIndex++) { const FontDesc& desc = gFonts[subIndex]; if (!strcmp(defaultName, desc.fName)) { defaultIndex = subIndex; } fprintf(out, " { \"%s\", SkTypeface::%s, gTestFonts[%d], \"%s\"},\n", desc.fName, gStyleName[desc.fStyle], desc.fFontIndex, desc.fFile); } fprintf(out, "};\n\n"); fprintf(out, "const int gSubFontsCount = (int) SK_ARRAY_COUNT(gSubFonts);\n\n"); SkASSERT(defaultIndex >= 0); fprintf(out, "const int gDefaultFontIndex = %d;\n", defaultIndex); }
static SkString generate_template(SkString source) { SkString debuggerTemplate; debuggerTemplate.appendf( "<!DOCTYPE html>\n" "<html>\n" "<head>\n" " <title>SkDebugger</title>\n" " <meta charset=\"utf-8\" />\n" " <meta http-equiv=\"X-UA-Compatible\" content=\"IE=egde,chrome=1\">\n" " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" " <script src=\"%s/res/js/core.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n" " <link href=\"%s/res/vul/elements.html\" rel=\"import\" />\n" " <link rel='shortcut icon' href='https://debugger.skia.org/res/img/favicon.ico' type='image/x-icon'/ >" "</head>\n" "<body class=\"fullbleed layout vertical\">\n" " <debugger-app-sk>This is the app." " </debugger-app-sk>\n" "</body>\n" "</html>", source.c_str(), source.c_str()); return debuggerTemplate; }
static SkString generate_template(SkString source) { SkString debuggerTemplate; debuggerTemplate.appendf( "<!DOCTYPE html>\n" "<html>\n" "<head>\n" " <title>SkDebugger</title>\n" " <meta charset='utf-8' />\n" " <meta http-equiv='X-UA-Compatible' content='IE=egde,chrome=1'>\n" " <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n" " <script src='%s/res/js/core.js' type='text/javascript' charset='utf-8'></script>\n" " <link href='%s/res/vul/elements.html' rel='import' />\n" " <link rel='shortcut icon' href='%s/res/img/favicon.ico' type='image/x-icon'/ >" "</head>\n" "<body class='fullbleed layout vertical'>\n" " <debugger-app-sk>This is the app." " </debugger-app-sk>\n" "</body>\n" "</html>", source.c_str(), source.c_str(), source.c_str()); return debuggerTemplate; }
DEF_TEST(SkRecordingAccuracyXfermode, reporter) { #define FINEGRAIN 0 const Drawer drawer; BitmapBackedCanvasStrategy golden(drawer.imageInfo()); PictureStrategy picture(drawer.imageInfo()); #if !FINEGRAIN unsigned numErrors = 0; SkString errors; #endif for (int iMode = 0; iMode < int(SkBlendMode::kLastMode); iMode++) { const SkRect& clip = SkRect::MakeXYWH(100, 0, 100, 100); SkBlendMode mode = SkBlendMode(iMode); const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode); const SkBitmap& pictureBM = picture.recordAndReplay(drawer, clip, mode); size_t pixelsSize = goldenBM.computeByteSize(); REPORTER_ASSERT(reporter, pixelsSize == pictureBM.computeByteSize()); // The pixel arrays should match. #if FINEGRAIN REPORTER_ASSERT(reporter, 0 == memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize)); #else if (memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize)) { numErrors++; errors.appendf("For SkXfermode %d %s: SkPictureRecorder bitmap is wrong\n", iMode, SkBlendMode_Name(mode)); } #endif } #if !FINEGRAIN REPORTER_ASSERT(reporter, 0 == numErrors, errors.c_str()); #endif }
static void push_codec_src(Path path, CodecSrc::Mode mode, CodecSrc::DstColorType dstColorType, float scale) { SkString folder; switch (mode) { case CodecSrc::kCodec_Mode: folder.append("codec"); break; case CodecSrc::kScanline_Mode: folder.append("scanline"); break; case CodecSrc::kScanline_Subset_Mode: folder.append("scanline_subset"); break; case CodecSrc::kStripe_Mode: folder.append("stripe"); break; case CodecSrc::kSubset_Mode: folder.append("codec_subset"); break; } switch (dstColorType) { case CodecSrc::kGrayscale_Always_DstColorType: folder.append("_kGray8"); break; case CodecSrc::kIndex8_Always_DstColorType: folder.append("_kIndex8"); break; default: break; } if (1.0f != scale) { folder.appendf("_%.3f", scale); } CodecSrc* src = new CodecSrc(path, mode, dstColorType, scale); push_src("image", folder, src); }
void onDraw(SkCanvas* canvas) override { SkScalar y = 20; SkPaint paint; paint.setAntiAlias(true); paint.setLCDRenderText(true); paint.setSubpixelText(true); paint.setTextSize(17); SkFontMgr* fm = fFM; int count = SkMin32(fm->countFamilies(), MAX_FAMILIES); for (int i = 0; i < count; ++i) { SkString familyName; fm->getFamilyName(i, &familyName); paint.setTypeface(nullptr); (void)drawString(canvas, familyName, 20, y, paint); SkScalar x = 220; SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i)); for (int j = 0; j < set->count(); ++j) { SkString sname; SkFontStyle fs; set->getStyle(j, &fs, &sname); sname.appendf(" [%d %d %d]", fs.weight(), fs.width(), fs.slant()); SkSafeUnref(paint.setTypeface(set->createTypeface(j))); x = drawString(canvas, sname, x, y, paint) + 20; // check to see that we get different glyphs in japanese and chinese x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &zh, 1, fs); x = drawCharacter(canvas, 0x5203, x, y, paint, fm, familyName.c_str(), &ja, 1, fs); // check that emoji characters are found x = drawCharacter(canvas, 0x1f601, x, y, paint, fm, familyName.c_str(), nullptr,0, fs); } y += 24; } }
void sniff(const void* ptr, size_t len) { SkMD5 md5; md5.write(ptr, len); SkMD5::Digest digest; md5.finish(digest); if (gSeen.contains(digest)) { return; } gSeen.add(digest); SkAutoTUnref<SkData> data(SkData::NewWithoutCopy(ptr, len)); SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data)); if (!codec) { gUnknown++; return; } SkString ext; switch (codec->getEncodedFormat()) { case SkEncodedFormat::kBMP_SkEncodedFormat: ext = "bmp"; break; case SkEncodedFormat::kGIF_SkEncodedFormat: ext = "gif"; break; case SkEncodedFormat::kICO_SkEncodedFormat: ext = "ico"; break; case SkEncodedFormat::kJPEG_SkEncodedFormat: ext = "jpg"; break; case SkEncodedFormat::kPNG_SkEncodedFormat: ext = "png"; break; case SkEncodedFormat::kRAW_SkEncodedFormat: ext = "dng"; break; case SkEncodedFormat::kWBMP_SkEncodedFormat: ext = "wbmp"; break; case SkEncodedFormat::kWEBP_SkEncodedFormat: ext = "webp"; break; default: gUnknown++; return; } SkString path; path.appendf("%s/%d.%s", gOutputDir, gKnown++, ext.c_str()); SkFILEWStream file(path.c_str()); file.write(ptr, len); SkDebugf("%s\n", path.c_str()); }
static void push_android_codec_src(Path path, CodecSrc::DstColorType dstColorType, SkAlphaType dstAlphaType, int sampleSize) { SkString folder; folder.append("scaled_codec"); switch (dstColorType) { case CodecSrc::kGrayscale_Always_DstColorType: folder.append("_kGray8"); break; case CodecSrc::kIndex8_Always_DstColorType: folder.append("_kIndex8"); break; case CodecSrc::kNonNative8888_Always_DstColorType: folder.append("_kNonNative"); break; default: break; } switch (dstAlphaType) { case kPremul_SkAlphaType: folder.append("_premul"); break; case kUnpremul_SkAlphaType: folder.append("_unpremul"); break; default: break; } if (1 != sampleSize) { folder.appendf("_%.3f", 1.0f / (float) sampleSize); } AndroidCodecSrc* src = new AndroidCodecSrc(path, dstColorType, dstAlphaType, sampleSize); push_src("image", folder, src); }
int tool_main(int argc, char** argv) { SkAutoGraphics ag; SkString usage; usage.printf("Usage: filename [filename]*\n"); if (argc < 2) { SkDebugf("%s\n", usage.c_str()); return -1; } SkTArray<Histogram> histograms[kNumBenchmarks]; for (size_t i = 0; i < kNumBenchmarks; ++i) { histograms[i].reset(argc - 1); bool success = benchmark_loop( argc, argv, BenchmarkControl::Make(i), histograms[i]); if (!success) { SkDebugf("benchmark_loop failed at index %d", i); } } // Output gnuplot readable histogram data.. const char* pbTitle = "bbh_shootout_playback.dat"; const char* recTitle = "bbh_shootout_record.dat"; SkFILEWStream playbackOut(pbTitle); SkFILEWStream recordOut(recTitle); recordOut.writeText("# "); playbackOut.writeText("# "); for (size_t i = 0; i < kNumBenchmarks; ++i) { SkString out; out.printf("%s ", BenchmarkControl::getBenchmarkName(i).c_str()); if (BenchmarkControl::getBenchmarkFunc(i) == &benchmark_recording) { recordOut.writeText(out.c_str()); } if (BenchmarkControl::getBenchmarkFunc(i) == &benchmark_playback) { playbackOut.writeText(out.c_str()); } } recordOut.writeText("\n"); playbackOut.writeText("\n"); for (int i = 0; i < argc - 1; ++i) { SkString pbLine; SkString recLine; // ==== Write record info recLine.printf("%d ", i); recLine.appendf("%f ", histograms[0][i].fCpuTime); // Append normal_record time recLine.appendf("%f", histograms[1][i].fCpuTime); // Append rtree_record time // ==== Write playback info pbLine.printf("%d ", i); pbLine.appendf("%f ", histograms[2][i].fCpuTime); // Start with normal playback time. // Append all playback benchmark times. for (size_t j = kNumBbhPlaybackBenchmarks; j < kNumBenchmarks; ++j) { pbLine.appendf("%f ", histograms[j][i].fCpuTime); } pbLine.remove(pbLine.size() - 1, 1); // Remove trailing space from line. pbLine.appendf("\n"); recLine.appendf("\n"); playbackOut.writeText(pbLine.c_str()); recordOut.writeText(recLine.c_str()); } SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle); return 0; }
static void testOpCubicsMain(PathOpsThreadState* data) { #if DEBUG_SHOW_TEST_NAME strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH); #endif SkASSERT(data); PathOpsThreadState& state = *data; SkString pathStr; for (int a = 0 ; a < 6; ++a) { for (int b = a + 1 ; b < 7; ++b) { for (int c = 0 ; c < 6; ++c) { for (int d = c + 1 ; d < 7; ++d) { for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) { for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f) { SkPath pathA, pathB; pathA.setFillType((SkPath::FillType) e); pathA.moveTo(SkIntToScalar(state.fA), SkIntToScalar(state.fB)); pathA.cubicTo(SkIntToScalar(state.fC), SkIntToScalar(state.fD), SkIntToScalar(b), SkIntToScalar(a), SkIntToScalar(d), SkIntToScalar(c)); pathA.close(); pathB.setFillType((SkPath::FillType) f); pathB.moveTo(SkIntToScalar(a), SkIntToScalar(b)); pathB.cubicTo(SkIntToScalar(c), SkIntToScalar(d), SkIntToScalar(state.fB), SkIntToScalar(state.fA), SkIntToScalar(state.fD), SkIntToScalar(state.fC)); pathB.close(); for (int op = 0 ; op <= kXOR_SkPathOp; ++op) { if (state.fReporter->verbose()) { pathStr.printf("static void cubicOp%d(skiatest::Reporter* reporter," " const char* filename) {\n", loopNo); pathStr.appendf(" SkPath path, pathB;\n"); pathStr.appendf(" path.setFillType(SkPath::k%s_FillType);\n", e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType ? "EvenOdd" : "?UNDEFINED"); pathStr.appendf(" path.moveTo(%d,%d);\n", state.fA, state.fB); pathStr.appendf(" path.cubicTo(%d,%d, %d,%d, %d,%d);\n", state.fC, state.fD, b, a, d, c); pathStr.appendf(" path.close();\n"); pathStr.appendf(" pathB.setFillType(SkPath::k%s_FillType);\n", f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType ? "EvenOdd" : "?UNDEFINED"); pathStr.appendf(" pathB.moveTo(%d,%d);\n", a, b); pathStr.appendf(" pathB.cubicTo(%d,%d, %d,%d, %d,%d);\n", c, d, state.fB, state.fA, state.fD, state.fC); pathStr.appendf(" pathB.close();\n"); pathStr.appendf(" testPathOp(reporter, path, pathB, %s, filename);\n", SkPathOpsDebug::OpStr((SkPathOp) op)); pathStr.appendf("}\n"); outputProgress(state.fPathStr, pathStr.c_str(), (SkPathOp) op); } if (!testPathOp(state.fReporter, pathA, pathB, (SkPathOp) op, "cubics")) { if (state.fReporter->verbose()) { ++loopNo; goto skipToNext; } } } } } skipToNext: ; } } } } }
SkString GrDrawTargetCaps::dump() const { SkString r; static const char* gNY[] = {"NO", "YES"}; r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]); r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); r.appendf("Compressed Update Support : %s\n", gNY[fCompressedTexSubImageSupport]); r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]); r.appendf("Max Texture Size : %d\n", fMaxTextureSize); r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); r.appendf("Max Sample Count : %d\n", fMaxSampleCount); r.appendf("Map Buffer Support : %s\n", map_flags_to_string(fMapBufferFlags).c_str()); static const char* kConfigNames[] = { "Unknown", // kUnknown_GrPixelConfig "Alpha8", // kAlpha_8_GrPixelConfig, "Index8", // kIndex_8_GrPixelConfig, "RGB565", // kRGB_565_GrPixelConfig, "RGBA444", // kRGBA_4444_GrPixelConfig, "RGBA8888", // kRGBA_8888_GrPixelConfig, "BGRA8888", // kBGRA_8888_GrPixelConfig, "ETC1", // kETC1_GrPixelConfig, "LATC", // kLATC_GrPixelConfig, "R11EAC", // kR11_EAC_GrPixelConfig, "ASTC12x12",// kASTC_12x12_GrPixelConfig, "RGBAFloat", // kRGBA_float_GrPixelConfig }; GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); GR_STATIC_ASSERT(7 == kETC1_GrPixelConfig); GR_STATIC_ASSERT(8 == kLATC_GrPixelConfig); GR_STATIC_ASSERT(9 == kR11_EAC_GrPixelConfig); GR_STATIC_ASSERT(10 == kASTC_12x12_GrPixelConfig); GR_STATIC_ASSERT(11 == kRGBA_float_GrPixelConfig); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]); SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]); for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { r.appendf("%s is renderable: %s, with MSAA: %s\n", kConfigNames[i], gNY[fConfigRenderSupport[i][0]], gNY[fConfigRenderSupport[i][1]]); } SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]); for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { r.appendf("%s is uploadable to a texture: %s\n", kConfigNames[i], gNY[fConfigTextureSupport[i]]); } return r; }
static bool dump_png(SkBitmap bitmap, const char* path, const char* md5) { const int w = bitmap.width(), h = bitmap.height(); // First get the bitmap into N32 color format. The next step will work only there. if (bitmap.colorType() != kN32_SkColorType) { SkBitmap n32; if (!bitmap.copyTo(&n32, kN32_SkColorType)) { return false; } bitmap = n32; } // Convert our N32 bitmap into unpremul RGBA for libpng. SkAutoTMalloc<uint32_t> rgba(w*h); if (!bitmap.readPixels(SkImageInfo::Make(w,h, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType), rgba, 4*w, 0,0)) { return false; } // We don't need bitmap anymore. Might as well drop our ref. bitmap.reset(); FILE* f = fopen(path, "wb"); if (!f) { return false; } png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png) { fclose(f); return false; } png_infop info = png_create_info_struct(png); if (!info) { png_destroy_write_struct(&png, &info); fclose(f); return false; } SkString description; description.append("Key: "); for (int i = 0; i < FLAGS_key.count(); i++) { description.appendf("%s ", FLAGS_key[i]); } description.append("Properties: "); for (int i = 0; i < FLAGS_properties.count(); i++) { description.appendf("%s ", FLAGS_properties[i]); } description.appendf("MD5: %s", md5); png_text text[2]; text[0].key = (png_charp)"Author"; text[0].text = (png_charp)"DM dump_png()"; text[0].compression = PNG_TEXT_COMPRESSION_NONE; text[1].key = (png_charp)"Description"; text[1].text = (png_charp)description.c_str(); text[1].compression = PNG_TEXT_COMPRESSION_NONE; png_set_text(png, info, text, 2); png_init_io(png, f); png_set_IHDR(png, info, (png_uint_32)w, (png_uint_32)h, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png, info); for (int j = 0; j < h; j++) { png_bytep row = (png_bytep)(rgba.get() + w*j); png_write_rows(png, &row, 1); } png_write_end(png, info); png_destroy_write_struct(&png, &info); fclose(f); return true; }
static void Run(Task* task) { SkString name = task->src->name(); SkString note; SkString whyBlacklisted = is_blacklisted(task->sink.tag, task->src.tag, task->src.options, name.c_str()); if (!whyBlacklisted.isEmpty()) { note.appendf(" (--blacklist %s)", whyBlacklisted.c_str()); } SkString log; WallTimer timer; timer.start(); if (!FLAGS_dryRun && whyBlacklisted.isEmpty()) { SkBitmap bitmap; SkDynamicMemoryWStream stream; if (FLAGS_pre_log) { SkDebugf("\nRunning %s->%s", name.c_str(), task->sink.tag); } start(task->sink.tag, task->src.tag, task->src.options, name.c_str()); Error err = task->sink->draw(*task->src, &bitmap, &stream, &log); if (!err.isEmpty()) { timer.end(); if (err.isFatal()) { fail(SkStringPrintf("%s %s %s %s: %s", task->sink.tag, task->src.tag, task->src.options, name.c_str(), err.c_str())); } else { note.appendf(" (skipped: %s)", err.c_str()); } done(timer.fWall, task->sink.tag, task->src.tag, task->src.options, name, note, log); return; } SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream()); SkString md5; if (!FLAGS_writePath.isEmpty() || !FLAGS_readPath.isEmpty()) { SkMD5 hash; if (data->getLength()) { hash.writeStream(data, data->getLength()); data->rewind(); } else { // If we're BGRA (Linux, Windows), swizzle over to RGBA (Mac, Android). // This helps eliminate multiple 0-pixel-diff hashes on gold.skia.org. // (Android's general slow speed breaks the tie arbitrarily in RGBA's favor.) // We might consider promoting 565 to RGBA too. if (bitmap.colorType() == kBGRA_8888_SkColorType) { SkBitmap swizzle; SkAssertResult(bitmap.copyTo(&swizzle, kRGBA_8888_SkColorType)); hash.write(swizzle.getPixels(), swizzle.getSize()); } else { hash.write(bitmap.getPixels(), bitmap.getSize()); } } SkMD5::Digest digest; hash.finish(digest); for (int i = 0; i < 16; i++) { md5.appendf("%02x", digest.data[i]); } } if (!FLAGS_readPath.isEmpty() && !gGold.contains(Gold(task->sink.tag, task->src.tag, task->src.options, name, md5))) { fail(SkStringPrintf("%s not found for %s %s %s %s in %s", md5.c_str(), task->sink.tag, task->src.tag, task->src.options, name.c_str(), FLAGS_readPath[0])); } if (!FLAGS_writePath.isEmpty()) { const char* ext = task->sink->fileExtension(); if (data->getLength()) { WriteToDisk(*task, md5, ext, data, data->getLength(), NULL); SkASSERT(bitmap.drawsNothing()); } else if (!bitmap.drawsNothing()) { WriteToDisk(*task, md5, ext, NULL, 0, &bitmap); } } } timer.end(); done(timer.fWall, task->sink.tag, task->src.tag, task->src.options, name, note, log); }
virtual void onDrawContent(SkCanvas* canvas) { struct FillAndName { SkPath::FillType fFill; const char* fName; }; static const FillAndName gFills[] = { {SkPath::kWinding_FillType, "Winding"}, {SkPath::kEvenOdd_FillType, "Even / Odd"}, {SkPath::kInverseWinding_FillType, "Inverse Winding"}, {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, }; struct StyleAndName { SkPaint::Style fStyle; const char* fName; }; static const StyleAndName gStyles[] = { {SkPaint::kFill_Style, "Fill"}, {SkPaint::kStroke_Style, "Stroke"}, {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, }; SkPaint titlePaint; titlePaint.setColor(SK_ColorBLACK); titlePaint.setAntiAlias(true); titlePaint.setLCDRenderText(true); titlePaint.setTextSize(24 * SK_Scalar1); const char title[] = "Empty Paths Drawn Into Rectangle Clips With Indicated Style and Fill"; canvas->drawText(title, strlen(title), 40 * SK_Scalar1, 100*SK_Scalar1, titlePaint); SkRandom rand; SkRect rect = SkRect::MakeWH(125*SK_Scalar1, 100*SK_Scalar1); int i = 0; canvas->save(); canvas->translate(80 * SK_Scalar1, 0); canvas->save(); for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) { for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) { if (0 == i % 4) { canvas->restore(); canvas->translate(0, rect.height() + 50 * SK_Scalar1); canvas->save(); } else { canvas->translate(rect.width() + 100 * SK_Scalar1, 0); } ++i; SkColor color = rand.nextU(); color = 0xff000000| color; // force solid this->drawEmpty(canvas, color, rect, gStyles[style].fStyle, gFills[fill].fFill); SkPaint rectPaint; rectPaint.setColor(SK_ColorBLACK); rectPaint.setStyle(SkPaint::kStroke_Style); rectPaint.setStrokeWidth(-1); rectPaint.setAntiAlias(true); canvas->drawRect(rect, rectPaint); SkString label; label.appendf("%s, %s", gStyles[style].fName, gFills[fill].fName); SkPaint labelPaint; labelPaint.setColor(color); labelPaint.setAntiAlias(true); labelPaint.setLCDRenderText(true); canvas->drawText(label.c_str(), label.size(), 0, rect.height() + 15 * SK_Scalar1, labelPaint); } } canvas->restore(); canvas->restore(); }
SkString* SkObjectParser::PathToString(const SkPath& path) { SkString* mPath = new SkString; mPath->appendf("Path (%d) (", path.getGenerationID()); static const char* gFillStrings[] = { "Winding", "EvenOdd", "InverseWinding", "InverseEvenOdd" }; mPath->append(gFillStrings[path.getFillType()]); mPath->append(", "); static const char* gConvexityStrings[] = { "Unknown", "Convex", "Concave" }; SkASSERT(SkPath::kConcave_Convexity == 2); mPath->append(gConvexityStrings[path.getConvexity()]); mPath->append(", "); if (path.isRect(nullptr)) { mPath->append("isRect, "); } else { mPath->append("isNotRect, "); } if (path.isOval(nullptr)) { mPath->append("isOval, "); } else { mPath->append("isNotOval, "); } SkRRect rrect; if (path.isRRect(&rrect)) { mPath->append("isRRect, "); } else { mPath->append("isNotRRect, "); } mPath->appendS32(path.countVerbs()); mPath->append("V, "); mPath->appendS32(path.countPoints()); mPath->append("P): "); static const char* gVerbStrings[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" }; static const int gPtsPerVerb[] = { 1, 1, 2, 2, 3, 0, 0 }; static const int gPtOffsetPerVerb[] = { 0, 1, 1, 1, 1, 0, 0 }; SkASSERT(SkPath::kDone_Verb == 6); SkPath::Iter iter(const_cast<SkPath&>(path), false); SkPath::Verb verb; SkPoint points[4]; for(verb = iter.next(points, false); verb != SkPath::kDone_Verb; verb = iter.next(points, false)) { mPath->append(gVerbStrings[verb]); mPath->append(" "); for (int i = 0; i < gPtsPerVerb[verb]; ++i) { mPath->append("("); mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fX); mPath->append(", "); mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fY); mPath->append(")"); } if (SkPath::kConic_Verb == verb) { mPath->append("("); mPath->appendScalar(iter.conicWeight()); mPath->append(")"); } mPath->append(" "); } SkString* boundStr = SkObjectParser::RectToString(path.getBounds(), " Bound: "); if (boundStr) { mPath->append(*boundStr); delete boundStr; } return mPath; }
SkString UnderJoin(const char* a, const char* b) { SkString s; s.appendf("%s_%s", a, b); return s; }
SkString GrDrawTargetCaps::dump() const { SkString r; static const char* gNY[] = {"NO", "YES"}; r.appendf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]); r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]); r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]); r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]); r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]); r.appendf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]); r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]); r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]); r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]); r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); r.appendf("Max Texture Size : %d\n", fMaxTextureSize); r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); r.appendf("Max Sample Count : %d\n", fMaxSampleCount); static const char* kConfigNames[] = { "Unknown", // kUnknown_GrPixelConfig "Alpha8", // kAlpha_8_GrPixelConfig, "Index8", // kIndex_8_GrPixelConfig, "RGB565", // kRGB_565_GrPixelConfig, "RGBA444", // kRGBA_4444_GrPixelConfig, "RGBA8888", // kRGBA_8888_GrPixelConfig, "BGRA8888", // kBGRA_8888_GrPixelConfig, }; GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]); SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]); for (size_t i = 0; i < SK_ARRAY_COUNT(kConfigNames); ++i) { if (i != kUnknown_GrPixelConfig) { r.appendf("%s is renderable: %s, with MSAA: %s\n", kConfigNames[i], gNY[fConfigRenderSupport[i][0]], gNY[fConfigRenderSupport[i][1]]); } } return r; }
void onDraw(SkCanvas* canvas) override { SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)}; static const int kMaxSrcRectSize = 1 << (SkNextLog2(gBmpSize) + 2); static const int kPadX = 30; static const int kPadY = 40; SkPaint paint; paint.setAlpha(0x20); canvas->drawBitmapRect(fLargeBitmap, SkRect::MakeIWH(gSize, gSize), &paint); canvas->translate(SK_Scalar1 * kPadX / 2, SK_Scalar1 * kPadY / 2); SkPaint blackPaint; SkScalar titleHeight = SK_Scalar1 * 24; blackPaint.setColor(SK_ColorBLACK); blackPaint.setTextSize(titleHeight); blackPaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&blackPaint); SkString title; title.printf("Bitmap size: %d x %d", gBmpSize, gBmpSize); canvas->drawText(title.c_str(), title.size(), 0, titleHeight, blackPaint); canvas->translate(0, SK_Scalar1 * kPadY / 2 + titleHeight); int rowCount = 0; canvas->save(); for (int w = 1; w <= kMaxSrcRectSize; w *= 4) { for (int h = 1; h <= kMaxSrcRectSize; h *= 4) { SkIRect srcRect = SkIRect::MakeXYWH((gBmpSize - w) / 2, (gBmpSize - h) / 2, w, h); fProc(canvas, fImage, fLargeBitmap, srcRect, dstRect); SkString label; label.appendf("%d x %d", w, h); blackPaint.setAntiAlias(true); blackPaint.setStyle(SkPaint::kFill_Style); blackPaint.setTextSize(SK_Scalar1 * 10); SkScalar baseline = dstRect.height() + blackPaint.getTextSize() + SK_Scalar1 * 3; canvas->drawText(label.c_str(), label.size(), 0, baseline, blackPaint); blackPaint.setStyle(SkPaint::kStroke_Style); blackPaint.setStrokeWidth(SK_Scalar1); blackPaint.setAntiAlias(false); canvas->drawRect(dstRect, blackPaint); canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0); ++rowCount; if ((dstRect.width() + kPadX) * rowCount > gSize) { canvas->restore(); canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY); canvas->save(); rowCount = 0; } } } { // test the following code path: // SkGpuDevice::drawPath() -> SkGpuDevice::drawWithMaskFilter() SkIRect srcRect; SkPaint paint; SkBitmap bm; bm = make_chessbm(5, 5); paint.setFilterQuality(kLow_SkFilterQuality); srcRect.setXYWH(1, 1, 3, 3); SkMaskFilter* mf = SkBlurMaskFilter::Create( kNormal_SkBlurStyle, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)), SkBlurMaskFilter::kHighQuality_BlurFlag | SkBlurMaskFilter::kIgnoreTransform_BlurFlag); paint.setMaskFilter(mf)->unref(); canvas->drawBitmapRect(bm, srcRect, dstRect, &paint); } }
void GrGLPerlinNoise::emitCode(GrGLFPBuilder* builder, const GrFragmentProcessor&, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { sk_ignore_unused_variable(inputColor); GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); SkString vCoords = fsBuilder->ensureFSCoords2D(coords, 0); fBaseFrequencyUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "baseFrequency"); const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni); fAlphaUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "alpha"); const char* alphaUni = builder->getUniformCStr(fAlphaUni); const char* stitchDataUni = NULL; if (fStitchTiles) { fStitchDataUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "stitchData"); stitchDataUni = builder->getUniformCStr(fStitchDataUni); } // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8 const char* chanCoordR = "0.125"; const char* chanCoordG = "0.375"; const char* chanCoordB = "0.625"; const char* chanCoordA = "0.875"; const char* chanCoord = "chanCoord"; const char* stitchData = "stitchData"; const char* ratio = "ratio"; const char* noiseVec = "noiseVec"; const char* noiseSmooth = "noiseSmooth"; const char* floorVal = "floorVal"; const char* fractVal = "fractVal"; const char* uv = "uv"; const char* ab = "ab"; const char* latticeIdx = "latticeIdx"; const char* bcoords = "bcoords"; const char* lattice = "lattice"; const char* inc8bit = "0.00390625"; // 1.0 / 256.0 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a // [-1,1] vector and perform a dot product between that vector and the provided vector. const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);"; // Add noise function static const GrGLShaderVar gPerlinNoiseArgs[] = { GrGLShaderVar(chanCoord, kFloat_GrSLType), GrGLShaderVar(noiseVec, kVec2f_GrSLType) }; static const GrGLShaderVar gPerlinNoiseStitchArgs[] = { GrGLShaderVar(chanCoord, kFloat_GrSLType), GrGLShaderVar(noiseVec, kVec2f_GrSLType), GrGLShaderVar(stitchData, kVec2f_GrSLType) }; SkString noiseCode; noiseCode.appendf("\tvec4 %s;\n", floorVal); noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec); noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal); noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec); // smooth curve : t * t * (3 - 2 * t) noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);", noiseSmooth, fractVal, fractVal, fractVal); // Adjust frequencies if we're stitching tiles if (fStitchTiles) { noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }", floorVal, stitchData, floorVal, stitchData); noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }", floorVal, stitchData, floorVal, stitchData); noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }", floorVal, stitchData, floorVal, stitchData); noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }", floorVal, stitchData, floorVal, stitchData); } // Get texture coordinates and normalize noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n", floorVal, floorVal); // Get permutation for x { SkString xCoords(""); xCoords.appendf("vec2(%s.x, 0.5)", floorVal); noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx); fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); noiseCode.append(".r;"); } // Get permutation for x + 1 { SkString xCoords(""); xCoords.appendf("vec2(%s.z, 0.5)", floorVal); noiseCode.appendf("\n\t%s.y = ", latticeIdx); fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); noiseCode.append(".r;"); } #if defined(SK_BUILD_FOR_ANDROID) // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3). // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725 // (or 0.484368 here). The following rounding operation prevents these precision issues from // affecting the result of the noise by making sure that we only have multiples of 1/255. // (Note that 1/255 is about 0.003921569, which is the value used here). noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);", latticeIdx, latticeIdx); #endif // Get (x,y) coordinates with the permutated x noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal); noiseCode.appendf("\n\n\tvec2 %s;", uv); // Compute u, at offset (0,0) { SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord); noiseCode.appendf("\n\tvec4 %s = ", lattice); fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.x = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); } noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal); // Compute v, at offset (-1,0) { SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.y = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); } // Compute 'a' as a linear interpolation of 'u' and 'v' noiseCode.appendf("\n\tvec2 %s;", ab); noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal); // Compute v, at offset (-1,-1) { SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.y = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); } noiseCode.appendf("\n\t%s.x += 1.0;", fractVal); // Compute u, at offset (0,-1) { SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.x = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); } // Compute 'b' as a linear interpolation of 'u' and 'v' noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); // Compute the noise as a linear interpolation of 'a' and 'b' noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth); SkString noiseFuncName; if (fStitchTiles) { fsBuilder->emitFunction(kFloat_GrSLType, "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs), gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName); } else { fsBuilder->emitFunction(kFloat_GrSLType, "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs), gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName); } // There are rounding errors if the floor operation is not performed here fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", noiseVec, vCoords.c_str(), baseFrequencyUni); // Clear the color accumulator fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", outputColor); if (fStitchTiles) { // Set up TurbulenceInitial stitch values. fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni); } fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); // Loop over all octaves fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves); fsBuilder->codeAppendf("\n\t\t\t%s += ", outputColor); if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { fsBuilder->codeAppend("abs("); } if (fStitchTiles) { fsBuilder->codeAppendf( "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); } else { fsBuilder->codeAppendf( "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", noiseFuncName.c_str(), chanCoordR, noiseVec, noiseFuncName.c_str(), chanCoordG, noiseVec, noiseFuncName.c_str(), chanCoordB, noiseVec, noiseFuncName.c_str(), chanCoordA, noiseVec); } if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { fsBuilder->codeAppendf(")"); // end of "abs(" } fsBuilder->codeAppendf(" * %s;", ratio); fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); if (fStitchTiles) { fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); } fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves if (fType == SkPerlinNoiseShader::kFractalNoise_Type) { // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 // by fractalNoise and (turbulenceFunctionResult) by turbulence. fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor); } fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni); // Clamp values fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor); // Pre-multiply the result fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", outputColor, outputColor, outputColor, outputColor); }
bool CopyTilesRenderer::render(SkBitmap** out) { int i = 0; bool success = true; SkBitmap dst; for (int x = 0; x < this->getViewWidth(); x += fLargeTileWidth) { for (int y = 0; y < this->getViewHeight(); y += fLargeTileHeight) { SkAutoCanvasRestore autoRestore(fCanvas, true); // Translate so that we draw the correct portion of the picture. // Perform a postTranslate so that the scaleFactor does not interfere with the // positioning. SkMatrix mat(fCanvas->getTotalMatrix()); mat.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); fCanvas->setMatrix(mat); // Draw the picture if (fUseMultiPictureDraw) { SkMultiPictureDraw mpd; mpd.add(fCanvas, fPicture); mpd.draw(); } else { fCanvas->drawPicture(fPicture); } // Now extract the picture into tiles SkBitmap baseBitmap; fCanvas->readPixels(SkIRect::MakeSize(fCanvas->getBaseLayerSize()), &baseBitmap); SkIRect subset; for (int tileY = 0; tileY < fLargeTileHeight; tileY += this->getTileHeight()) { for (int tileX = 0; tileX < fLargeTileWidth; tileX += this->getTileWidth()) { subset.set(tileX, tileY, tileX + this->getTileWidth(), tileY + this->getTileHeight()); SkDEBUGCODE(bool extracted =) baseBitmap.extractSubset(&dst, subset); SkASSERT(extracted); if (!fWritePath.isEmpty()) { // Similar to write() in PictureRenderer.cpp, but just encodes // a bitmap directly. // TODO: Share more common code with write() to do this, to properly // write out the JSON summary, etc. SkString pathWithNumber = SkOSPath::Join(fWritePath.c_str(), fInputFilename.c_str()); pathWithNumber.remove(pathWithNumber.size() - 4, 4); pathWithNumber.appendf("%i.png", i++); SkBitmap copy; #if SK_SUPPORT_GPU if (isUsingGpuDevice()) { dst.pixelRef()->readPixels(©, &subset); } else { #endif dst.copyTo(©); #if SK_SUPPORT_GPU } #endif success &= SkImageEncoder::EncodeFile(pathWithNumber.c_str(), copy, SkImageEncoder::kPNG_Type, 100); } } } } } return success; }
SkString GrCaps::dump() const { SkString r; static const char* gNY[] = {"NO", "YES"}; r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); r.appendf("sRGB Support : %s\n", gNY[fSRGBSupport]); r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]); r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]); r.appendf("Reuse Scratch Buffers : %s\n", gNY[fReuseScratchBuffers]); r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]); r.appendf("Compressed Update Support : %s\n", gNY[fCompressedTexSubImageSupport]); r.appendf("Oversized Stencil Support : %s\n", gNY[fOversizedStencilSupport]); r.appendf("Texture Barrier Support : %s\n", gNY[fTextureBarrierSupport]); r.appendf("Sample Locations Support : %s\n", gNY[fSampleLocationsSupport]); r.appendf("Uses Mixed Samples : %s\n", gNY[fUsesMixedSamples]); r.appendf("Supports instanced draws : %s\n", gNY[fSupportsInstancedDraws]); r.appendf("Full screen clear is free : %s\n", gNY[fFullClearIsFree]); r.appendf("Must clear buffer memory : %s\n", gNY[fMustClearUploadedBufferData]); r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]); r.appendf("Draw Instead of TexSubImage [workaround] : %s\n", gNY[fUseDrawInsteadOfPartialRenderTargetWrite]); r.appendf("Prefer VRAM Use over flushes [workaround] : %s\n", gNY[fPreferVRAMUseOverFlushes]); if (this->advancedBlendEquationSupport()) { r.appendf("Advanced Blend Equation Blacklist : 0x%x\n", fAdvBlendEqBlacklist); } r.appendf("Max Vertex Attributes : %d\n", fMaxVertexAttributes); r.appendf("Max Texture Size : %d\n", fMaxTextureSize); r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize); r.appendf("Max Color Sample Count : %d\n", fMaxColorSampleCount); r.appendf("Max Stencil Sample Count : %d\n", fMaxStencilSampleCount); r.appendf("Max Raster Samples : %d\n", fMaxRasterSamples); static const char* kBlendEquationSupportNames[] = { "Basic", "Advanced", "Advanced Coherent", }; GR_STATIC_ASSERT(0 == kBasic_BlendEquationSupport); GR_STATIC_ASSERT(1 == kAdvanced_BlendEquationSupport); GR_STATIC_ASSERT(2 == kAdvancedCoherent_BlendEquationSupport); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1); r.appendf("Blend Equation Support : %s\n", kBlendEquationSupportNames[fBlendEquationSupport]); r.appendf("Map Buffer Support : %s\n", map_flags_to_string(fMapBufferFlags).c_str()); static const char* kConfigNames[] = { "Unknown", // kUnknown_GrPixelConfig "Alpha8", // kAlpha_8_GrPixelConfig, "Index8", // kIndex_8_GrPixelConfig, "RGB565", // kRGB_565_GrPixelConfig, "RGBA444", // kRGBA_4444_GrPixelConfig, "RGBA8888", // kRGBA_8888_GrPixelConfig, "BGRA8888", // kBGRA_8888_GrPixelConfig, "SRGBA8888",// kSRGBA_8888_GrPixelConfig, "SBGRA8888",// kSBGRA_8888_GrPixelConfig, "ETC1", // kETC1_GrPixelConfig, "LATC", // kLATC_GrPixelConfig, "R11EAC", // kR11_EAC_GrPixelConfig, "ASTC12x12",// kASTC_12x12_GrPixelConfig, "RGBAFloat",// kRGBA_float_GrPixelConfig "AlphaHalf",// kAlpha_half_GrPixelConfig "RGBAHalf", // kRGBA_half_GrPixelConfig }; GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig); GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig); GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig); GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig); GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig); GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig); GR_STATIC_ASSERT(8 == kSBGRA_8888_GrPixelConfig); GR_STATIC_ASSERT(9 == kETC1_GrPixelConfig); GR_STATIC_ASSERT(10 == kLATC_GrPixelConfig); GR_STATIC_ASSERT(11 == kR11_EAC_GrPixelConfig); GR_STATIC_ASSERT(12 == kASTC_12x12_GrPixelConfig); GR_STATIC_ASSERT(13 == kRGBA_float_GrPixelConfig); GR_STATIC_ASSERT(14 == kAlpha_half_GrPixelConfig); GR_STATIC_ASSERT(15 == kRGBA_half_GrPixelConfig); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, false)); SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, true)); for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { GrPixelConfig config = static_cast<GrPixelConfig>(i); r.appendf("%s is renderable: %s, with MSAA: %s\n", kConfigNames[i], gNY[this->isConfigRenderable(config, false)], gNY[this->isConfigRenderable(config, true)]); } SkASSERT(!this->isConfigTexturable(kUnknown_GrPixelConfig)); for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) { GrPixelConfig config = static_cast<GrPixelConfig>(i); r.appendf("%s is uploadable to a texture: %s\n", kConfigNames[i], gNY[this->isConfigTexturable(config)]); } return r; }
SkString GrGLCaps::dump() const { SkString r = INHERITED::dump(); r.appendf("--- GL-Specific ---\n"); for (int i = 0; i < fStencilFormats.count(); ++i) { r.appendf("Stencil Format %d, stencil bits: %02d, total bits: %02d\n", i, fStencilFormats[i].fStencilBits, fStencilFormats[i].fTotalBits); } static const char* kMSFBOExtStr[] = { "None", "ARB", "EXT", "ES 3.0", "Apple", "IMG MS To Texture", "EXT MS To Texture", }; GR_STATIC_ASSERT(0 == kNone_MSFBOType); GR_STATIC_ASSERT(1 == kDesktop_ARB_MSFBOType); GR_STATIC_ASSERT(2 == kDesktop_EXT_MSFBOType); GR_STATIC_ASSERT(3 == kES_3_0_MSFBOType); GR_STATIC_ASSERT(4 == kES_Apple_MSFBOType); GR_STATIC_ASSERT(5 == kES_IMG_MsToTexture_MSFBOType); GR_STATIC_ASSERT(6 == kES_EXT_MsToTexture_MSFBOType); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMSFBOExtStr) == kLast_MSFBOType + 1); static const char* kFBFetchTypeStr[] = { "None", "EXT", "NV", }; GR_STATIC_ASSERT(0 == kNone_FBFetchType); GR_STATIC_ASSERT(1 == kEXT_FBFetchType); GR_STATIC_ASSERT(2 == kNV_FBFetchType); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFBFetchTypeStr) == kLast_FBFetchType + 1); static const char* kInvalidateFBTypeStr[] = { "None", "Discard", "Invalidate", }; GR_STATIC_ASSERT(0 == kNone_InvalidateFBType); GR_STATIC_ASSERT(1 == kDiscard_InvalidateFBType); GR_STATIC_ASSERT(2 == kInvalidate_InvalidateFBType); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kInvalidateFBTypeStr) == kLast_InvalidateFBType + 1); static const char* kMapBufferTypeStr[] = { "None", "MapBuffer", "MapBufferRange", "Chromium", }; GR_STATIC_ASSERT(0 == kNone_MapBufferType); GR_STATIC_ASSERT(1 == kMapBuffer_MapBufferType); GR_STATIC_ASSERT(2 == kMapBufferRange_MapBufferType); GR_STATIC_ASSERT(3 == kChromium_MapBufferType); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMapBufferTypeStr) == kLast_MapBufferType + 1); r.appendf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO")); r.appendf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]); r.appendf("FB Fetch Type: %s\n", kFBFetchTypeStr[fFBFetchType]); r.appendf("Invalidate FB Type: %s\n", kInvalidateFBTypeStr[fInvalidateFBType]); r.appendf("Map Buffer Type: %s\n", kMapBufferTypeStr[fMapBufferType]); r.appendf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors); r.appendf("Max FS Texture Units: %d\n", fMaxFragmentTextureUnits); if (!fIsCoreProfile) { r.appendf("Max Fixed Function Texture Coords: %d\n", fMaxFixedFunctionTextureCoords); } r.appendf("Max Vertex Attributes: %d\n", fMaxVertexAttributes); r.appendf("Support RGBA8 Render Buffer: %s\n", (fRGBA8RenderbufferSupport ? "YES": "NO")); r.appendf("BGRA is an internal format: %s\n", (fBGRAIsInternalFormat ? "YES": "NO")); r.appendf("Support texture swizzle: %s\n", (fTextureSwizzleSupport ? "YES": "NO")); r.appendf("Unpack Row length support: %s\n", (fUnpackRowLengthSupport ? "YES": "NO")); r.appendf("Unpack Flip Y support: %s\n", (fUnpackFlipYSupport ? "YES": "NO")); r.appendf("Pack Row length support: %s\n", (fPackRowLengthSupport ? "YES": "NO")); r.appendf("Pack Flip Y support: %s\n", (fPackFlipYSupport ? "YES": "NO")); r.appendf("Texture Usage support: %s\n", (fTextureUsageSupport ? "YES": "NO")); r.appendf("Texture Storage support: %s\n", (fTexStorageSupport ? "YES": "NO")); r.appendf("GL_R support: %s\n", (fTextureRedSupport ? "YES": "NO")); r.appendf("GL_ARB_imaging support: %s\n", (fImagingSupport ? "YES": "NO")); r.appendf("Two Format Limit: %s\n", (fTwoFormatLimit ? "YES": "NO")); r.appendf("Fragment coord conventions support: %s\n", (fFragCoordsConventionSupport ? "YES": "NO")); r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO")); r.appendf("Use non-VBO for dynamic data: %s\n", (fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO")); r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO")); r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO")); return r; }