DEF_GPUTEST_FOR_ALL_CONTEXTS(VertexAttributeCount, reporter, ctxInfo) { GrContext* context = ctxInfo.grContext(); sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox, 1, 1, kRGBA_8888_GrPixelConfig)); if (!drawContext) { ERRORF(reporter, "Could not create draw context."); return; } int attribCnt = context->caps()->maxVertexAttributes(); if (!attribCnt) { ERRORF(reporter, "No attributes allowed?!"); return; } context->flush(); context->resetGpuStats(); #if GR_GPU_STATS REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0); REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 0); #endif SkAutoTUnref<GrDrawBatch> batch; GrPaint grPaint; // This one should succeed. batch.reset(new Batch(attribCnt)); drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch); context->flush(); #if GR_GPU_STATS REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 1); REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 0); #endif context->resetGpuStats(); // This one should fail. batch.reset(new Batch(attribCnt+1)); drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch); context->flush(); #if GR_GPU_STATS REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0); REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 1); #endif }
sk_sp<SkSpecialImage> SkDisplacementMapEffect::onFilterImage(SkSpecialImage* source, const Context& ctx, SkIPoint* offset) const { SkIPoint colorOffset = SkIPoint::Make(0, 0); sk_sp<SkSpecialImage> color(this->filterInput(1, source, ctx, &colorOffset)); if (!color) { return nullptr; } SkIPoint displOffset = SkIPoint::Make(0, 0); sk_sp<SkSpecialImage> displ(this->filterInput(0, source, ctx, &displOffset)); if (!displ) { return nullptr; } const SkIRect srcBounds = SkIRect::MakeXYWH(colorOffset.x(), colorOffset.y(), color->width(), color->height()); // Both paths do bounds checking on color pixel access, we don't need to // pad the color bitmap to bounds here. SkIRect bounds; if (!this->applyCropRect(ctx, srcBounds, &bounds)) { return nullptr; } SkIRect displBounds; displ = this->applyCropRect(ctx, displ.get(), &displOffset, &displBounds); if (!displ) { return nullptr; } if (!bounds.intersect(displBounds)) { return nullptr; } const SkIRect colorBounds = bounds.makeOffset(-colorOffset.x(), -colorOffset.y()); SkVector scale = SkVector::Make(fScale, fScale); ctx.ctm().mapVectors(&scale, 1); #if SK_SUPPORT_GPU if (source->isTextureBacked()) { GrContext* context = source->getContext(); sk_sp<GrTexture> colorTexture(color->asTextureRef(context)); sk_sp<GrTexture> displTexture(displ->asTextureRef(context)); if (!colorTexture || !displTexture) { return nullptr; } GrPaint paint; SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displTexture.get()); offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displOffset.fX), SkIntToScalar(colorOffset.fY - displOffset.fY)); paint.addColorFragmentProcessor( GrDisplacementMapEffect::Make(fXChannelSelector, fYChannelSelector, scale, displTexture.get(), offsetMatrix, colorTexture.get(), SkISize::Make(color->width(), color->height()))); paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); SkMatrix matrix; matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y())); sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox, bounds.width(), bounds.height(), kSkia8888_GrPixelConfig)); if (!drawContext) { return nullptr; } drawContext->drawRect(GrNoClip(), paint, matrix, SkRect::Make(colorBounds)); offset->fX = bounds.left(); offset->fY = bounds.top(); return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()), kNeedNewImageUniqueID_SpecialImage, drawContext->asTexture()); } #endif SkBitmap colorBM, displBM; if (!color->getROPixels(&colorBM) || !displ->getROPixels(&displBM)) { return nullptr; } if ((colorBM.colorType() != kN32_SkColorType) || (displBM.colorType() != kN32_SkColorType)) { return nullptr; } SkAutoLockPixels colorLock(colorBM), displLock(displBM); if (!colorBM.getPixels() || !displBM.getPixels()) { return nullptr; } SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(), colorBM.alphaType()); SkBitmap dst; if (!dst.tryAllocPixels(info)) { return nullptr; } SkAutoLockPixels dstLock(dst); computeDisplacement(fXChannelSelector, fYChannelSelector, scale, &dst, displBM, colorOffset - displOffset, colorBM, colorBounds); offset->fX = bounds.left(); offset->fY = bounds.top(); return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), dst); }
sk_sp<SkSpecialImage> SkXfermodeImageFilter::filterImageGPU(SkSpecialImage* source, sk_sp<SkSpecialImage> background, const SkIPoint& backgroundOffset, sk_sp<SkSpecialImage> foreground, const SkIPoint& foregroundOffset, const SkIRect& bounds) const { SkASSERT(source->isTextureBacked()); GrContext* context = source->getContext(); sk_sp<GrTexture> backgroundTex, foregroundTex; if (background) { backgroundTex = background->asTextureRef(context); } if (foreground) { foregroundTex = foreground->asTextureRef(context); } GrPaint paint; // SRGBTODO: AllowSRGBInputs? SkAutoTUnref<const GrFragmentProcessor> bgFP; if (backgroundTex) { SkMatrix backgroundMatrix; backgroundMatrix.setIDiv(backgroundTex->width(), backgroundTex->height()); backgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX), SkIntToScalar(-backgroundOffset.fY)); bgFP.reset(GrTextureDomainEffect::Create( backgroundTex.get(), backgroundMatrix, GrTextureDomain::MakeTexelDomain(backgroundTex.get(), background->subset()), GrTextureDomain::kDecal_Mode, GrTextureParams::kNone_FilterMode)); } else { bgFP.reset(GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK, GrConstColorProcessor::kIgnore_InputMode)); } if (foregroundTex) { SkMatrix foregroundMatrix; foregroundMatrix.setIDiv(foregroundTex->width(), foregroundTex->height()); foregroundMatrix.preTranslate(SkIntToScalar(-foregroundOffset.fX), SkIntToScalar(-foregroundOffset.fY)); SkAutoTUnref<const GrFragmentProcessor> foregroundFP; foregroundFP.reset(GrTextureDomainEffect::Create( foregroundTex.get(), foregroundMatrix, GrTextureDomain::MakeTexelDomain(foregroundTex.get(), foreground->subset()), GrTextureDomain::kDecal_Mode, GrTextureParams::kNone_FilterMode)); paint.addColorFragmentProcessor(foregroundFP.get()); // A null fMode is interpreted to mean kSrcOver_Mode (to match raster). SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get())); if (!mode) { // It would be awesome to use SkXfermode::Create here but it knows better // than us and won't return a kSrcOver_Mode SkXfermode. That means we // have to get one the hard way. struct ProcCoeff rec; rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode); SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC); mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode)); } sk_sp<const GrFragmentProcessor> xferFP(mode->getFragmentProcessorForImageFilter(bgFP)); // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed if (xferFP) { paint.addColorFragmentProcessor(xferFP.get()); } } else { paint.addColorFragmentProcessor(bgFP); } paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); sk_sp<GrDrawContext> drawContext(context->newDrawContext(GrContext::kLoose_BackingFit, bounds.width(), bounds.height(), kSkia8888_GrPixelConfig)); if (!drawContext) { return nullptr; } SkMatrix matrix; matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(bounds)); return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()), kNeedNewImageUniqueID_SpecialImage, drawContext->asTexture()); }