double tf_shift(dofft_closure *k, int realp, const bench_tensor *sz, int n, int vecn, double sign, C *inA, C *inB, C *outA, C *outB, C *tmp, int rounds, double tol, int which_shift) { int nb, na, dim, N = n * vecn; int i, j; double e = 0.0; /* test 3: check the time-shift property */ /* the paper performs more tests, but this code should be fine too */ nb = 1; na = n; /* check shifts across all SZ dimensions */ for (dim = 0; dim < sz->rnk; ++dim) { int ncur = sz->dims[dim].n; na /= ncur; for (j = 0; j < rounds; ++j) { arand(inA, N); if (which_shift == TIME_SHIFT) { for (i = 0; i < vecn; ++i) { if (realp) mkreal(inA + i * n, n); arol(inB + i * n, inA + i * n, ncur, nb, na); } k->apply(k, inA, outA); k->apply(k, inB, outB); for (i = 0; i < vecn; ++i) aphase_shift(tmp + i * n, outB + i * n, ncur, nb, na, sign); e = dmax(e, acmp(tmp, outA, N, "time shift", tol)); } else { for (i = 0; i < vecn; ++i) { if (realp) mkhermitian(inA + i * n, sz->rnk, sz->dims, 1); aphase_shift(inB + i * n, inA + i * n, ncur, nb, na, -sign); } k->apply(k, inA, outA); k->apply(k, inB, outB); for (i = 0; i < vecn; ++i) arol(tmp + i * n, outB + i * n, ncur, nb, na); e = dmax(e, acmp(tmp, outA, N, "freq shift", tol)); } } nb *= ncur; } return e; }
void operator()(const SkRecords::DrawPicture& dp) { int drawPictureOffset; if (fOps.count()) { drawPictureOffset = fOps[fIndex]; } else { drawPictureOffset = fIndex; } fOpIndexStack.push(drawPictureOffset); SkAutoCanvasMatrixPaint acmp(fCanvas, &dp.matrix, dp.paint, dp.picture->cullRect()); if (const SkBigPicture* bp = dp.picture->asSkBigPicture()) { // Draw sub-pictures with the same replacement list but a different picture ReplaceDraw draw(fCanvas, fLayerCache, this->drawablePicts(), this->drawableCount(), fTopLevelPicture, bp, fInitialMatrix, fCallback, fOpIndexStack.begin(), fOpIndexStack.count()); fNumReplaced += draw.draw(); } else { // TODO: can we assume / assert this doesn't happen? dp.picture->playback(fCanvas, fCallback); } fOpIndexStack.pop(); }
double linear(dofft_closure *k, int realp, int n, C *inA, C *inB, C *inC, C *outA, C *outB, C *outC, C *tmp, int rounds, double tol) { int j; double e = 0.0; for (j = 0; j < rounds; ++j) { C alpha, beta; c_re(alpha) = mydrand(); c_im(alpha) = realp ? 0.0 : mydrand(); c_re(beta) = mydrand(); c_im(beta) = realp ? 0.0 : mydrand(); arand(inA, n); arand(inB, n); k->apply(k, inA, outA); k->apply(k, inB, outB); ascale(outA, alpha, n); ascale(outB, beta, n); aadd(tmp, outA, outB, n); ascale(inA, alpha, n); ascale(inB, beta, n); aadd(inC, inA, inB, n); k->apply(k, inC, outC); e = dmax(e, acmp(outC, tmp, n, "linear", tol)); } return e; }
static double verify_impulse(fftd_func *dft, int n, int veclen, COMPLEX *inA, COMPLEX *inB, COMPLEX *inC, COMPLEX *outA, COMPLEX *outB, COMPLEX *outC, COMPLEX *tmp, int rounds) { int N = n * veclen; COMPLEX impulse; int i; double e, maxerr = 0.0; /* test 2: check that the unit impulse is transformed properly */ RE(impulse) = 1.0; IM(impulse) = 0.0; for (i = 0; i < N; ++i) { /* impulse */ RE(inA[i]) = 0.0; IM(inA[i]) = 0.0; /* transform of the impulse */ outA[i] = impulse; } for (i = 0; i < veclen; ++i) inA[i * n] = impulse; /* a simple test first, to help with debugging: */ dft((double *)outB, (double *)inA); e = acmp(outB, outA, N); if(e > maxerr) maxerr = e; for (i = 0; i < rounds; ++i) { fill_random(inB, N); asub(inC, inA, inB, N); dft((double *)outB, (double *)inB); dft((double *)outC, (double *)inC); aadd(tmp, outB, outC, N); e = acmp(tmp, outA, N); if(e > maxerr) maxerr = e; } return maxerr; }
void SkDebugCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { this->addDrawCommand(new SkBeginDrawPictureCommand(picture, matrix, paint)); SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); picture->playback(this); this->addDrawCommand(new SkEndDrawPictureCommand(SkToBool(matrix) || SkToBool(paint))); }
void operator()(const SkRecords::DrawPicture& dp) { SkAutoCanvasMatrixPaint acmp(fCanvas, dp.matrix, dp.paint, dp.picture->cullRect()); // Draw sub-pictures with the same replacement list but a different picture ReplaceDraw draw(fCanvas, dp.picture, fReplacements, fInitialMatrix, fCallback); draw.draw(); }
void SkRecorder::onDrawPicture(const SkPicture* pic, const SkMatrix* matrix, const SkPaint* paint) { if (fDrawPictureMode == Record_DrawPictureMode) { fApproxBytesUsedBySubPictures += SkPictureUtils::ApproximateBytesUsed(pic); APPEND(DrawPicture, this->copy(paint), pic, matrix ? *matrix : SkMatrix::I()); } else { SkASSERT(fDrawPictureMode == Playback_DrawPictureMode); SkAutoCanvasMatrixPaint acmp(this, matrix, paint, pic->cullRect()); pic->playback(this); } }
void SkDeferredCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { #if 1 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); picture->playback(this); #else this->flush_before_saves(); fCanvas->drawPicture(picture, matrix, paint); #endif }
static double impulse0(dofft_closure *k, int n, int vecn, C *inA, C *inB, C *inC, C *outA, C *outB, C *outC, C *tmp, int rounds, double tol) { int N = n * vecn; double e = 0.0; int j; k->apply(k, inA, tmp); e = dmax(e, acmp(tmp, outA, N, "impulse 1", tol)); for (j = 0; j < rounds; ++j) { arand(inB, N); asub(inC, inA, inB, N); k->apply(k, inB, outB); k->apply(k, inC, outC); aadd(tmp, outB, outC, N); e = dmax(e, acmp(tmp, outA, N, "impulse", tol)); } return e; }
void preserves_input(dofft_closure *k, aconstrain constrain, int n, C *inA, C *inB, C *outB, int rounds) { int j; int recopy_input = k->recopy_input; k->recopy_input = 1; for (j = 0; j < rounds; ++j) { arand(inA, n); if (constrain) constrain(inA, n); acopy(inB, inA, n); k->apply(k, inB, outB); acmp(inB, inA, n, "preserves_input", 0.0); } k->recopy_input = recopy_input; }
static double verify_linear(fftd_func *dft, int N, COMPLEX *inA, COMPLEX *inB, COMPLEX *inC, COMPLEX *outA, COMPLEX *outB, COMPLEX *outC, COMPLEX *tmp, int rounds) { int i; double maxerr = 0.0; double e; /* test 1: check linearity */ for (i = 0; i < rounds; ++i) { COMPLEX alpha, beta; RE(alpha) = double_rand(); IM(alpha) = double_rand(); RE(beta) = double_rand(); IM(beta) = double_rand(); fill_random(inA, N); fill_random(inB, N); dft((double *)outA, (double *)inA); dft((double *)outB, (double *)inB); ascale(outA, alpha, N); ascale(outB, beta, N); aadd(tmp, outA, outB, N); ascale(inA, alpha, N); ascale(inB, beta, N); aadd(inC, inA, inB, N); dft((double *)outC, (double *)inC); e = acmp(outC, tmp, N); if(e > maxerr) maxerr = e; } return maxerr; }
static double verify_shift(fftd_func *dft, int N, COMPLEX *inA, COMPLEX *inB, COMPLEX *outA, COMPLEX *outB, COMPLEX *tmp, int rounds) { const double twopin = 2 * M_PI / (double) N; int i, j; double e, maxerr = 0.0; /* test 3: check the time-shift property */ /* the paper performs more tests, but this code should be fine too */ for (i = 0; i < rounds; ++i) { fill_random(inA, N); arol(inB, inA, N, 1); dft((double *)outA, (double *)inA); dft((double *)outB, (double *)inB); for (j = 0; j < N; ++j) { double s = SIGN * sin(j * twopin); double c = cos(j * twopin); int index = j; RE(tmp[index]) = RE(outB[index]) * c - IM(outB[index]) * s; IM(tmp[index]) = RE(outB[index]) * s + IM(outB[index]) * c; } e = acmp(tmp, outA, N); if(e > maxerr) maxerr = e; } return maxerr; }
void SkMultiPictureDraw::draw(bool flush) { AutoMPDReset mpdreset(this); #ifdef FORCE_SINGLE_THREAD_DRAWING_FOR_TESTING for (int i = 0; i < fThreadSafeDrawData.count(); ++i) { fThreadSafeDrawData[i].draw(); } #else sk_parallel_for(fThreadSafeDrawData.count(), [&](int i) { fThreadSafeDrawData[i].draw(); }); #endif // N.B. we could get going on any GPU work from this main thread while the CPU work runs. // But in practice, we've either got GPU work or CPU work, not both. const int count = fGPUDrawData.count(); if (0 == count) { return; } #if !defined(SK_IGNORE_GPU_LAYER_HOISTING) && SK_SUPPORT_GPU GrContext* context = fGPUDrawData[0].fCanvas->getGrContext(); SkASSERT(context); // Start by collecting all the layers that are going to be atlased and render // them (if necessary). Hoisting the free floating layers is deferred until // drawing the canvas that requires them. SkTDArray<GrHoistedLayer> atlasedNeedRendering, atlasedRecycled; for (int i = 0; i < count; ++i) { const DrawData& data = fGPUDrawData[i]; // we only expect 1 context for all the canvases SkASSERT(data.fCanvas->getGrContext() == context); if (!data.fPaint) { SkRect clipBounds; if (!data.fCanvas->getClipBounds(&clipBounds)) { continue; } SkMatrix initialMatrix = data.fCanvas->getTotalMatrix(); initialMatrix.preConcat(data.fMatrix); GrRenderTarget* rt = data.fCanvas->internal_private_accessTopLayerRenderTarget(); SkASSERT(rt); // TODO: sorting the cacheable layers from smallest to largest // would improve the packing and reduce the number of swaps // TODO: another optimization would be to make a first pass to // lock any required layer that is already in the atlas GrLayerHoister::FindLayersToAtlas(context, data.fPicture, initialMatrix, clipBounds, &atlasedNeedRendering, &atlasedRecycled, rt->numColorSamples()); } } GrLayerHoister::DrawLayersToAtlas(context, atlasedNeedRendering); SkTDArray<GrHoistedLayer> needRendering, recycled; #endif for (int i = 0; i < count; ++i) { const DrawData& data = fGPUDrawData[i]; SkCanvas* canvas = data.fCanvas; const SkPicture* picture = data.fPicture; #if !defined(SK_IGNORE_GPU_LAYER_HOISTING) && SK_SUPPORT_GPU if (!data.fPaint) { SkRect clipBounds; if (!canvas->getClipBounds(&clipBounds)) { continue; } SkAutoCanvasMatrixPaint acmp(canvas, &data.fMatrix, data.fPaint, picture->cullRect()); const SkMatrix initialMatrix = canvas->getTotalMatrix(); GrRenderTarget* rt = data.fCanvas->internal_private_accessTopLayerRenderTarget(); SkASSERT(rt); // Find the layers required by this canvas. It will return atlased // layers in the 'recycled' list since they have already been drawn. GrLayerHoister::FindLayersToHoist(context, picture, initialMatrix, clipBounds, &needRendering, &recycled, rt->numColorSamples()); GrLayerHoister::DrawLayers(context, needRendering); // Render the entire picture using new layers GrRecordReplaceDraw(picture, canvas, context->getLayerCache(), initialMatrix, NULL); GrLayerHoister::UnlockLayers(context, needRendering); GrLayerHoister::UnlockLayers(context, recycled); needRendering.rewind(); recycled.rewind(); } else #endif { canvas->drawPicture(picture, &data.fMatrix, data.fPaint); } if (flush) { canvas->flush(); } } #if !defined(SK_IGNORE_GPU_LAYER_HOISTING) && SK_SUPPORT_GPU GrLayerHoister::UnlockLayers(context, atlasedNeedRendering); GrLayerHoister::UnlockLayers(context, atlasedRecycled); #if !GR_CACHE_HOISTED_LAYERS GrLayerHoister::PurgeCache(context); #endif #endif }