bool SkCullPoints::sect_test(int x0, int y0, int x1, int y1) const { const SkIRect& r = fR; if (x0 < r.fLeft && x1 < r.fLeft || x0 > r.fRight && x1 > r.fRight || y0 < r.fTop && y1 < r.fTop || y0 > r.fBottom && y1 > r.fBottom) return false; // since the crossprod test is a little expensive, check for easy-in cases first if (r.contains(x0, y0) || r.contains(x1, y1)) return true; // At this point we're not sure, so we do a crossprod test SkIPoint vec; const SkIPoint* rAsQuad = fAsQuad; vec.set(x1 - x0, y1 - y0); bool isNeg = cross_product_is_neg(vec, x0 - rAsQuad[0].fX, y0 - rAsQuad[0].fY); for (int i = 1; i < 4; i++) { if (cross_product_is_neg(vec, x0 - rAsQuad[i].fX, y0 - rAsQuad[i].fY) != isNeg) { return true; } } return false; // we didn't intersect }
void State::setViewport(int w, int h) { fViewport.set(w, h); if (fView) { fView->setSize(SkIntToScalar(w), SkIntToScalar(h)); } resetGpuState(); }
PatchView() : fAngle(0) { fShader0 = make_shader0(&fSize0); fSize1 = fSize0; if (fSize0.fX == 0 || fSize0.fY == 0) { fSize1.set(2, 2); } fShader1 = make_shader1(fSize1); const SkScalar S = SkIntToScalar(50); const SkScalar T = SkIntToScalar(40); fPts[0].set(S*0, T); fPts[1].set(S*1, T); fPts[2].set(S*2, T); fPts[3].set(S*3, T); fPts[4].set(S*3, T*2); fPts[5].set(S*3, T*3); fPts[6].set(S*3, T*4); fPts[7].set(S*2, T*4); fPts[8].set(S*1, T*4); fPts[9].set(S*0, T*4); fPts[10].set(S*0, T*3); fPts[11].set(S*0, T*2); this->setBGColor(SK_ColorGRAY); }
static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, const SkIRect* subset) { if (NULL == texture) { return NULL; } GrContext* context = texture->getContext(); if (NULL == context) { return NULL; } GrTextureDesc desc; SkIPoint pointStorage; SkIPoint* topLeft; if (subset != NULL) { SkASSERT(SkIRect::MakeWH(texture->width(), texture->height()).contains(*subset)); // Create a new texture that is the size of subset. desc.fWidth = subset->width(); desc.fHeight = subset->height(); pointStorage.set(subset->x(), subset->y()); topLeft = &pointStorage; } else { desc.fWidth = texture->width(); desc.fHeight = texture->height(); topLeft = NULL; } desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; desc.fConfig = texture->config(); SkImageInfo info; if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) { return NULL; } info.fWidth = desc.fWidth; info.fHeight = desc.fHeight; info.fAlphaType = kPremul_SkAlphaType; GrTexture* dst = context->createUncachedTexture(desc, NULL, 0); if (NULL == dst) { return NULL; } context->copyTexture(texture, dst->asRenderTarget(), topLeft); // TODO: figure out if this is responsible for Chrome canvas errors #if 0 // The render texture we have created (to perform the copy) isn't fully // functional (since it doesn't have a stencil buffer). Release it here // so the caller doesn't try to render to it. // TODO: we can undo this release when dynamic stencil buffer attach/ // detach has been implemented dst->releaseRenderTarget(); #endif SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst)); SkSafeUnref(dst); return pixelRef; }
bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, const SkIRect* subset, SkBitmap* dst, SkDiscardableMemory::Factory* factory) { SkAutoTDelete<SkImageGenerator> autoGenerator(generator); if (NULL == autoGenerator.get()) { return false; } SkImageInfo prInfo = autoGenerator->getInfo(); if (prInfo.isEmpty()) { return false; } SkIPoint origin = SkIPoint::Make(0, 0); SkImageInfo bmInfo = prInfo; if (subset) { const SkIRect prBounds = SkIRect::MakeWH(prInfo.width(), prInfo.height()); if (subset->isEmpty() || !prBounds.contains(*subset)) { return false; } bmInfo = prInfo.makeWH(subset->width(), subset->height()); origin.set(subset->x(), subset->y()); } // must compute our desired rowBytes w.r.t. the pixelRef's dimensions, not ours, which may be // smaller. if (!dst->setInfo(bmInfo, prInfo.minRowBytes())) { return false; } // Since dst->setInfo() may have changed/fixed-up info, we check from the bitmap SkASSERT(dst->info().colorType() != kUnknown_SkColorType); if (dst->empty()) { // Use a normal pixelref. return dst->tryAllocPixels(); } SkAutoTUnref<SkDiscardablePixelRef> ref( new SkDiscardablePixelRef(prInfo, autoGenerator.detach(), dst->rowBytes(), factory)); dst->setPixelRef(ref, origin.x(), origin.y()); return true; }
sk_sp<GrDrawContext> GaussianBlur(GrContext* context, GrTexture* origSrc, sk_sp<SkColorSpace> colorSpace, const SkIRect& dstBounds, const SkIRect* srcBounds, float sigmaX, float sigmaY, SkBackingFit fit) { SkASSERT(context); SkIRect clearRect; int scaleFactorX, radiusX; int scaleFactorY, radiusY; int maxTextureSize = context->caps()->maxTextureSize(); sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX); sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY); SkASSERT(sigmaX || sigmaY); SkIPoint srcOffset = SkIPoint::Make(-dstBounds.x(), -dstBounds.y()); SkIRect localDstBounds = SkIRect::MakeWH(dstBounds.width(), dstBounds.height()); SkIRect localSrcBounds; SkIRect srcRect; if (srcBounds) { srcRect = localSrcBounds = *srcBounds; srcRect.offset(srcOffset); srcBounds = &localSrcBounds; } else { srcRect = localDstBounds; } scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); scale_irect(&srcRect, scaleFactorX, scaleFactorY); // setup new clip GrFixedClip clip(localDstBounds); sk_sp<GrTexture> srcTexture(sk_ref_sp(origSrc)); SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() || kRGBA_8888_GrPixelConfig == srcTexture->config() || kSRGBA_8888_GrPixelConfig == srcTexture->config() || kSBGRA_8888_GrPixelConfig == srcTexture->config() || kRGBA_half_GrPixelConfig == srcTexture->config() || kAlpha_8_GrPixelConfig == srcTexture->config()); const int width = dstBounds.width(); const int height = dstBounds.height(); const GrPixelConfig config = srcTexture->config(); sk_sp<GrDrawContext> dstDrawContext(context->makeDrawContext(fit, width, height, config, colorSpace, 0, kDefault_GrSurfaceOrigin)); if (!dstDrawContext) { return nullptr; } // For really small blurs (certainly no wider than 5x5 on desktop gpus) it is faster to just // launch a single non separable kernel vs two launches if (sigmaX > 0.0f && sigmaY > 0.0f && (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) { // We shouldn't be scaling because this is a small size blur SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY)); convolve_gaussian_2d(dstDrawContext.get(), clip, localDstBounds, srcOffset, srcTexture.get(), radiusX, radiusY, sigmaX, sigmaY, srcBounds); return dstDrawContext; } sk_sp<GrDrawContext> tmpDrawContext(context->makeDrawContext(fit, width, height, config, colorSpace, 0, kDefault_GrSurfaceOrigin)); if (!tmpDrawContext) { return nullptr; } sk_sp<GrDrawContext> srcDrawContext; SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY)); for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { GrPaint paint; paint.setGammaCorrect(dstDrawContext->isGammaCorrect()); SkMatrix matrix; matrix.setIDiv(srcTexture->width(), srcTexture->height()); SkIRect dstRect(srcRect); if (srcBounds && i == 1) { SkRect domain; matrix.mapRect(&domain, SkRect::Make(*srcBounds)); domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width() : 0.0f, (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height() : 0.0f); sk_sp<GrFragmentProcessor> fp(GrTextureDomainEffect::Make( srcTexture.get(), nullptr, matrix, domain, GrTextureDomain::kDecal_Mode, GrTextureParams::kBilerp_FilterMode)); paint.addColorFragmentProcessor(std::move(fp)); srcRect.offset(-srcOffset); srcOffset.set(0, 0); } else { GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode); paint.addColorTextureProcessor(srcTexture.get(), nullptr, matrix, params); } paint.setPorterDuffXPFactory(SkBlendMode::kSrc); shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY); dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect), SkRect::Make(srcRect)); srcDrawContext = dstDrawContext; srcRect = dstRect; srcTexture = srcDrawContext->asTexture(); dstDrawContext.swap(tmpDrawContext); localSrcBounds = srcRect; } srcRect = localDstBounds; scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); if (sigmaX > 0.0f) { if (scaleFactorX > 1) { SkASSERT(srcDrawContext); // Clear out a radius to the right of the srcRect to prevent the // X convolution from reading garbage. clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, radiusX, srcRect.height()); srcDrawContext->clear(&clearRect, 0x0, false); } convolve_gaussian(dstDrawContext.get(), clip, srcRect, srcTexture.get(), Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, srcBounds, srcOffset); srcDrawContext = dstDrawContext; srcTexture = srcDrawContext->asTexture(); srcRect.offsetTo(0, 0); dstDrawContext.swap(tmpDrawContext); localSrcBounds = srcRect; srcOffset.set(0, 0); } if (sigmaY > 0.0f) { if (scaleFactorY > 1 || sigmaX > 0.0f) { SkASSERT(srcDrawContext); // Clear out a radius below the srcRect to prevent the Y // convolution from reading garbage. clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, srcRect.width(), radiusY); srcDrawContext->clear(&clearRect, 0x0, false); } convolve_gaussian(dstDrawContext.get(), clip, srcRect, srcTexture.get(), Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, srcBounds, srcOffset); srcDrawContext = dstDrawContext; srcRect.offsetTo(0, 0); dstDrawContext.swap(tmpDrawContext); } SkASSERT(srcDrawContext); srcTexture = nullptr; // we don't use this from here on out if (scaleFactorX > 1 || scaleFactorY > 1) { // Clear one pixel to the right and below, to accommodate bilinear upsampling. clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, srcRect.width() + 1, 1); srcDrawContext->clear(&clearRect, 0x0, false); clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, 1, srcRect.height()); srcDrawContext->clear(&clearRect, 0x0, false); SkMatrix matrix; matrix.setIDiv(srcDrawContext->width(), srcDrawContext->height()); GrPaint paint; paint.setGammaCorrect(dstDrawContext->isGammaCorrect()); // FIXME: this should be mitchell, not bilinear. GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode); sk_sp<GrTexture> tex(srcDrawContext->asTexture()); paint.addColorTextureProcessor(tex.get(), nullptr, matrix, params); paint.setPorterDuffXPFactory(SkBlendMode::kSrc); SkIRect dstRect(srcRect); scale_irect(&dstRect, scaleFactorX, scaleFactorY); dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect), SkRect::Make(srcRect)); srcDrawContext = dstDrawContext; srcRect = dstRect; dstDrawContext.swap(tmpDrawContext); } return srcDrawContext; }