static bool make_out_dirs() { SkString outDir = make_filepath(0, OUT_DIR, ""); if (!sk_exists(outDir.c_str())) { if (!sk_mkdir(outDir.c_str())) { SkDebugf("could not create dir %s\n", outDir.c_str()); return false; } } SkString grDir = make_filepath(0, outGrDir, ""); if (!sk_exists(grDir.c_str())) { if (!sk_mkdir(grDir.c_str())) { SkDebugf("could not create dir %s\n", grDir.c_str()); return false; } } SkString skDir = make_filepath(0, outSkDir, ""); if (!sk_exists(skDir.c_str())) { if (!sk_mkdir(skDir.c_str())) { SkDebugf("could not create dir %s\n", skDir.c_str()); return false; } } SkString skpDir = make_filepath(0, outSkpDir, ""); if (!sk_exists(skpDir.c_str())) { if (!sk_mkdir(skpDir.c_str())) { SkDebugf("could not create dir %s\n", skpDir.c_str()); return false; } } SkString diffDir = make_filepath(0, outDiffDir, ""); if (!sk_exists(diffDir.c_str())) { if (!sk_mkdir(diffDir.c_str())) { SkDebugf("could not create dir %s\n", diffDir.c_str()); return false; } } SkString statusDir = make_filepath(0, outStatusDir, ""); if (!sk_exists(statusDir.c_str())) { if (!sk_mkdir(statusDir.c_str())) { SkDebugf("could not create dir %s\n", statusDir.c_str()); return false; } } return true; }
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(); }
static void TestWStream(skiatest::Reporter* reporter) { SkDynamicMemoryWStream ds; const char s[] = "abcdefghijklmnopqrstuvwxyz"; int i; for (i = 0; i < 100; i++) { REPORTER_ASSERT(reporter, ds.write(s, 26)); } REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26); char* dst = new char[100 * 26 + 1]; dst[100*26] = '*'; ds.copyTo(dst); REPORTER_ASSERT(reporter, dst[100*26] == '*'); for (i = 0; i < 100; i++) { REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0); } { SkAutoTDelete<SkStreamAsset> stream(ds.detachAsStream()); REPORTER_ASSERT(reporter, 100 * 26 == stream->getLength()); REPORTER_ASSERT(reporter, ds.getOffset() == 0); test_loop_stream(reporter, stream.get(), s, 26, 100); SkAutoTDelete<SkStreamAsset> stream2(stream->duplicate()); test_loop_stream(reporter, stream2.get(), s, 26, 100); SkAutoTDelete<SkStreamAsset> stream3(stream->fork()); REPORTER_ASSERT(reporter, stream3->isAtEnd()); char tmp; size_t bytes = stream->read(&tmp, 1); REPORTER_ASSERT(reporter, 0 == bytes); stream3->rewind(); test_loop_stream(reporter, stream3.get(), s, 26, 100); } for (i = 0; i < 100; i++) { REPORTER_ASSERT(reporter, ds.write(s, 26)); } REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26); { SkAutoTUnref<SkData> data(ds.copyToData()); REPORTER_ASSERT(reporter, 100 * 26 == data->size()); REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0); } { // Test that this works after a copyToData. SkAutoTDelete<SkStreamAsset> stream(ds.detachAsStream()); REPORTER_ASSERT(reporter, ds.getOffset() == 0); test_loop_stream(reporter, stream.get(), s, 26, 100); SkAutoTDelete<SkStreamAsset> stream2(stream->duplicate()); test_loop_stream(reporter, stream2.get(), s, 26, 100); } delete[] dst; SkString tmpDir = skiatest::GetTmpDir(); if (!tmpDir.isEmpty()) { test_filestreams(reporter, tmpDir.c_str()); } }
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); } }
virtual const char* onGetName() { return fName.c_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(); }
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; }
static SkStreamAsset* resource(const char path[]) { SkString fullPath = GetResourcePath(path); return SkStream::NewFromFile(fullPath.c_str()); }
DEF_TEST(SkpSkGrThreaded, reporter) { if (!initTest()) { return; } SkpSkGrThreadedTestRunner testRunner(reporter); for (int dirIndex = 1; dirIndex <= 100; ++dirIndex) { SkString pictDir = make_in_dir_name(dirIndex); if (pictDir.size() == 0) { continue; } SkOSFile::Iter iter(pictDir.c_str(), "skp"); SkString filename; while (iter.next(&filename)) { SkString pngName = make_png_name(filename.c_str()); SkString oldPng = make_filepath(dirIndex, outSkDir, pngName.c_str()); SkString newPng = make_filepath(dirIndex, outGrDir, pngName.c_str()); if (sk_exists(oldPng.c_str()) && sk_exists(newPng.c_str())) { bumpCount(reporter, true); continue; } for (size_t index = 0; index < skipOverSkGrCount; ++index) { if (skipOverSkGr[index].directory == dirIndex && strcmp(filename.c_str(), skipOverSkGr[index].filename) == 0) { bumpCount(reporter, true); goto skipOver; } } *testRunner.fRunnables.append() = new SkpSkGrThreadedRunnable( &testSkGrMain, dirIndex, filename.c_str(), &testRunner); skipOver: ; } } testRunner.render(); SkpSkGrThreadState& max = testRunner.fRunnables[0]->fState; for (int dirIndex = 2; dirIndex <= 100; ++dirIndex) { SkpSkGrThreadState& state = testRunner.fRunnables[dirIndex - 1]->fState; for (int index = 0; index < state.fFoundCount; ++index) { int maxIdx = max.fFoundCount; if (maxIdx < kMaxFiles) { max.fError[maxIdx] = state.fError[index]; strcpy(max.fFilesFound[maxIdx], state.fFilesFound[index]); max.fDirsFound[maxIdx] = state.fDirsFound[index]; ++max.fFoundCount; continue; } for (maxIdx = 0; maxIdx < max.fFoundCount; ++maxIdx) { if (max.fError[maxIdx] < state.fError[index]) { max.fError[maxIdx] = state.fError[index]; strcpy(max.fFilesFound[maxIdx], state.fFilesFound[index]); max.fDirsFound[maxIdx] = state.fDirsFound[index]; break; } } } } TestResult encoder; encoder.fTestStep = kEncodeFiles; for (int index = 0; index < max.fFoundCount; ++index) { encoder.fDirNo = max.fDirsFound[index]; strcpy(encoder.fFilename, max.fFilesFound[index]); encoder.testOne(); SkDebugf("+"); } }
void test(int dirNo, const SkString& filename) { init(dirNo); strcpy(fFilename, filename.c_str()); testOne(); }
DEF_TEST(SkpSkGr, reporter) { SkTArray<TestResult, true> errors; if (!initTest()) { return; } SkpSkGrThreadState state; state.init(0); int smallCount = 0; for (int dirNo = 1; dirNo <= 100; ++dirNo) { SkString pictDir = make_in_dir_name(dirNo); SkASSERT(pictDir.size()); if (reporter->verbose()) { SkDebugf("dirNo=%d\n", dirNo); } SkOSFile::Iter iter(pictDir.c_str(), "skp"); SkString filename; int testCount = 0; PreParser preParser(dirNo); SkFILEWStream statusStream(makeStatusString(dirNo).c_str()); while (iter.next(&filename)) { for (size_t index = 0; index < skipOverSkGrCount; ++index) { if (skipOverSkGr[index].directory == dirNo && strcmp(filename.c_str(), skipOverSkGr[index].filename) == 0) { goto skipOver; } } if (preParser.match(filename, &statusStream, &state.fResult)) { addError(&state); ++testCount; goto checkEarlyExit; } if (state.fSmallestError > 5000000) { goto breakOut; } { TestResult& result = state.fResult; result.test(dirNo, filename); SkString outStr(result.status()); statusStream.write(outStr.c_str(), outStr.size()); statusStream.flush(); if (1) { SkDebugf("%s", outStr.c_str()); } bool noMatch = addError(&state); if (noMatch) { smallCount = 0; } else if (++smallCount > 10000) { goto breakOut; } } ++testCount; if (reporter->verbose()) { if (testCount % 100 == 0) { SkDebugf("#%d\n", testCount); } } skipOver: reporter->bumpTestCount(); checkEarlyExit: if (1 && testCount == 20) { break; } } } breakOut: if (reporter->verbose()) { for (int index = 0; index < state.fFoundCount; ++index) { SkDebugf("%d %s %d\n", state.fDirsFound[index], state.fFilesFound[index], state.fError[index]); } } for (int index = 0; index < state.fFoundCount; ++index) { TestResult::Test(state.fDirsFound[index], state.fFilesFound[index], kEncodeFiles, reporter->verbose()); if (reporter->verbose()) SkDebugf("+"); } }
static SkString makeStatusString(int dirNo) { SkString statName; statName.printf("stats%d.txt", dirNo); SkString statusFile = make_filepath(0, outStatusDir, statName.c_str()); return statusFile; }
void TestResult::testOne() { SkPicture* pic = NULL; { SkString d; d.printf(" {%d, \"%s\"},", fDirNo, fFilename); SkString path = make_filepath(fDirNo, IN_DIR, fFilename); SkFILEStream stream(path.c_str()); if (!stream.isValid()) { SkDebugf("invalid stream %s\n", path.c_str()); goto finish; } if (fTestStep == kEncodeFiles) { size_t length = stream.getLength(); SkTArray<char, true> bytes; bytes.push_back_n(length); stream.read(&bytes[0], length); stream.rewind(); SkString wPath = make_filepath(0, outSkpDir, fFilename); SkFILEWStream wStream(wPath.c_str()); wStream.write(&bytes[0], length); wStream.flush(); } pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory); if (!pic) { SkDebugf("unable to decode %s\n", fFilename); goto finish; } int pWidth = pic->width(); int pHeight = pic->height(); int pLargerWH = SkTMax(pWidth, pHeight); GrContextFactory contextFactory; #ifdef SK_BUILD_FOR_WIN GrContext* context = contextFactory.get(kAngle); #else GrContext* context = contextFactory.get(kNative); #endif if (NULL == context) { SkDebugf("unable to allocate context for %s\n", fFilename); goto finish; } int maxWH = context->getMaxRenderTargetSize(); int scale = 1; while (pLargerWH / scale > maxWH) { scale *= 2; } SkBitmap bitmap; SkIPoint dim; do { dim.fX = (pWidth + scale - 1) / scale; dim.fY = (pHeight + scale - 1) / scale; bool success = bitmap.allocN32Pixels(dim.fX, dim.fY); if (success) { break; } SkDebugf("-%d-", scale); } while ((scale *= 2) < 256); if (scale >= 256) { SkDebugf("unable to allocate bitmap for %s (w=%d h=%d) (sw=%d sh=%d)\n", fFilename, pWidth, pHeight, dim.fX, dim.fY); goto finish; } SkCanvas skCanvas(bitmap); drawPict(pic, &skCanvas, fScaleOversized ? scale : 1); GrTextureDesc desc; desc.fConfig = kSkia8888_GrPixelConfig; desc.fFlags = kRenderTarget_GrTextureFlagBit; desc.fWidth = dim.fX; desc.fHeight = dim.fY; desc.fSampleCnt = 0; SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0)); if (!texture) { SkDebugf("unable to allocate texture for %s (w=%d h=%d)\n", fFilename, dim.fX, dim.fY); goto finish; } SkGpuDevice grDevice(context, texture.get()); SkCanvas grCanvas(&grDevice); drawPict(pic, &grCanvas, fScaleOversized ? scale : 1); SkBitmap grBitmap; grBitmap.allocPixels(grCanvas.imageInfo()); grCanvas.readPixels(&grBitmap, 0, 0); if (fTestStep == kCompareBits) { fPixelError = similarBits(grBitmap, bitmap); int skTime = timePict(pic, &skCanvas); int grTime = timePict(pic, &grCanvas); fTime = skTime - grTime; } else if (fTestStep == kEncodeFiles) { SkString pngStr = make_png_name(fFilename); const char* pngName = pngStr.c_str(); writePict(grBitmap, outGrDir, pngName); writePict(bitmap, outSkDir, pngName); } } finish: delete pic; }
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 }
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; }
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; }
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; }
virtual const char* onGetName() { fName.printf("shadermask"); fName.appendf("_%s", fontQualityName(fPaint)); fName.appendf("_%02X", fPaint.getAlpha()); return fName.c_str(); }
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; }
void GrContext::printGpuStats() const { SkString out; this->dumpGpuStats(&out); SkDebugf("%s", out.c_str()); }
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()); }
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)); } }
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; }
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()); }
SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember, const SkFontStyle& fontStyle) const { SkString familyName; familyMember->getFamilyName(&familyName); return this->matchFamilyStyle(familyName.c_str(), fontStyle); }
void WriteTask::makeDirOrFail(SkString dir) { if (!sk_mkdir(dir.c_str())) { this->fail(); } }
SkPDFString::SkPDFString(const SkString& value) : fValue(FormatString(value.c_str(), value.size())) { }
static bool eq(const SkString& str, const char* strPtr, size_t len) { return len == str.size() && 0 == memcmp(str.c_str(), strPtr, len); }
bool GetResourceAsBitmap(const char* resource, SkBitmap* dst) { SkString resourcePath = GetResourcePath(resource); SkAutoTUnref<SkData> resourceData(SkData::NewFromFileName(resourcePath.c_str())); return resourceData && SkInstallDiscardablePixelRef(resourceData, dst); }