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());
}
Esempio n. 2
0
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();
}
Esempio n. 3
0
// "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);
        }
    }
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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());
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
sk_sp<SkImage> SkImage::makeNonTextureImage() const {
    return sk_ref_sp(const_cast<SkImage*>(this));
}
Esempio n. 9
0
SkImage* SkImage::NewRasterData(const Info& info, SkData* pixels, size_t rowBytes) {
    return MakeRasterData(info, sk_ref_sp(pixels), rowBytes).release();
}
Esempio n. 10
0
void sk_paint_set_shader(sk_paint_t* cpaint, sk_shader_t* cshader) {
    AsPaint(cpaint)->setShader(sk_ref_sp(AsShader(cshader)));
}
Esempio n. 11
0
void sk_paint_set_maskfilter(sk_paint_t* cpaint, sk_maskfilter_t* cfilter) {
    AsPaint(cpaint)->setMaskFilter(sk_ref_sp(AsMaskFilter(cfilter)));
}
Esempio n. 12
0
SkScalerContext* SkTestTypeface::onCreateScalerContext(
    const SkScalerContextEffects& effects, const SkDescriptor* desc) const
{
    return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc);
}
Esempio n. 13
0
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);
}
Esempio n. 14
0
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);
}
Esempio n. 15
0
sk_sp<SkImage> SkImage::makeNonTextureImage() const {
    if (!this->isTextureBacked()) {
        return sk_ref_sp(const_cast<SkImage*>(this));
    }
    return this->makeRasterImage();
}
Esempio n. 16
0
SkImage* SkImage::NewFromEncoded(SkData* encoded, const SkIRect* subset) {
    return MakeFromEncoded(sk_ref_sp(encoded), subset).release();
}
Esempio n. 17
0
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);
}
Esempio n. 18
0
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();
}
Esempio n. 19
0
static sk_sp<SkImage> make_pict_gen(GrContext*, SkPicture* pic, const SkImageInfo& info) {
    return SkImage::MakeFromPicture(sk_ref_sp(pic), info.dimensions(), nullptr, nullptr);
}
Esempio n. 20
0
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());
}
Esempio n. 21
0
 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
     return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
 }
Esempio n. 22
0
SkShader* SkShader::CreateComposeShader(SkShader* dst, SkShader* src, SkXfermode* xfer) {
    return MakeComposeShader(sk_ref_sp(dst), sk_ref_sp(src), xfer).release();
}
Esempio n. 23
0
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());
}
Esempio n. 24
0
sk_sp<SkTypeface> SkTypeface::MakeDefault(Style style) {
    return sk_ref_sp(GetDefaultTypeface(style));
}