bool SkDeferredDisplayListRecorder::init() { SkASSERT(fContext); SkASSERT(!fLazyProxyData); SkASSERT(!fSurface); if (!fCharacterization.isValid()) { return false; } fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>( new SkDeferredDisplayList::LazyProxyData); auto proxyProvider = fContext->contextPriv().proxyProvider(); GrSurfaceDesc desc; desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fWidth = fCharacterization.width(); desc.fHeight = fCharacterization.height(); desc.fConfig = fCharacterization.config(); desc.fSampleCnt = fCharacterization.stencilCount(); sk_sp<SkDeferredDisplayList::LazyProxyData> lazyProxyData = fLazyProxyData; // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the // DDL is being replayed into. GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone; if (fContext->caps()->usesMixedSamples() && desc.fSampleCnt > 1) { surfaceFlags |= GrInternalSurfaceFlags::kMixedSampled; } if (fContext->caps()->maxWindowRectangles() > 0) { surfaceFlags |= GrInternalSurfaceFlags::kWindowRectsSupport; } sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy( [lazyProxyData](GrResourceProvider* resourceProvider) { if (!resourceProvider) { return sk_sp<GrSurface>(); } // The proxy backing the destination surface had better have been instantiated // prior to the proxy backing the DLL's surface. Steal its GrRenderTarget. SkASSERT(lazyProxyData->fReplayDest->priv().peekSurface()); return sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->priv().peekSurface()); }, desc, fCharacterization.origin(), surfaceFlags, GrProxyProvider::Textureable(fCharacterization.isTextureable()), GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kYes); sk_sp<GrSurfaceContext> c = fContext->contextPriv().makeWrappedSurfaceContext( std::move(proxy), fCharacterization.refColorSpace(), &fCharacterization.surfaceProps()); fSurface = SkSurface_Gpu::MakeWrappedRenderTarget(fContext.get(), sk_ref_sp(c->asRenderTargetContext())); return SkToBool(fSurface.get()); }
SkShader* SkShader::CreatePictureShader(const SkPicture* src, TileMode tmx, TileMode tmy, const SkMatrix* localMatrix, const SkRect* tile) { return MakePictureShader(sk_ref_sp(const_cast<SkPicture*>(src)), tmx, tmy, localMatrix, tile).release(); }
// "Interesting" fuzzer values. static void test_linear_fuzzer(skiatest::Reporter*) { static const SkColor gColors0[] = { 0x30303030, 0x30303030 }; static const SkColor gColors1[] = { 0x30303030, 0x30303030, 0x30303030 }; static const SkScalar gPos1[] = { 0, 0, 1 }; static const SkScalar gMatrix0[9] = { 6.40969056e-10f, 0 , 6.40969056e-10f, 0 , 4.42539023e-39f, 6.40969056e-10f, 0 , 0 , 1 }; static const SkScalar gMatrix1[9] = { -2.75294113f , 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, -3.32810161e+24f, 6.40969056e-10f, 6.40969056e-10f, 0 }; static const SkScalar gMatrix2[9] = { 7.93481258e+17f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 0.688235283f }; static const SkScalar gMatrix3[9] = { 1.89180674e+11f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f, 11276.0469f , 8.12524808e+20f }; static const struct { SkPoint fPts[2]; const SkColor* fColors; const SkScalar* fPos; int fCount; SkTileMode fTileMode; uint32_t fFlags; const SkScalar* fLocalMatrix; const SkScalar* fGlobalMatrix; } gConfigs[] = { { {{0, -2.752941f}, {0, 0}}, gColors0, nullptr, SK_ARRAY_COUNT(gColors0), SkTileMode::kClamp, 0, gMatrix0, nullptr }, { {{4.42539023e-39f, -4.42539023e-39f}, {9.78041162e-15f, 4.42539023e-39f}}, gColors1, gPos1, SK_ARRAY_COUNT(gColors1), SkTileMode::kClamp, 0, nullptr, gMatrix1 }, { {{4.42539023e-39f, 6.40969056e-10f}, {6.40969056e-10f, 1.49237238e-19f}}, gColors1, gPos1, SK_ARRAY_COUNT(gColors1), SkTileMode::kClamp, 0, nullptr, gMatrix2 }, { {{6.40969056e-10f, 6.40969056e-10f}, {6.40969056e-10f, -0.688235283f}}, gColors0, nullptr, SK_ARRAY_COUNT(gColors0), SkTileMode::kClamp, 0, gMatrix3, nullptr }, }; sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB(); SkColorSpace* colorSpaces[] = { nullptr, // hits the legacy gradient impl srgb.get(), // triggers 4f/raster-pipeline }; SkPaint paint; for (auto colorSpace : colorSpaces) { sk_sp<SkSurface> surface = SkSurface::MakeRaster(SkImageInfo::Make(100, 100, kN32_SkColorType, kPremul_SkAlphaType, sk_ref_sp(colorSpace))); SkCanvas* canvas = surface->getCanvas(); for (const auto& config : gConfigs) { SkAutoCanvasRestore acr(canvas, false); SkTLazy<SkMatrix> localMatrix; if (config.fLocalMatrix) { localMatrix.init(); localMatrix.get()->set9(config.fLocalMatrix); } paint.setShader(SkGradientShader::MakeLinear(config.fPts, config.fColors, config.fPos, config.fCount, config.fTileMode, config.fFlags, localMatrix.getMaybeNull())); if (config.fGlobalMatrix) { SkMatrix m; m.set9(config.fGlobalMatrix); canvas->save(); canvas->concat(m); } canvas->drawPaint(paint); } } }
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; }
sk_sp<SkFont> SkFont::makeWithFlags(uint32_t newFlags) const { return SkFont::Make(sk_ref_sp(this->getTypeface()), this->getSize(), this->getScaleX(), this->getSkewX(), this->getMaskType(), newFlags); }
FontCache::FontCache() : m_purgePreventCount(0) { m_fontManager = sk_ref_sp(s_staticFontManager); if (!m_fontManager) m_fontManager.reset(SkFontMgr_New_DirectWrite()); ASSERT(m_fontManager.get()); }
void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawContext* drawContext, const GrClip& clip, GrDrawBatch* batch) { // Setup clip GrAppliedClip appliedClip; SkRect bounds; batch_bounds(&bounds, batch); if (!clip.apply(fContext, drawContext, &bounds, pipelineBuilder.isHWAntialias(), pipelineBuilder.hasUserStencilSettings(), &appliedClip)) { return; } // TODO: this is the only remaining usage of the AutoRestoreFragmentProcessorState - remove it GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps; if (appliedClip.getClipCoverageFragmentProcessor()) { arfps.set(&pipelineBuilder); arfps.addCoverageFragmentProcessor(sk_ref_sp(appliedClip.getClipCoverageFragmentProcessor())); } GrPipeline::CreateArgs args; args.fPipelineBuilder = &pipelineBuilder; args.fDrawContext = drawContext; args.fCaps = this->caps(); args.fScissor = &appliedClip.scissorState(); args.fHasStencilClip = appliedClip.hasStencilClip(); if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) { if (!fResourceProvider->attachStencilAttachment(drawContext->accessRenderTarget())) { SkDebugf("ERROR creating stencil attachment. Draw skipped.\n"); return; } } batch->getPipelineOptimizations(&args.fOpts); GrScissorState finalScissor; if (args.fOpts.fOverrides.fUsePLSDstRead || fClipBatchToBounds) { GrGLIRect viewport; viewport.fLeft = 0; viewport.fBottom = 0; viewport.fWidth = drawContext->width(); viewport.fHeight = drawContext->height(); SkIRect ibounds; ibounds.fLeft = SkTPin(SkScalarFloorToInt(batch->bounds().fLeft), viewport.fLeft, viewport.fWidth); ibounds.fTop = SkTPin(SkScalarFloorToInt(batch->bounds().fTop), viewport.fBottom, viewport.fHeight); ibounds.fRight = SkTPin(SkScalarCeilToInt(batch->bounds().fRight), viewport.fLeft, viewport.fWidth); ibounds.fBottom = SkTPin(SkScalarCeilToInt(batch->bounds().fBottom), viewport.fBottom, viewport.fHeight); if (appliedClip.scissorState().enabled()) { const SkIRect& scissorRect = appliedClip.scissorState().rect(); if (!ibounds.intersect(scissorRect)) { return; } } finalScissor.set(ibounds); args.fScissor = &finalScissor; } args.fOpts.fColorPOI.completeCalculations( sk_sp_address_as_pointer_address(pipelineBuilder.fColorFragmentProcessors.begin()), pipelineBuilder.numColorFragmentProcessors()); args.fOpts.fCoveragePOI.completeCalculations( sk_sp_address_as_pointer_address(pipelineBuilder.fCoverageFragmentProcessors.begin()), pipelineBuilder.numCoverageFragmentProcessors()); if (!this->setupDstReadIfNecessary(pipelineBuilder, drawContext->accessRenderTarget(), clip, args.fOpts, &args.fDstTexture, batch->bounds())) { return; } if (!batch->installPipeline(args)) { return; } #ifdef ENABLE_MDB SkASSERT(fRenderTarget); batch->pipeline()->addDependenciesTo(fRenderTarget); #endif SkRect clippedBounds; SkAssertResult(intersect(&clippedBounds, bounds, appliedClip.deviceBounds())); this->recordBatch(batch, clippedBounds); }
sk_sp<SkImage> SkImage::makeNonTextureImage() const { return sk_ref_sp(const_cast<SkImage*>(this)); }
SkImage* SkImage::NewRasterData(const Info& info, SkData* pixels, size_t rowBytes) { return MakeRasterData(info, sk_ref_sp(pixels), rowBytes).release(); }
void sk_paint_set_shader(sk_paint_t* cpaint, sk_shader_t* cshader) { AsPaint(cpaint)->setShader(sk_ref_sp(AsShader(cshader))); }
void sk_paint_set_maskfilter(sk_paint_t* cpaint, sk_maskfilter_t* cfilter) { AsPaint(cpaint)->setMaskFilter(sk_ref_sp(AsMaskFilter(cfilter))); }
SkScalerContext* SkTestTypeface::onCreateScalerContext( const SkScalerContextEffects& effects, const SkDescriptor* desc) const { return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc); }
void NativeImageSkia::drawPattern( GraphicsContext* context, const FloatRect& floatSrcRect, const FloatSize& scale, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect, WebBlendMode blendMode, const IntSize& repeatSpacing) const { FloatRect normSrcRect = floatSrcRect; normSrcRect.intersect(FloatRect(0, 0, bitmap().width(), bitmap().height())); if (destRect.isEmpty() || normSrcRect.isEmpty()) return; // nothing to draw SkMatrix totalMatrix = context->getTotalMatrix(); AffineTransform ctm = context->getCTM(); SkScalar ctmScaleX = ctm.xScale(); SkScalar ctmScaleY = ctm.yScale(); totalMatrix.preScale(scale.width(), scale.height()); // Figure out what size the bitmap will be in the destination. The // destination rect is the bounds of the pattern, we need to use the // matrix to see how big it will be. SkRect destRectTarget; totalMatrix.mapRect(&destRectTarget, normSrcRect); float destBitmapWidth = SkScalarToFloat(destRectTarget.width()); float destBitmapHeight = SkScalarToFloat(destRectTarget.height()); bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap()); // Compute the resampling mode. InterpolationQuality resampling; if (context->isAccelerated()) resampling = InterpolationLow; else if (isLazyDecoded) resampling = InterpolationHigh; else resampling = computeInterpolationQuality(totalMatrix, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight, isDataComplete()); resampling = limitInterpolationQuality(context, resampling); SkMatrix localMatrix; // We also need to translate it such that the origin of the pattern is the // origin of the destination rect, which is what WebKit expects. Skia uses // the coordinate system origin as the base for the pattern. If WebKit wants // a shifted image, it will shift it from there using the localMatrix. const float adjustedX = phase.x() + normSrcRect.x() * scale.width(); const float adjustedY = phase.y() + normSrcRect.y() * scale.height(); localMatrix.setTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjustedY)); sk_sp<SkShader> shader; SkFilterQuality filterLevel = static_cast<SkFilterQuality>(resampling); // Bicubic filter is only applied to defer-decoded images, see // NativeImageSkia::draw for details. if (resampling == InterpolationHigh && !isLazyDecoded) { // Do nice resampling. filterLevel = kNone_SkFilterQuality; float scaleX = destBitmapWidth / normSrcRect.width(); float scaleY = destBitmapHeight / normSrcRect.height(); SkRect scaledSrcRect; // Since we are resizing the bitmap, we need to remove the scale // applied to the pixels in the bitmap shader. This means we need // CTM * localMatrix to have identity scale. Since we // can't modify CTM (or the rectangle will be drawn in the wrong // place), we must set localMatrix's scale to the inverse of // CTM scale. localMatrix.preScale(ctmScaleX ? 1 / ctmScaleX : 1, ctmScaleY ? 1 / ctmScaleY : 1); // The image fragment generated here is not exactly what is // requested. The scale factor used is approximated and image // fragment is slightly larger to align to integer // boundaries. SkBitmap resampled = extractScaledImageFragment(normSrcRect, scaleX, scaleY, &scaledSrcRect); if (repeatSpacing.isZero()) { shader = SkShader::MakeBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix); } else { shader = SkShader::MakeBitmapShader( createBitmapWithSpace(resampled, repeatSpacing.width() * ctmScaleX, repeatSpacing.height() * ctmScaleY), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix); } } else { // Because no resizing occurred, the shader transform should be // set to the pattern's transform, which just includes scale. localMatrix.preScale(scale.width(), scale.height()); // No need to resample before drawing. SkBitmap srcSubset; bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect)); if (repeatSpacing.isZero()) { shader = SkShader::MakeBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix); } else { shader = SkShader::MakeBitmapShader( createBitmapWithSpace(srcSubset, repeatSpacing.width() * ctmScaleX, repeatSpacing.height() * ctmScaleY), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix); } } SkPaint paint; paint.setShader(shader); paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp, blendMode)); paint.setColorFilter(sk_ref_sp(context->colorFilter())); paint.setFilterQuality(filterLevel); context->drawRect(destRect, paint); }
static sk_sp<SkImage> make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpace colorSpace, bool nv12, const GrBackendObject yuvTextureHandles[], const SkISize yuvSizes[], GrSurfaceOrigin origin, sk_sp<SkColorSpace> imageColorSpace) { const SkBudgeted budgeted = SkBudgeted::kYes; if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 || yuvSizes[1].fWidth <= 0 || yuvSizes[1].fHeight <= 0) { return nullptr; } if (!nv12 && (yuvSizes[2].fWidth <= 0 || yuvSizes[2].fHeight <= 0)) { return nullptr; } const GrPixelConfig kConfig = nv12 ? kRGBA_8888_GrPixelConfig : kAlpha_8_GrPixelConfig; GrBackendTextureDesc yDesc; yDesc.fConfig = kConfig; yDesc.fOrigin = origin; yDesc.fSampleCnt = 0; yDesc.fTextureHandle = yuvTextureHandles[0]; yDesc.fWidth = yuvSizes[0].fWidth; yDesc.fHeight = yuvSizes[0].fHeight; GrBackendTextureDesc uDesc; uDesc.fConfig = kConfig; uDesc.fOrigin = origin; uDesc.fSampleCnt = 0; uDesc.fTextureHandle = yuvTextureHandles[1]; uDesc.fWidth = yuvSizes[1].fWidth; uDesc.fHeight = yuvSizes[1].fHeight; sk_sp<GrSurfaceProxy> yProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, yDesc); sk_sp<GrSurfaceProxy> uProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, uDesc); sk_sp<GrSurfaceProxy> vProxy; if (nv12) { vProxy = uProxy; } else { GrBackendTextureDesc vDesc; vDesc.fConfig = kConfig; vDesc.fOrigin = origin; vDesc.fSampleCnt = 0; vDesc.fTextureHandle = yuvTextureHandles[2]; vDesc.fWidth = yuvSizes[2].fWidth; vDesc.fHeight = yuvSizes[2].fHeight; vProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, vDesc); } if (!yProxy || !uProxy || !vProxy) { return nullptr; } const int width = yuvSizes[0].fWidth; const int height = yuvSizes[0].fHeight; // Needs to be a render target in order to draw to it for the yuv->rgb conversion. sk_sp<GrRenderTargetContext> renderTargetContext(ctx->makeRenderTargetContext( SkBackingFit::kExact, width, height, kRGBA_8888_GrPixelConfig, std::move(imageColorSpace), 0, origin)); if (!renderTargetContext) { return nullptr; } GrPaint paint; paint.setPorterDuffXPFactory(SkBlendMode::kSrc); paint.addColorFragmentProcessor( GrYUVEffect::MakeYUVToRGB(ctx->resourceProvider(), sk_ref_sp(yProxy->asTextureProxy()), sk_ref_sp(uProxy->asTextureProxy()), sk_ref_sp(vProxy->asTextureProxy()), yuvSizes, colorSpace, nv12)); const SkRect rect = SkRect::MakeIWH(width, height); renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect); if (!renderTargetContext->asSurfaceProxy()) { return nullptr; } ctx->contextPriv().flushSurfaceWrites(renderTargetContext->asSurfaceProxy()); // MDB: this call is okay bc we know 'renderTargetContext' was exact return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID, kOpaque_SkAlphaType, renderTargetContext->asTextureProxyRef(), renderTargetContext->refColorSpace(), budgeted); }
sk_sp<SkImage> SkImage::makeNonTextureImage() const { if (!this->isTextureBacked()) { return sk_ref_sp(const_cast<SkImage*>(this)); } return this->makeRasterImage(); }
SkImage* SkImage::NewFromEncoded(SkData* encoded, const SkIRect* subset) { return MakeFromEncoded(sk_ref_sp(encoded), subset).release(); }
sk_sp<SkShader> SkImage::makeShader(SkShader::TileMode tileX, SkShader::TileMode tileY, const SkMatrix* localMatrix) const { return SkImageShader::Make(sk_ref_sp(const_cast<SkImage*>(this)), tileX, tileY, localMatrix); }
SkImage* SkImage::NewFromPicture(const SkPicture* picture, const SkISize& dimensions, const SkMatrix* matrix, const SkPaint* paint) { return MakeFromPicture(sk_ref_sp(const_cast<SkPicture*>(picture)), dimensions, matrix, paint).release(); }
static sk_sp<SkImage> make_pict_gen(GrContext*, SkPicture* pic, const SkImageInfo& info) { return SkImage::MakeFromPicture(sk_ref_sp(pic), info.dimensions(), nullptr, nullptr); }
sk_sp<SkFont> SkFont::makeWithSize(SkScalar newSize) const { return SkFont::Make(sk_ref_sp(this->getTypeface()), newSize, this->getScaleX(), this->getSkewX(), this->getMaskType(), this->getFlags()); }
SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex); }
SkShader* SkShader::CreateComposeShader(SkShader* dst, SkShader* src, SkXfermode* xfer) { return MakeComposeShader(sk_ref_sp(dst), sk_ref_sp(src), xfer).release(); }
sk_sp<SkSurface> VulkanWindowContext::getBackbufferSurface() { BackbufferInfo* backbuffer = this->getAvailableBackbuffer(); SkASSERT(backbuffer); // reset the fence GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, ResetFences(fBackendContext->fDevice, 2, backbuffer->fUsageFences)); // semaphores should be in unsignaled state // acquire the image VkResult res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64_MAX, backbuffer->fAcquireSemaphore, VK_NULL_HANDLE, &backbuffer->fImageIndex); if (VK_ERROR_SURFACE_LOST_KHR == res) { // need to figure out how to create a new vkSurface without the platformData* // maybe use attach somehow? but need a Window return nullptr; } if (VK_ERROR_OUT_OF_DATE_KHR == res) { // tear swapchain down and try again if (!this->createSwapchain(0, 0, fDisplayParams)) { return nullptr; } // acquire the image res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64_MAX, backbuffer->fAcquireSemaphore, VK_NULL_HANDLE, &backbuffer->fImageIndex); if (VK_SUCCESS != res) { return nullptr; } } // set up layout transfer from initial to color attachment VkImageLayout layout = fImageLayouts[backbuffer->fImageIndex]; VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ? VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkAccessFlags srcAccessMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ? 0 : VK_ACCESS_MEMORY_READ_BIT; VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType NULL, // pNext srcAccessMask, // outputMask dstAccessMask, // inputMask layout, // oldLayout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout fPresentQueueIndex, // srcQueueFamilyIndex fBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex fImages[backbuffer->fImageIndex], // image { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange }; GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[0], 0)); VkCommandBufferBeginInfo info; memset(&info, 0, sizeof(VkCommandBufferBeginInfo)); info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; info.flags = 0; GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[0], &info)); GR_VK_CALL(fBackendContext->fInterface, CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[0], srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier)); GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, EndCommandBuffer(backbuffer->fTransitionCmdBuffers[0])); VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // insert the layout transfer into the queue and wait on the acquire VkSubmitInfo submitInfo; memset(&submitInfo, 0, sizeof(VkSubmitInfo)); submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &backbuffer->fAcquireSemaphore; submitInfo.pWaitDstStageMask = &waitDstStageFlags; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[0]; submitInfo.signalSemaphoreCount = 0; GR_VK_CALL_ERRCHECK(fBackendContext->fInterface, QueueSubmit(fBackendContext->fQueue, 1, &submitInfo, backbuffer->fUsageFences[0])); return sk_ref_sp(fSurfaces[backbuffer->fImageIndex].get()); }
sk_sp<SkTypeface> SkTypeface::MakeDefault(Style style) { return sk_ref_sp(GetDefaultTypeface(style)); }