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("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("Oversized Stencil Support : %s\n", gNY[fOversizedStencilSupport]); 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, "SRGBA8888",// kSRGBA_8888_GrPixelConfig, "ETC1", // kETC1_GrPixelConfig, "LATC", // kLATC_GrPixelConfig, "R11EAC", // kR11_EAC_GrPixelConfig, "ASTC12x12",// kASTC_12x12_GrPixelConfig, "RGBAFloat",// kRGBA_float_GrPixelConfig "AlphaHalf",// kAlpha_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 == kETC1_GrPixelConfig); GR_STATIC_ASSERT(9 == kLATC_GrPixelConfig); GR_STATIC_ASSERT(10 == kR11_EAC_GrPixelConfig); GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig); GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig); GR_STATIC_ASSERT(13 == kAlpha_half_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]]); } r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]); for (int s = 0; s < kGrShaderTypeCount; ++s) { GrShaderType shaderType = static_cast<GrShaderType>(s); r.appendf("\t%s:\n", shader_type_to_string(shaderType)); for (int p = 0; p < kGrSLPrecisionCount; ++p) { if (fFloatPrecisions[s][p].supported()) { GrSLPrecision precision = static_cast<GrSLPrecision>(p); r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n", precision_to_string(precision), fFloatPrecisions[s][p].fLogRangeLow, fFloatPrecisions[s][p].fLogRangeHigh, fFloatPrecisions[s][p].fBits); } } } return r; }
virtual const char* onGetName() { return fName.c_str(); }
void PictureBenchmark::run(SkPicture* pict) { SkASSERT(pict); if (NULL == pict) { return; } SkASSERT(fRenderer != NULL); if (NULL == fRenderer) { return; } fRenderer->init(pict, NULL, NULL, NULL, false); // We throw this away to remove first time effects (such as paging in this program) fRenderer->setup(); if (fPreprocess) { if (NULL != fRenderer->getCanvas()) { fRenderer->getCanvas()->EXPERIMENTAL_optimize(pict); } } fRenderer->render(NULL); fRenderer->resetState(true); // flush, swapBuffers and Finish if (fPreprocess) { if (NULL != fRenderer->getCanvas()) { fRenderer->getCanvas()->EXPERIMENTAL_purge(pict); } } if (fPurgeDecodedTex) { fRenderer->purgeTextures(); } bool usingGpu = false; #if SK_SUPPORT_GPU usingGpu = fRenderer->isUsingGpuDevice(); #endif uint32_t timerTypes = fTimerTypes; if (!usingGpu) { timerTypes &= ~TimerData::kGpu_Flag; } SkString timeFormat; if (TimerData::kPerIter_Result == fTimerResult) { timeFormat = fRenderer->getPerIterTimeFormat(); } else { timeFormat = fRenderer->getNormalTimeFormat(); } static const int kNumInnerLoops = 10; int numOuterLoops = 1; int numInnerLoops = fRepeats; if (TimerData::kPerIter_Result == fTimerResult && fRepeats > 1) { // interpret this flag combination to mean: generate 'fRepeats' // numbers by averaging each rendering 'kNumInnerLoops' times numOuterLoops = fRepeats; numInnerLoops = kNumInnerLoops; } if (fTimeIndividualTiles) { TiledPictureRenderer* tiledRenderer = fRenderer->getTiledRenderer(); SkASSERT(tiledRenderer && tiledRenderer->supportsTimingIndividualTiles()); if (NULL == tiledRenderer || !tiledRenderer->supportsTimingIndividualTiles()) { return; } int xTiles, yTiles; if (!tiledRenderer->tileDimensions(xTiles, yTiles)) { return; } int x, y; while (tiledRenderer->nextTile(x, y)) { // There are two timers, which will behave slightly differently: // 1) longRunningTimer, along with perTileTimerData, will time how long it takes to draw // one tile fRepeats times, and take the average. As such, it will not respect the // logPerIter or printMin options, since it does not know the time per iteration. It // will also be unable to call flush() for each tile. // The goal of this timer is to make up for a system timer that is not precise enough to // measure the small amount of time it takes to draw one tile once. // // 2) perTileTimer, along with perTileTimerData, will record each run separately, and // then take the average. As such, it supports logPerIter and printMin options. // // Although "legal", having two gpu timers running at the same time // seems to cause problems (i.e., INVALID_OPERATIONs) on several // platforms. To work around this, we disable the gpu timer on the // long running timer. SkAutoTDelete<Timer> longRunningTimer(this->setupTimer()); TimerData longRunningTimerData(numOuterLoops); for (int outer = 0; outer < numOuterLoops; ++outer) { SkAutoTDelete<Timer> perTileTimer(this->setupTimer(false)); TimerData perTileTimerData(numInnerLoops); longRunningTimer->start(); for (int inner = 0; inner < numInnerLoops; ++inner) { perTileTimer->start(); tiledRenderer->drawCurrentTile(); perTileTimer->truncatedEnd(); tiledRenderer->resetState(false); // flush & swapBuffers, but don't Finish perTileTimer->end(); SkAssertResult(perTileTimerData.appendTimes(perTileTimer.get())); if (fPurgeDecodedTex) { fRenderer->purgeTextures(); } } longRunningTimer->truncatedEnd(); tiledRenderer->resetState(true); // flush, swapBuffers and Finish longRunningTimer->end(); SkAssertResult(longRunningTimerData.appendTimes(longRunningTimer.get())); } fWriter->tileConfig(tiledRenderer->getConfigName()); fWriter->tileMeta(x, y, xTiles, yTiles); // TODO(borenet): Turn off per-iteration tile time reporting for now. // Avoiding logging the time for every iteration for each tile cuts // down on data file size by a significant amount. Re-enable this once // we're loading the bench data directly into a data store and are no // longer generating SVG graphs. #if 0 fWriter->tileData( &perTileTimerData, timeFormat.c_str(), fTimerResult, timerTypes); #endif if (fPurgeDecodedTex) { fWriter->addTileFlag(PictureResultsWriter::kPurging); } fWriter->addTileFlag(PictureResultsWriter::kAvg); fWriter->tileData( &longRunningTimerData, tiledRenderer->getNormalTimeFormat().c_str(), TimerData::kAvg_Result, timerTypes, numInnerLoops); } } else { SkAutoTDelete<Timer> longRunningTimer(this->setupTimer()); TimerData longRunningTimerData(numOuterLoops); for (int outer = 0; outer < numOuterLoops; ++outer) { SkAutoTDelete<Timer> perRunTimer(this->setupTimer(false)); TimerData perRunTimerData(numInnerLoops); longRunningTimer->start(); for (int inner = 0; inner < numInnerLoops; ++inner) { fRenderer->setup(); perRunTimer->start(); fRenderer->render(NULL); perRunTimer->truncatedEnd(); fRenderer->resetState(false); // flush & swapBuffers, but don't Finish perRunTimer->end(); SkAssertResult(perRunTimerData.appendTimes(perRunTimer.get())); if (fPreprocess) { if (NULL != fRenderer->getCanvas()) { fRenderer->getCanvas()->EXPERIMENTAL_purge(pict); } } if (fPurgeDecodedTex) { fRenderer->purgeTextures(); } } longRunningTimer->truncatedEnd(); fRenderer->resetState(true); // flush, swapBuffers and Finish longRunningTimer->end(); SkAssertResult(longRunningTimerData.appendTimes(longRunningTimer.get())); } fWriter->tileConfig(fRenderer->getConfigName()); if (fPurgeDecodedTex) { fWriter->addTileFlag(PictureResultsWriter::kPurging); } // Beware - since the per-run-timer doesn't ever include a glFinish it can // report a lower time then the long-running-timer #if 0 fWriter->tileData( &perRunTimerData, timeFormat.c_str(), fTimerResult, timerTypes); #else fWriter->tileData( &longRunningTimerData, timeFormat.c_str(), fTimerResult, timerTypes, numInnerLoops); #endif } fRenderer->end(); }
virtual void onDraw(SkCanvas* canvas) { static const int kBmpSize = 2048; if (fLargeBitmap.isNull()) { makebm(&fLargeBitmap, kBmpSize, kBmpSize); } SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)}; static const int kMaxSrcRectSize = 1 << (SkNextLog2(kBmpSize) + 2); static const int kPadX = 30; static const int kPadY = 40; SkPaint paint; paint.setAlpha(0x20); canvas->drawBitmapRect(fLargeBitmap, NULL, SkRect::MakeWH(gSize * SK_Scalar1, gSize * SK_Scalar1), &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); SkString title; title.printf("Bitmap size: %d x %d", kBmpSize, kBmpSize); 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((kBmpSize - w) / 2, (kBmpSize - h) / 2, w, h); canvas->drawBitmapRect(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.setFilterLevel(SkPaint::kLow_FilterLevel); 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); } }
SkString onShortName() override { SkString str = SkString("etc1bitmap_"); str.append(this->fileExtension()); return str; }
bool SkSVGPaint::writeChangedElements(SkSVGParser& parser, SkSVGPaint& current, bool* changed) { SkSVGPaint& lastState = parser.fLastFlush; for (int index = kInitial + 1; index < kTerminal; index++) { SkString* topAttr = current[index]; size_t attrLength = topAttr->size(); if (attrLength == 0) continue; const char* attrValue = topAttr->c_str(); SkString* lastAttr = lastState[index]; switch(index) { case kClipPath: case kClipRule: // !!! need to add this outside of paint break; case kEnableBackground: // !!! don't know what to do with this break; case kFill: goto addColor; case kFillRule: case kFilter: break; case kFontFamily: parser._startElement("typeface"); parser._addAttributeLen("fontName", attrValue, attrLength); parser._endElement(); // typeface break; case kFontSize: case kLetterSpacing: break; case kMask: case kOpacity: if (changed[kStroke] == false && changed[kFill] == false) { parser._startElement("color"); SkString& opacity = current.f_opacity; parser._addAttributeLen("color", parser.fLastColor.c_str(), parser.fLastColor.size()); parser._addAttributeLen("alpha", opacity.c_str(), opacity.size()); parser._endElement(); // color } break; case kStopColor: break; case kStopOpacity: break; case kStroke: addColor: if (strncmp(lastAttr->c_str(), "url(", 4) == 0 && strncmp(attrValue, "url(", 4) != 0) { parser._startElement("shader"); parser._endElement(); } if (topAttr->equals(*lastAttr)) continue; { bool urlRef = strncmp(attrValue, "url(", 4) == 0; bool colorNone = strcmp(attrValue, "none") == 0; bool lastEqual = parser.fLastColor.equals(attrValue, attrLength); bool newColor = urlRef == false && colorNone == false && lastEqual == false; if (newColor || changed[kOpacity]) { parser._startElement("color"); if (newColor || changed[kOpacity]) { parser._addAttributeLen("color", attrValue, attrLength); parser.fLastColor.set(attrValue, attrLength); } if (changed[kOpacity]) { SkString& opacity = current.f_opacity; parser._addAttributeLen("alpha", opacity.c_str(), opacity.size()); } parser._endElement(); // color } } break; case kStroke_Dasharray: parser._startElement("dash"); SkSVGParser::ConvertToArray(*topAttr); parser._addAttribute("intervals", topAttr->c_str()); parser._endElement(); // dash break; case kStroke_Linecap: case kStroke_Linejoin: case kStroke_Miterlimit: case kStroke_Width: case kStyle: case kTransform: break; default: SkASSERT(0); return false; } } return true; }
const char* onGetName() override { return fName.c_str(); }
GrMipMapBench(int w, int h) : fW(w), fH(h) { fName.printf("gr_mipmap_build_%dx%d", w, h); }
static void output_font(SkTypeface* face, const char* name, SkTypeface::Style style, const char* used, FILE* out) { int emSize = face->getUnitsPerEm() * 2; SkPaint paint; paint.setAntiAlias(true); paint.setTextAlign(SkPaint::kLeft_Align); paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); paint.setTextSize(emSize); SkSafeUnref(paint.setTypeface(face)); SkTDArray<SkPath::Verb> verbs; SkTDArray<unsigned> charCodes; SkTDArray<SkScalar> widths; SkString ptsOut; output_path_data(paint, used, emSize, &ptsOut, &verbs, &charCodes, &widths); SkString fontnameStr(name); SkString strippedStr = strip_spaces(fontnameStr); strippedStr.appendf("%s", gStyleName[style]); const char* fontname = strippedStr.c_str(); fprintf(out, "const SkScalar %sPoints[] = {\n", fontname); ptsOut = strip_final(ptsOut); fprintf(out, "%s", ptsOut.c_str()); fprintf(out, "\n};\n\n"); fprintf(out, "const unsigned char %sVerbs[] = {\n", fontname); int verbCount = verbs.count(); int outChCount = 0; for (int index = 0; index < verbCount;) { SkPath::Verb verb = verbs[index]; SkASSERT(verb >= SkPath::kMove_Verb && verb <= SkPath::kDone_Verb); SkASSERT((unsigned) verb == (unsigned char) verb); fprintf(out, "%u", verb); if (++index < verbCount) { outChCount += 3; fprintf(out, "%c", ','); if (outChCount >= kMaxLineLength) { outChCount = 0; fprintf(out, "%c", '\n'); } else { fprintf(out, "%c", ' '); } } } fprintf(out, "\n};\n\n"); fprintf(out, "const unsigned %sCharCodes[] = {\n", fontname); int offsetCount = charCodes.count(); for (int index = 0; index < offsetCount;) { unsigned offset = charCodes[index]; fprintf(out, "%u", offset); if (++index < offsetCount) { outChCount += offset_str_len(offset) + 2; fprintf(out, "%c", ','); if (outChCount >= kMaxLineLength) { outChCount = 0; fprintf(out, "%c", '\n'); } else { fprintf(out, "%c", ' '); } } } fprintf(out, "\n};\n\n"); SkString widthsStr; fprintf(out, "const SkFixed %sWidths[] = {\n", fontname); for (int index = 0; index < offsetCount; ++index) { output_fixed(widths[index], emSize, &widthsStr); } widthsStr = strip_final(widthsStr); fprintf(out, "%s\n};\n\n", widthsStr.c_str()); fprintf(out, "const int %sCharCodesCount = (int) SK_ARRAY_COUNT(%sCharCodes);\n\n", fontname, fontname); SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); fprintf(out, "const SkPaint::FontMetrics %sMetrics = {\n", fontname); SkString metricsStr; metricsStr.printf("0x%08x, ", metrics.fFlags); output_scalar(metrics.fTop, emSize, &metricsStr); output_scalar(metrics.fAscent, emSize, &metricsStr); output_scalar(metrics.fDescent, emSize, &metricsStr); output_scalar(metrics.fBottom, emSize, &metricsStr); output_scalar(metrics.fLeading, emSize, &metricsStr); output_scalar(metrics.fAvgCharWidth, emSize, &metricsStr); output_scalar(metrics.fMaxCharWidth, emSize, &metricsStr); output_scalar(metrics.fXMin, emSize, &metricsStr); output_scalar(metrics.fXMax, emSize, &metricsStr); output_scalar(metrics.fXHeight, emSize, &metricsStr); output_scalar(metrics.fCapHeight, emSize, &metricsStr); output_scalar(metrics.fUnderlineThickness, emSize, &metricsStr); output_scalar(metrics.fUnderlinePosition, emSize, &metricsStr); metricsStr = strip_final(metricsStr); fprintf(out, "%s\n};\n\n", metricsStr.c_str()); }
int tool_main(int argc, char** argv) { SkString usage; usage.printf("Time drawing .skp files.\n" "\tPossible arguments for --filter: [%s]\n\t\t[%s]", filterTypesUsage().c_str(), filterFlagsUsage().c_str()); SkCommandLineFlags::SetUsage(usage.c_str()); SkCommandLineFlags::Parse(argc, argv); if (FLAGS_repeat < 1) { SkString error; error.printf("--repeats must be >= 1. Was %i\n", FLAGS_repeat); gLogger.logError(error); exit(-1); } if (FLAGS_logFile.count() == 1) { if (!gLogger.SetLogFile(FLAGS_logFile[0])) { SkString str; str.printf("Could not open %s for writing.\n", FLAGS_logFile[0]); gLogger.logError(str); // TODO(borenet): We're disabling this for now, due to // write-protected Android devices. The very short-term // solution is to ignore the fact that we have no log file. //exit(-1); } } #ifdef SK_BUILD_JSON_WRITER SkAutoTDelete<PictureJSONResultsWriter> jsonWriter; if (FLAGS_jsonLog.count() == 1) { jsonWriter.reset(SkNEW(PictureJSONResultsWriter(FLAGS_jsonLog[0]))); gWriter.add(jsonWriter.get()); } #endif gWriter.add(&gLogWriter); #if SK_ENABLE_INST_COUNT gPrintInstCount = true; #endif SkAutoGraphics ag; sk_tools::PictureBenchmark benchmark; setup_benchmark(&benchmark); int failures = 0; for (int i = 0; i < FLAGS_readPath.count(); ++i) { failures += process_input(FLAGS_readPath[i], benchmark); } if (failures != 0) { SkString err; err.printf("Failed to run %i benchmarks.\n", failures); gLogger.logError(err); return 1; } #if SK_LAZY_CACHE_STATS if (FLAGS_trackDeferredCaching) { SkDebugf("Total cache hit rate: %f\n", (double) gTotalCacheHits / (gTotalCacheHits + gTotalCacheMisses)); } #endif gWriter.end(); return 0; }
static int filter_picture(const SkString& inFile, const SkString& outFile) { SkAutoTUnref<SkPicture> inPicture; SkFILEStream inStream(inFile.c_str()); if (inStream.isValid()) { inPicture.reset(SkPicture::CreateFromStream(&inStream)); } if (nullptr == inPicture.get()) { SkDebugf("Could not read file %s\n", inFile.c_str()); return -1; } int localCount[SK_ARRAY_COUNT(gOptTable)]; memset(localCount, 0, sizeof(localCount)); SkDebugCanvas debugCanvas(SkScalarCeilToInt(inPicture->cullRect().width()), SkScalarCeilToInt(inPicture->cullRect().height())); inPicture->playback(&debugCanvas); // delete the initial save and restore since replaying the commands will // re-add them if (debugCanvas.getSize() > 1) { debugCanvas.deleteDrawCommandAt(0); debugCanvas.deleteDrawCommandAt(debugCanvas.getSize()-1); } bool changed = true; int numBefore = debugCanvas.getSize(); while (changed) { changed = false; for (int i = 0; i < debugCanvas.getSize(); ++i) { for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { if ((*gOptTable[opt].fCheck)(&debugCanvas, i)) { (*gOptTable[opt].fApply)(&debugCanvas, i); ++gOptTable[opt].fNumTimesApplied; ++localCount[opt]; if (debugCanvas.getSize() == i) { // the optimization removed all the remaining operations break; } opt = 0; // try all the opts all over again changed = true; } } } } int numAfter = debugCanvas.getSize(); if (!outFile.isEmpty()) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(inPicture->cullRect().width(), inPicture->cullRect().height(), nullptr, 0); debugCanvas.draw(canvas); SkAutoTUnref<SkPicture> outPicture(recorder.endRecording()); SkFILEWStream outStream(outFile.c_str()); outPicture->serialize(&outStream); } bool someOptFired = false; for (size_t opt = 0; opt < SK_ARRAY_COUNT(gOptTable); ++opt) { if (0 != localCount[opt]) { SkDebugf("%d: %d ", opt, localCount[opt]); someOptFired = true; } } if (!someOptFired) { SkDebugf("No opts fired\n"); } else { SkDebugf("\t before: %d after: %d delta: %d\n", numBefore, numAfter, numBefore-numAfter); } return 0; }
static void setup_benchmark(sk_tools::PictureBenchmark* benchmark) { sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount]; sk_bzero(drawFilters, sizeof(drawFilters)); if (FLAGS_filter.count() > 0) { const char* filters = FLAGS_filter[0]; const char* colon = strchr(filters, ':'); if (colon) { int32_t type = -1; size_t typeLen = colon - filters; for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) { if (typeLen == strlen(gFilterTypes[tIndex]) && !strncmp(filters, gFilterTypes[tIndex], typeLen)) { type = SkToS32(tIndex); break; } } if (type < 0) { SkString err; err.printf("Unknown type for --filter %s\n", filters); gLogger.logError(err); exit(-1); } int flag = -1; size_t flagLen = strlen(filters) - typeLen - 1; for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) { if (flagLen == strlen(gFilterFlags[fIndex]) && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) { flag = 1 << fIndex; break; } } if (flag < 0) { SkString err; err.printf("Unknown flag for --filter %s\n", filters); gLogger.logError(err); exit(-1); } for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) { if (type != SkDrawFilter::kTypeCount && index != type) { continue; } drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags) (drawFilters[index] | flag); } } else { SkString err; err.printf("Unknown arg for --filter %s : missing colon\n", filters); gLogger.logError(err); exit(-1); } } if (FLAGS_timers.count() > 0) { size_t index = 0; bool timerWall = false; bool truncatedTimerWall = false; bool timerCpu = false; bool truncatedTimerCpu = false; bool timerGpu = false; while (index < strlen(FLAGS_timers[0])) { switch (FLAGS_timers[0][index]) { case 'w': timerWall = true; break; case 'c': timerCpu = true; break; case 'W': truncatedTimerWall = true; break; case 'C': truncatedTimerCpu = true; break; case 'g': timerGpu = true; break; default: SkDebugf("mystery character\n"); break; } index++; } benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu, truncatedTimerCpu, timerGpu); } SkString errorString; SkAutoTUnref<sk_tools::PictureRenderer> renderer(parseRenderer(errorString, kBench_PictureTool)); if (errorString.size() > 0) { gLogger.logError(errorString); } if (NULL == renderer.get()) { exit(-1); } if (FLAGS_timeIndividualTiles) { if (FLAGS_multi > 1) { gLogger.logError("Cannot time individual tiles with more than one thread.\n"); exit(-1); } sk_tools::TiledPictureRenderer* tiledRenderer = renderer->getTiledRenderer(); if (NULL == tiledRenderer) { gLogger.logError("--timeIndividualTiles requires tiled rendering.\n"); exit(-1); } if (!tiledRenderer->supportsTimingIndividualTiles()) { gLogger.logError("This renderer does not support --timeIndividualTiles.\n"); exit(-1); } benchmark->setTimeIndividualTiles(true); } benchmark->setPurgeDecodedTex(FLAGS_purgeDecodedTex); benchmark->setPreprocess(FLAGS_preprocess); if (FLAGS_readPath.count() < 1) { gLogger.logError(".skp files or directories are required.\n"); exit(-1); } renderer->setDrawFilters(drawFilters, filtersName(drawFilters)); if (FLAGS_logPerIter) { benchmark->setTimerResultType(TimerData::kPerIter_Result); } else if (FLAGS_min) { benchmark->setTimerResultType(TimerData::kMin_Result); } else { benchmark->setTimerResultType(TimerData::kAvg_Result); } benchmark->setRenderer(renderer); benchmark->setRepeats(FLAGS_repeat); benchmark->setWriter(&gWriter); }
static bool run_single_benchmark(const SkString& inputPath, sk_tools::PictureBenchmark& benchmark) { SkFILEStream inputStream; inputStream.setPath(inputPath.c_str()); if (!inputStream.isValid()) { SkString err; err.printf("Could not open file %s\n", inputPath.c_str()); gLogger.logError(err); return false; } SkDiscardableMemoryPool* pool = SkGetGlobalDiscardableMemoryPool(); // Since the old picture has been deleted, all pixels should be cleared. SkASSERT(pool->getRAMUsed() == 0); if (FLAGS_countRAM) { pool->setRAMBudget(SK_MaxU32); // Set the limit to max, so all pixels will be kept } SkPicture::InstallPixelRefProc proc; if (FLAGS_deferImageDecoding) { proc = &sk_tools::LazyDecodeBitmap; } else { proc = &SkImageDecoder::DecodeMemory; } SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream, proc)); if (NULL == picture.get()) { SkString err; err.printf("Could not read an SkPicture from %s\n", inputPath.c_str()); gLogger.logError(err); return false; } SkString filename = SkOSPath::SkBasename(inputPath.c_str()); gWriter.bench(filename.c_str(), picture->width(), picture->height()); benchmark.run(picture); #if SK_LAZY_CACHE_STATS if (FLAGS_trackDeferredCaching) { int cacheHits = pool->getCacheHits(); int cacheMisses = pool->getCacheMisses(); pool->resetCacheHitsAndMisses(); SkString hitString; hitString.printf("Cache hit rate: %f\n", (double) cacheHits / (cacheHits + cacheMisses)); gLogger.logProgress(hitString); gTotalCacheHits += cacheHits; gTotalCacheMisses += cacheMisses; } #endif if (FLAGS_countRAM) { SkString ramCount("RAM used for bitmaps: "); size_t bytes = pool->getRAMUsed(); if (bytes > 1024) { size_t kb = bytes / 1024; if (kb > 1024) { size_t mb = kb / 1024; ramCount.appendf("%zi MB\n", mb); } else { ramCount.appendf("%zi KB\n", kb); } } else { ramCount.appendf("%zi bytes\n", bytes); } gLogger.logProgress(ramCount); } return true; }
static SkStreamAsset* resource(const char path[]) { SkString fullPath = GetResourcePath(path); return SkStream::NewFromFile(fullPath.c_str()); }
void SkSVGPaint::setSave(SkSVGParser& parser) { SkTDArray<SkString*> clips; SkSVGPaint* walking = parser.fHead; int index; SkMatrix sum; sum.reset(); while (walking != NULL) { for (index = kInitial + 1; index < kTerminal; index++) { SkString* lastAttr = (*walking)[index]; if (lastAttr->size() == 0) continue; if (index == kTransform) { const char* str = lastAttr->c_str(); SkASSERT(strncmp(str, "matrix(", 7) == 0); str += 6; const char* strEnd = strrchr(str, ')'); SkASSERT(strEnd != NULL); SkString mat(str, strEnd - str); SkSVGParser::ConvertToArray(mat); SkScalar values[6]; SkParse::FindScalars(mat.c_str() + 1, values, 6); SkMatrix matrix; matrix.reset(); matrix.setScaleX(values[0]); matrix.setSkewY(values[1]); matrix.setSkewX(values[2]); matrix.setScaleY(values[3]); matrix.setTranslateX(values[4]); matrix.setTranslateY(values[5]); sum.setConcat(matrix, sum); continue; } if ( index == kClipPath) *clips.insert(0) = lastAttr; } walking = walking->fNext; } if ((sum == parser.fLastTransform) == false) { SkMatrix inverse; bool success = parser.fLastTransform.invert(&inverse); SkASSERT(success == true); SkMatrix output; output.setConcat(inverse, sum); parser.fLastTransform = sum; SkString outputStr; outputStr.appendUnichar('['); outputStr.appendScalar(output.getScaleX()); outputStr.appendUnichar(','); outputStr.appendScalar(output.getSkewX()); outputStr.appendUnichar(','); outputStr.appendScalar(output.getTranslateX()); outputStr.appendUnichar(','); outputStr.appendScalar(output.getSkewY()); outputStr.appendUnichar(','); outputStr.appendScalar(output.getScaleY()); outputStr.appendUnichar(','); outputStr.appendScalar(output.getTranslateY()); outputStr.appendUnichar(','); outputStr.appendScalar(output.getPerspX()); outputStr.appendUnichar(','); outputStr.appendScalar(output.getPerspY()); outputStr.append(",1]"); parser._startElement("matrix"); parser._addAttributeLen("matrix", outputStr.c_str(), outputStr.size()); parser._endElement(); } #if 0 // incomplete if (parser.fTransformClips.size() > 0) { // need to reset the clip when the 'g' scope is ended parser._startElement("add"); const char* start = strchr(current->f_clipPath.c_str(), '#') + 1; SkASSERT(start); parser._addAttributeLen("use", start, strlen(start) - 1); parser._endElement(); // clip } #endif }
void GrInOrderDrawBuffer::flush() { if (fFlushing) { return; } SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc); SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc); int numCmds = fCmds.count(); if (0 == numCmds) { return; } GrAutoTRestore<bool> flushRestore(&fFlushing); fFlushing = true; fVertexPool.unlock(); fIndexPool.unlock(); GrDrawTarget::AutoClipRestore acr(fDstGpu); AutoGeometryAndStatePush agasp(fDstGpu, kPreserve_ASRInit); GrDrawState playbackState; GrDrawState* prevDrawState = fDstGpu->drawState(); prevDrawState->ref(); fDstGpu->setDrawState(&playbackState); GrClipData clipData; int currState = 0; int currClip = 0; int currClear = 0; int currDraw = 0; int currStencilPath = 0; int currDrawPath = 0; int currDrawPaths = 0; int currCopySurface = 0; int currCmdMarker = 0; for (int c = 0; c < numCmds; ++c) { GrGpuTraceMarker newMarker("", -1); if (cmd_has_trace_marker(fCmds[c])) { SkString traceString = fGpuCmdMarkers[currCmdMarker].toString(); newMarker.fMarker = traceString.c_str(); fDstGpu->addGpuTraceMarker(&newMarker); ++currCmdMarker; } switch (strip_trace_bit(fCmds[c])) { case kDraw_Cmd: { const DrawRecord& draw = fDraws[currDraw]; fDstGpu->setVertexSourceToBuffer(draw.fVertexBuffer); if (draw.isIndexed()) { fDstGpu->setIndexSourceToBuffer(draw.fIndexBuffer); } fDstGpu->executeDraw(draw); ++currDraw; break; } case kStencilPath_Cmd: { const StencilPath& sp = fStencilPaths[currStencilPath]; fDstGpu->stencilPath(sp.fPath.get(), sp.fFill); ++currStencilPath; break; } case kDrawPath_Cmd: { const DrawPath& cp = fDrawPath[currDrawPath]; fDstGpu->executeDrawPath(cp.fPath.get(), cp.fFill, NULL != cp.fDstCopy.texture() ? &cp.fDstCopy : NULL); ++currDrawPath; break; } case kDrawPaths_Cmd: { DrawPaths& dp = fDrawPaths[currDrawPaths]; const GrDeviceCoordTexture* dstCopy = NULL != dp.fDstCopy.texture() ? &dp.fDstCopy : NULL; fDstGpu->executeDrawPaths(dp.fPathCount, dp.fPaths, dp.fTransforms, dp.fFill, dp.fStroke, dstCopy); ++currDrawPaths; break; } case kSetState_Cmd: fStates[currState].restoreTo(&playbackState); ++currState; break; case kSetClip_Cmd: clipData.fClipStack = &fClips[currClip]; clipData.fOrigin = fClipOrigins[currClip]; fDstGpu->setClip(&clipData); ++currClip; break; case kClear_Cmd: if (GrColor_ILLEGAL == fClears[currClear].fColor) { fDstGpu->discard(fClears[currClear].fRenderTarget); } else { fDstGpu->clear(&fClears[currClear].fRect, fClears[currClear].fColor, fClears[currClear].fCanIgnoreRect, fClears[currClear].fRenderTarget); } ++currClear; break; case kCopySurface_Cmd: fDstGpu->copySurface(fCopySurfaces[currCopySurface].fDst.get(), fCopySurfaces[currCopySurface].fSrc.get(), fCopySurfaces[currCopySurface].fSrcRect, fCopySurfaces[currCopySurface].fDstPoint); ++currCopySurface; break; } if (cmd_has_trace_marker(fCmds[c])) { fDstGpu->removeGpuTraceMarker(&newMarker); } } // we should have consumed all the states, clips, etc. SkASSERT(fStates.count() == currState); SkASSERT(fClips.count() == currClip); SkASSERT(fClipOrigins.count() == currClip); SkASSERT(fClears.count() == currClear); SkASSERT(fDraws.count() == currDraw); SkASSERT(fCopySurfaces.count() == currCopySurface); SkASSERT(fGpuCmdMarkers.count() == currCmdMarker); fDstGpu->setDrawState(prevDrawState); prevDrawState->unref(); this->reset(); ++fDrawID; }
bool SkSVGPaint::writeChangedAttributes(SkSVGParser& parser, SkSVGPaint& current, bool* changed) { SkSVGPaint& lastState = parser.fLastFlush; for (int index = kInitial + 1; index < kTerminal; index++) { if (changed[index] == false) continue; SkString* topAttr = current[index]; size_t attrLength = topAttr->size(); if (attrLength == 0) continue; const char* attrValue = topAttr->c_str(); SkString* lastAttr = lastState[index]; switch(index) { case kClipPath: case kClipRule: case kEnableBackground: break; case kFill: if (topAttr->equals("none") == false && lastAttr->equals("none") == true) parser._addAttribute("stroke", "false"); goto fillStrokeAttrCommon; case kFillRule: case kFilter: case kFontFamily: break; case kFontSize: parser._addAttributeLen("textSize", attrValue, attrLength); break; case kLetterSpacing: parser._addAttributeLen("textTracking", attrValue, attrLength); break; case kMask: break; case kOpacity: break; case kStopColor: break; case kStopOpacity: break; case kStroke: if (topAttr->equals("none") == false && lastAttr->equals("none") == true) parser._addAttribute("stroke", "true"); fillStrokeAttrCommon: if (strncmp(attrValue, "url(", 4) == 0) { SkASSERT(attrValue[4] == '#'); const char* idStart = attrValue + 5; const char* idEnd = strrchr(attrValue, ')'); SkASSERT(idStart < idEnd); SkString id(idStart, idEnd - idStart); SkSVGElement* found; if (strncmp(id.c_str(), "mask", 4) != 0) { bool itsFound = parser.fIDs.find(id.c_str(), &found); SkASSERT(itsFound); SkASSERT(found->getType() == SkSVGType_LinearGradient || found->getType() == SkSVGType_RadialGradient); } parser._addAttribute("shader", id.c_str()); } break; case kStroke_Dasharray: break; case kStroke_Linecap: parser._addAttributeLen("strokeCap", attrValue, attrLength); break; case kStroke_Linejoin: parser._addAttributeLen("strokeJoin", attrValue, attrLength); break; case kStroke_Miterlimit: parser._addAttributeLen("strokeMiter", attrValue, attrLength); break; case kStroke_Width: parser._addAttributeLen("strokeWidth", attrValue, attrLength); case kStyle: case kTransform: break; default: SkASSERT(0); return false; } } return true; }
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; }
virtual const char* onGetName() { fName.printf("shadermask"); fName.appendf("_%s", fontQualityName(fPaint)); fName.appendf("_%02X", fPaint.getAlpha()); return fName.c_str(); }
bool SkScriptRuntime::executeTokens(unsigned char* opCode) { SkOperand2 operand[2]; // 1=accumulator and 2=operand SkScriptEngine2::TypeOp op; size_t ref; int index, size; int registerLoad; SkScriptCallBack* callBack SK_INIT_TO_AVOID_WARNING; do { switch ((op = (SkScriptEngine2::TypeOp) *opCode++)) { case SkScriptEngine2::kArrayToken: // create an array operand[0].fArray = new SkOpArray(SkOperand2::kNoType /*fReturnType*/); break; case SkScriptEngine2::kArrayIndex: // array accessor index = operand[1].fS32; if (index >= operand[0].fArray->count()) { fError = kArrayIndexOutOfBounds; return false; } operand[0] = operand[0].fArray->begin()[index]; break; case SkScriptEngine2::kArrayParam: // array initializer, or function param *operand[0].fArray->append() = operand[1]; break; case SkScriptEngine2::kCallback: memcpy(&index, opCode, sizeof(index)); opCode += sizeof(index); callBack = fCallBackArray[index]; break; case SkScriptEngine2::kFunctionCall: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackFunction* callBackFunction = (SkScriptCallBackFunction*) callBack; if (callBackFunction->invoke(ref, operand[0].fArray, /* params */ &operand[0] /* result */) == false) { fError = kFunctionCallFailed; return false; } } break; case SkScriptEngine2::kMemberOp: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackMember* callBackMember = (SkScriptCallBackMember*) callBack; if (callBackMember->invoke(ref, operand[0].fObject, &operand[0]) == false) { fError = kMemberOpFailed; return false; } } break; case SkScriptEngine2::kPropertyOp: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackProperty* callBackProperty = (SkScriptCallBackProperty*) callBack; if (callBackProperty->getResult(ref, &operand[0])== false) { fError = kPropertyOpFailed; return false; } } break; case SkScriptEngine2::kAccumulatorPop: fRunStack.pop(&operand[0]); break; case SkScriptEngine2::kAccumulatorPush: *fRunStack.push() = operand[0]; break; case SkScriptEngine2::kIntegerAccumulator: case SkScriptEngine2::kIntegerOperand: registerLoad = op - SkScriptEngine2::kIntegerAccumulator; memcpy(&operand[registerLoad].fS32, opCode, sizeof(int32_t)); opCode += sizeof(int32_t); break; case SkScriptEngine2::kScalarAccumulator: case SkScriptEngine2::kScalarOperand: registerLoad = op - SkScriptEngine2::kScalarAccumulator; memcpy(&operand[registerLoad].fScalar, opCode, sizeof(SkScalar)); opCode += sizeof(SkScalar); break; case SkScriptEngine2::kStringAccumulator: case SkScriptEngine2::kStringOperand: { SkString* strPtr = new SkString(); track(strPtr); registerLoad = op - SkScriptEngine2::kStringAccumulator; memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); strPtr->set((char*) opCode, size); opCode += size; operand[registerLoad].fString = strPtr; } break; case SkScriptEngine2::kStringTrack: // call after kObjectToValue track(operand[0].fString); break; case SkScriptEngine2::kBoxToken: { SkOperand2::OpType type; memcpy(&type, opCode, sizeof(type)); opCode += sizeof(type); SkScriptCallBackConvert* callBackBox = (SkScriptCallBackConvert*) callBack; if (callBackBox->convert(type, &operand[0]) == false) return false; } break; case SkScriptEngine2::kUnboxToken: case SkScriptEngine2::kUnboxToken2: { SkScriptCallBackConvert* callBackUnbox = (SkScriptCallBackConvert*) callBack; if (callBackUnbox->convert(SkOperand2::kObject, &operand[0]) == false) return false; } break; case SkScriptEngine2::kIfOp: case SkScriptEngine2::kLogicalAndInt: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); if (operand[0].fS32 == 0) opCode += size; // skip to else (or end of if predicate) break; case SkScriptEngine2::kElseOp: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); opCode += size; // if true: after predicate, always skip to end of else break; case SkScriptEngine2::kLogicalOrInt: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); if (operand[0].fS32 != 0) opCode += size; // skip to kToBool opcode after || predicate break; // arithmetic conversion ops case SkScriptEngine2::kFlipOpsOp: SkTSwap(operand[0], operand[1]); break; case SkScriptEngine2::kIntToString: case SkScriptEngine2::kIntToString2: case SkScriptEngine2::kScalarToString: case SkScriptEngine2::kScalarToString2:{ SkString* strPtr = new SkString(); track(strPtr); if (op == SkScriptEngine2::kIntToString || op == SkScriptEngine2::kIntToString2) strPtr->appendS32(operand[op - SkScriptEngine2::kIntToString].fS32); else strPtr->appendScalar(operand[op - SkScriptEngine2::kScalarToString].fScalar); operand[0].fString = strPtr; } break; case SkScriptEngine2::kIntToScalar: case SkScriptEngine2::kIntToScalar2: operand[0].fScalar = SkScriptEngine2::IntToScalar(operand[op - SkScriptEngine2::kIntToScalar].fS32); break; case SkScriptEngine2::kStringToInt: if (SkParse::FindS32(operand[0].fString->c_str(), &operand[0].fS32) == NULL) return false; break; case SkScriptEngine2::kStringToScalar: case SkScriptEngine2::kStringToScalar2: if (SkParse::FindScalar(operand[0].fString->c_str(), &operand[op - SkScriptEngine2::kStringToScalar].fScalar) == NULL) return false; break; case SkScriptEngine2::kScalarToInt: operand[0].fS32 = SkScalarFloorToInt(operand[0].fScalar); break; // arithmetic ops case SkScriptEngine2::kAddInt: operand[0].fS32 += operand[1].fS32; break; case SkScriptEngine2::kAddScalar: operand[0].fScalar += operand[1].fScalar; break; case SkScriptEngine2::kAddString: // if (fTrackString.find(operand[1].fString) < 0) { // operand[1].fString = SkNEW_ARGS(SkString, (*operand[1].fString)); // track(operand[1].fString); // } operand[0].fString->append(*operand[1].fString); break; case SkScriptEngine2::kBitAndInt: operand[0].fS32 &= operand[1].fS32; break; case SkScriptEngine2::kBitNotInt: operand[0].fS32 = ~operand[0].fS32; break; case SkScriptEngine2::kBitOrInt: operand[0].fS32 |= operand[1].fS32; break; case SkScriptEngine2::kDivideInt: SkASSERT(operand[1].fS32 != 0); if (operand[1].fS32 == 0) operand[0].fS32 = operand[0].fS32 == 0 ? SK_NaN32 : operand[0].fS32 > 0 ? SK_MaxS32 : -SK_MaxS32; else if (operand[1].fS32 != 0) // throw error on divide by zero? operand[0].fS32 /= operand[1].fS32; break; case SkScriptEngine2::kDivideScalar: if (operand[1].fScalar == 0) operand[0].fScalar = operand[0].fScalar == 0 ? SK_ScalarNaN : operand[0].fScalar > 0 ? SK_ScalarMax : -SK_ScalarMax; else operand[0].fScalar = operand[0].fScalar / operand[1].fScalar; break; case SkScriptEngine2::kEqualInt: operand[0].fS32 = operand[0].fS32 == operand[1].fS32; break; case SkScriptEngine2::kEqualScalar: operand[0].fS32 = operand[0].fScalar == operand[1].fScalar; break; case SkScriptEngine2::kEqualString: operand[0].fS32 = *operand[0].fString == *operand[1].fString; break; case SkScriptEngine2::kGreaterEqualInt: operand[0].fS32 = operand[0].fS32 >= operand[1].fS32; break; case SkScriptEngine2::kGreaterEqualScalar: operand[0].fS32 = operand[0].fScalar >= operand[1].fScalar; break; case SkScriptEngine2::kGreaterEqualString: operand[0].fS32 = strcmp(operand[0].fString->c_str(), operand[1].fString->c_str()) >= 0; break; case SkScriptEngine2::kToBool: operand[0].fS32 = !! operand[0].fS32; break; case SkScriptEngine2::kLogicalNotInt: operand[0].fS32 = ! operand[0].fS32; break; case SkScriptEngine2::kMinusInt: operand[0].fS32 = -operand[0].fS32; break; case SkScriptEngine2::kMinusScalar: operand[0].fScalar = -operand[0].fScalar; break; case SkScriptEngine2::kModuloInt: operand[0].fS32 %= operand[1].fS32; break; case SkScriptEngine2::kModuloScalar: operand[0].fScalar = SkScalarMod(operand[0].fScalar, operand[1].fScalar); break; case SkScriptEngine2::kMultiplyInt: operand[0].fS32 *= operand[1].fS32; break; case SkScriptEngine2::kMultiplyScalar: operand[0].fScalar = SkScalarMul(operand[0].fScalar, operand[1].fScalar); break; case SkScriptEngine2::kShiftLeftInt: operand[0].fS32 <<= operand[1].fS32; break; case SkScriptEngine2::kShiftRightInt: operand[0].fS32 >>= operand[1].fS32; break; case SkScriptEngine2::kSubtractInt: operand[0].fS32 -= operand[1].fS32; break; case SkScriptEngine2::kSubtractScalar: operand[0].fScalar -= operand[1].fScalar; break; case SkScriptEngine2::kXorInt: operand[0].fS32 ^= operand[1].fS32; break; case SkScriptEngine2::kEnd: goto done; case SkScriptEngine2::kNop: SkASSERT(0); default: break; } } while (true); done: fRunStack.push(operand[0]); return true; }
void GrContext::printGpuStats() const { SkString out; this->dumpGpuStats(&out); SkDebugf("%s", out.c_str()); }
SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember, const SkFontStyle& fontStyle) const { SkString familyName; familyMember->getFamilyName(&familyName); return this->matchFamilyStyle(familyName.c_str(), fontStyle); }
void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder, const GrEffectRef& effect, EffectKey effectKey, TransformedCoordsArray* outCoords) { SkTArray<Transform, true>& transforms = fTransforms.push_back(); EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey); int numTransforms = effect->numTransforms(); transforms.push_back_n(numTransforms); for (int t = 0; t < numTransforms; t++) { GrSLType varyingType = kVoid_GrSLType; const char* uniName; switch (get_matrix_type(totalKey, t)) { case kIdentity_MatrixType: transforms[t].fType = kVoid_GrSLType; uniName = NULL; varyingType = kVec2f_GrSLType; break; case kTrans_MatrixType: transforms[t].fType = kVec2f_GrSLType; uniName = "StageTranslate"; varyingType = kVec2f_GrSLType; break; case kNoPersp_MatrixType: transforms[t].fType = kMat33f_GrSLType; uniName = "StageMatrix"; varyingType = kVec2f_GrSLType; break; case kGeneral_MatrixType: transforms[t].fType = kMat33f_GrSLType; uniName = "StageMatrix"; varyingType = kVec3f_GrSLType; break; default: GrCrash("Unexpected key."); } SkString suffixedUniName; if (kVoid_GrSLType != transforms[t].fType) { if (0 != t) { suffixedUniName.append(uniName); suffixedUniName.appendf("_%i", t); uniName = suffixedUniName.c_str(); } transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility, transforms[t].fType, uniName, &uniName); } const char* varyingName = "MatrixCoord"; SkString suffixedVaryingName; if (0 != t) { suffixedVaryingName.append(varyingName); suffixedVaryingName.appendf("_%i", t); varyingName = suffixedVaryingName.c_str(); } const char* vsVaryingName; const char* fsVaryingName; builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ? builder->positionAttribute() : builder->localCoordsAttribute(); // varying = matrix * coords (logically) switch (transforms[t].fType) { case kVoid_GrSLType: SkASSERT(kVec2f_GrSLType == varyingType); builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str()); break; case kVec2f_GrSLType: SkASSERT(kVec2f_GrSLType == varyingType); builder->vsCodeAppendf("\t%s = %s + %s;\n", vsVaryingName, uniName, coords.c_str()); break; case kMat33f_GrSLType: { SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); if (kVec2f_GrSLType == varyingType) { builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n", vsVaryingName, uniName, coords.c_str()); } else { builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n", vsVaryingName, uniName, coords.c_str()); } break; } default: GrCrash("Unexpected uniform type."); } SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (SkString(fsVaryingName), varyingType)); } }
SkPDFString::SkPDFString(const SkString& value) : fValue(FormatString(value.c_str(), value.size())) { }
InterpBench(void* param, const char name[]) : INHERITED(param) { fName.printf("interp_%s", name); fFx = 3.3f; fDx = 0.1257f; }
// static SkString SkPDFString::DoFormatString(const void* input, size_t len, bool wideInput, bool wideOutput) { SkASSERT(len <= kMaxLen); const uint16_t* win = (const uint16_t*) input; const char* cin = (const char*) input; if (wideOutput) { SkASSERT(wideInput); SkString result; result.append("<"); for (size_t i = 0; i < len; i++) { result.appendHex(win[i], 4); } result.append(">"); return result; } // 7-bit clean is a heuristic to decide what string format to use; // a 7-bit clean string should require little escaping. bool sevenBitClean = true; for (size_t i = 0; i < len; i++) { SkASSERT(!wideInput || !(win[i] & ~0xFF)); char val = wideInput ? win[i] : cin[i]; if (val > '~' || val < ' ') { sevenBitClean = false; break; } } SkString result; if (sevenBitClean) { result.append("("); for (size_t i = 0; i < len; i++) { SkASSERT(!wideInput || !(win[i] & ~0xFF)); char val = wideInput ? win[i] : cin[i]; if (val == '\\' || val == '(' || val == ')') { result.append("\\"); } result.append(&val, 1); } result.append(")"); } else { result.append("<"); for (size_t i = 0; i < len; i++) { SkASSERT(!wideInput || !(win[i] & ~0xFF)); unsigned char val = wideInput ? win[i] : cin[i]; result.appendHex(val, 2); } result.append(">"); } return result; }
void GrGLBicubicEffect::emitCode(EmitArgs& args) { const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>(); GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; fCoefficientsUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat44f_GrSLType, kDefault_GrSLPrecision, "Coefficients"); fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision, "ImageIncrement"); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); const char* coeff = uniformHandler->getUniformCStr(fCoefficientsUni); GrGLSLColorSpaceXformHelper colorSpaceHelper(uniformHandler, bicubicEffect.colorSpaceXform(), &fColorSpaceXformUni); SkString cubicBlendName; static const GrGLSLShaderVar gCubicBlendArgs[] = { GrGLSLShaderVar("coefficients", kMat44f_GrSLType), GrGLSLShaderVar("t", kFloat_GrSLType), GrGLSLShaderVar("c0", kVec4f_GrSLType), GrGLSLShaderVar("c1", kVec4f_GrSLType), GrGLSLShaderVar("c2", kVec4f_GrSLType), GrGLSLShaderVar("c3", kVec4f_GrSLType), }; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); fragBuilder->emitFunction(kVec4f_GrSLType, "cubicBlend", SK_ARRAY_COUNT(gCubicBlendArgs), gCubicBlendArgs, "\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n" "\tvec4 c = coefficients * ts;\n" "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n", &cubicBlendName); fragBuilder->codeAppendf("\tvec2 coord = %s - %s * vec2(0.5);\n", coords2D.c_str(), imgInc); // We unnormalize the coord in order to determine our fractional offset (f) within the texel // We then snap coord to a texel center and renormalize. The snap prevents cases where the // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/ // double hit a texel. fragBuilder->codeAppendf("\tcoord /= %s;\n", imgInc); fragBuilder->codeAppend("\tvec2 f = fract(coord);\n"); fragBuilder->codeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc); fragBuilder->codeAppend("\tvec4 rowColors[4];\n"); for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { SkString coord; coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1); SkString sampleVar; sampleVar.printf("rowColors[%d]", x); fDomain.sampleTexture(fragBuilder, args.fUniformHandler, args.fGLSLCaps, bicubicEffect.domain(), sampleVar.c_str(), coord, args.fTexSamplers[0]); } fragBuilder->codeAppendf( "\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff); } SkString bicubicColor; bicubicColor.printf("%s(%s, f.y, s0, s1, s2, s3)", cubicBlendName.c_str(), coeff); if (colorSpaceHelper.getXformMatrix()) { SkString xformedColor; fragBuilder->appendColorGamutXform(&xformedColor, bicubicColor.c_str(), &colorSpaceHelper); bicubicColor.swap(xformedColor); } fragBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(args.fInputColor)).c_str()); }
bool SkSVGPaint::flush(SkSVGParser& parser, bool isFlushable, bool isDef) { SkSVGPaint current; SkSVGPaint* walking = parser.fHead; int index; while (walking != NULL) { for (index = kInitial + 1; index < kTerminal; index++) { SkString* lastAttr = (*walking)[index]; if (lastAttr->size() == 0) continue; if (current[index]->size() > 0) continue; current[index]->set(*lastAttr); } walking = walking->fNext; } bool paintChanged = false; SkSVGPaint& lastState = parser.fLastFlush; if (isFlushable == false) { if (isDef == true) { if (current.f_mask.size() > 0 && current.f_mask.equals(lastState.f_mask) == false) { SkSVGElement* found; const char* idStart = strchr(current.f_mask.c_str(), '#'); SkASSERT(idStart); SkString id(idStart + 1, strlen(idStart) - 2); bool itsFound = parser.fIDs.find(id.c_str(), &found); SkASSERT(itsFound); SkSVGElement* gradient = found->getGradient(); if (gradient) { gradient->write(parser, current.f_fill); gradient->write(parser, current.f_stroke); } } } goto setLast; } { bool changed[kTerminal]; memset(changed, 0, sizeof(changed)); for (index = kInitial + 1; index < kTerminal; index++) { if (index == kTransform || index == kClipPath || index == kStopColor || index == kStopOpacity || index == kClipRule || index == kFillRule) continue; SkString* lastAttr = lastState[index]; SkString* currentAttr = current[index]; paintChanged |= changed[index] = lastAttr->equals(*currentAttr) == false; } if (paintChanged) { if (current.f_mask.size() > 0) { if (current.f_fill.equals("none") == false && strncmp(current.f_fill.c_str(), "url(#", 5) != 0) { SkASSERT(current.f_fill.c_str()[0] == '#'); SkString replacement("url(#mask"); replacement.append(current.f_fill.c_str() + 1); replacement.appendUnichar(')'); current.f_fill.set(replacement); } if (current.f_stroke.equals("none") == false && strncmp(current.f_stroke.c_str(), "url(#", 5) != 0) { SkASSERT(current.f_stroke.c_str()[0] == '#'); SkString replacement("url(#mask"); replacement.append(current.f_stroke.c_str() + 1); replacement.appendUnichar(')'); current.f_stroke.set(replacement); } } if (current.f_fill.equals("none") && current.f_stroke.equals("none")) current.f_opacity.set("0"); if (parser.fSuppressPaint == false) { parser._startElement("paint"); bool success = writeChangedAttributes(parser, current, changed); if (success == false) return paintChanged; success = writeChangedElements(parser, current, changed); if (success == false) return paintChanged; parser._endElement(); // paint } } } setLast: for (index = kInitial + 1; index < kTerminal; index++) { SkString* lastAttr = lastState[index]; SkString* currentAttr = current[index]; lastAttr->set(*currentAttr); } return paintChanged; }
void WriteTask::makeDirOrFail(SkString dir) { if (!sk_mkdir(dir.c_str())) { this->fail(); } }
static bool run_single_benchmark(const SkString& inputPath, sk_tools::PictureBenchmark& benchmark) { SkFILEStream inputStream; inputStream.setPath(inputPath.c_str()); if (!inputStream.isValid()) { SkString err; err.printf("Could not open file %s\n", inputPath.c_str()); gLogger.logError(err); return false; } // Since the old picture has been deleted, all pixels should be cleared. SkASSERT(gLruImageCache.getImageCacheUsed() == 0); if (FLAGS_countRAM) { // Set the limit to zero, so all pixels will be kept gLruImageCache.setImageCacheLimit(0); } SkPicture::InstallPixelRefProc proc; if (FLAGS_deferImageDecoding) { proc = &sk_tools::LazyDecodeBitmap; } else { proc = &SkImageDecoder::DecodeMemory; } SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromStream(&inputStream, proc)); if (NULL == picture.get()) { SkString err; err.printf("Could not read an SkPicture from %s\n", inputPath.c_str()); gLogger.logError(err); return false; } SkString filename; sk_tools::get_basename(&filename, inputPath); SkString result; result.printf("running bench [%i %i] %s ", picture->width(), picture->height(), filename.c_str()); gLogger.logProgress(result); benchmark.run(picture); #if LAZY_CACHE_STATS if (FLAGS_trackDeferredCaching) { int32_t cacheHits = SkLazyPixelRef::GetCacheHits(); int32_t cacheMisses = SkLazyPixelRef::GetCacheMisses(); SkLazyPixelRef::ResetCacheStats(); SkString hitString; hitString.printf("Cache hit rate: %f\n", (double) cacheHits / (cacheHits + cacheMisses)); gLogger.logProgress(hitString); gTotalCacheHits += cacheHits; gTotalCacheMisses += cacheMisses; } #endif if (FLAGS_countRAM) { SkString ramCount("RAM used for bitmaps: "); size_t bytes = gLruImageCache.getImageCacheUsed(); if (bytes > 1024) { size_t kb = bytes / 1024; if (kb > 1024) { size_t mb = kb / 1024; ramCount.appendf("%zi MB\n", mb); } else { ramCount.appendf("%zi KB\n", kb); } } else { ramCount.appendf("%zi bytes\n", bytes); } gLogger.logProgress(ramCount); } return true; }