Esempio n. 1
0
bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
                                   SkBitmap* result, SkIPoint* offset) const {
#if SK_SUPPORT_GPU
    SkBitmap input = src;
    SkASSERT(fInputCount == 1);
    SkIPoint srcOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPU(0, proxy, src, ctx, &input, &srcOffset)) {
        return false;
    }
    GrTexture* srcTexture = input.getTexture();
    SkIRect bounds;
    if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
        return false;
    }
    SkRect srcRect = SkRect::Make(bounds);
    SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
    GrContext* context = srcTexture->getContext();

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag,
    desc.fWidth = bounds.width();
    desc.fHeight = bounds.height();
    desc.fConfig = kRGBA_8888_GrPixelConfig;

    SkAutoTUnref<GrTexture> dst(context->textureProvider()->createTexture(desc,
                                      GrTextureProvider::FromImageFilter(ctx.sizeConstraint())));
    if (!dst) {
        return false;
    }

    // setup new clip
    GrClip clip(dstRect);

    GrFragmentProcessor* fp;
    offset->fX = bounds.left();
    offset->fY = bounds.top();
    bounds.offset(-srcOffset);
    SkMatrix matrix(ctx.ctm());
    matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
    GrPaint paint;
    if (this->asFragmentProcessor(&fp, srcTexture, matrix, bounds)) {
        SkASSERT(fp);
        paint.addColorFragmentProcessor(fp)->unref();
        paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

        SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
        if (drawContext) {
            drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);

            WrapTexture(dst, bounds.width(), bounds.height(), result);
            return true;
        }
    }
#endif
    return false;
}
Esempio n. 2
0
void GrRenderTarget::discard() {
    // go through context so that all necessary flushing occurs
    GrContext* context = this->getContext();
    GrDrawContext* drawContext = context ? context->drawContext() : NULL;
    if (!drawContext) {
        return;
    }

    drawContext->discard(this);
}
void GrRenderTarget::discard() {
    // go through context so that all necessary flushing occurs
    GrContext* context = this->getContext();
    if (!context) {
        return;
    }

    sk_sp<GrDrawContext> drawContext(context->drawContext(sk_ref_sp(this), nullptr));
    if (!drawContext) {
        return;
    }

    drawContext->discard();
}
DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(VertexAttributeCount, reporter, ctxInfo) {
    GrContext* context = ctxInfo.fGrContext;
    GrTextureDesc desc;
    desc.fHeight = 1;
    desc.fWidth = 1;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fConfig = kRGBA_8888_GrPixelConfig;
    SkAutoTUnref<GrTexture> target(context->textureProvider()->createTexture(desc,
                                                                             SkBudgeted::kYes));
    if (!target) {
        ERRORF(reporter, "Could not create render target.");
        return;
    }
    SkAutoTUnref<GrDrawContext> dc(context->drawContext(target->asRenderTarget()));
    if (!dc) {
        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;
    GrPipelineBuilder pb;
    pb.setRenderTarget(target->asRenderTarget());
    // This one should succeed.
    batch.reset(new Batch(attribCnt));
    dc->drawContextPriv().testingOnly_drawBatch(pb, 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));
    dc->drawContextPriv().testingOnly_drawBatch(pb, batch);
    context->flush();
#if GR_GPU_STATS
    REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0);
    REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 1);
#endif
}
Esempio n. 5
0
bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
                                                     const SkBitmap& src,
                                                     const Context& ctx,
                                                     SkBitmap* result,
                                                     SkIPoint* offset) const {
    GrContext* context = nullptr;
    SkBitmap background = src;
    SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &background, &backgroundOffset)) {
        background.reset();
    }
    GrTexture* backgroundTex = background.getTexture();
    if (backgroundTex) {
        context = backgroundTex->getContext();
    }

    SkBitmap foreground = src;
    SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPUDeprecated(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
        foreground.reset();
    }
    GrTexture* foregroundTex = foreground.getTexture();
    if (foregroundTex) {
        context = foregroundTex->getContext();
    }

    if (!context) {
        return false;
    }

    SkIRect bounds = background.bounds().makeOffset(backgroundOffset.x(), backgroundOffset.y());
    bounds.join(foreground.bounds().makeOffset(foregroundOffset.x(), foregroundOffset.y()));
    if (bounds.isEmpty()) {
        return false;
    }

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = bounds.width();
    desc.fHeight = bounds.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
    if (!dst) {
        return false;
    }

    GrPaint paint;
    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, backgroundMatrix,
                            GrTextureDomain::MakeTexelDomain(backgroundTex, background.bounds()),
                            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, foregroundMatrix,
                            GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
                            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));
        }

        SkAutoTUnref<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);
        }
    } else {
        paint.addColorFragmentProcessor(bgFP);
    }

    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

    SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
    if (!drawContext) {
        return false;
    }

    SkMatrix matrix;
    matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
    drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(bounds));

    offset->fX = bounds.left();
    offset->fY = bounds.top();
    GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result);
    return true;
}
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;
        }

        GrSurfaceDesc desc;
        desc.fFlags = kRenderTarget_GrSurfaceFlag;
        desc.fWidth = bounds.width();
        desc.fHeight = bounds.height();
        desc.fConfig = kSkia8888_GrPixelConfig;

        SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
        if (!dst) {
            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::Create(fXChannelSelector,
                                            fYChannelSelector,
                                            scale,
                                            displTexture.get(),
                                            offsetMatrix,
                                            colorTexture.get(),
                                            SkISize::Make(color->width(),
                                                          color->height())))->unref();
        paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
        SkMatrix matrix;
        matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y()));

        SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
        if (!drawContext) {
            return nullptr;
        }

        drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(colorBounds));

        offset->fX = bounds.left();
        offset->fY = bounds.top();
        return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()),
                                           kNeedNewImageUniqueID_SpecialImage,
                                           dst);
    }
#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);
}
Esempio n. 7
0
bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
                                           const SkBitmap& src,
                                           const Context& ctx,
                                           SkBitmap* result,
                                           SkIPoint* offset) const {
    SkBitmap background = src;
    SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
    if (this->getInput(0) && 
        !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &background, &backgroundOffset)) {
        return this->onFilterImage(proxy, src, ctx, result, offset);
    }

    GrTexture* backgroundTex = background.getTexture();
    if (NULL == backgroundTex) {
        SkASSERT(false);
        return false;
    }

    SkBitmap foreground = src;
    SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
    if (this->getInput(1) && 
        !this->getInput(1)->getInputResultGPU(proxy, src, ctx, &foreground, &foregroundOffset)) {
        return this->onFilterImage(proxy, src, ctx, result, offset);
    }
    GrTexture* foregroundTex = foreground.getTexture();
    GrContext* context = foregroundTex->getContext();

    GrFragmentProcessor* xferProcessor = NULL;

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = src.width();
    desc.fHeight = src.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    SkAutoTUnref<GrTexture> dst(context->textureProvider()->refScratchTexture(
        desc, GrTextureProvider::kApprox_ScratchTexMatch));
    if (!dst) {
        return false;
    }

    GrPaint paint;
    if (!fMode || !fMode->asFragmentProcessor(&xferProcessor, paint.getProcessorDataManager(),
                                              backgroundTex)) {
        // canFilterImageGPU() should've taken care of this
        SkASSERT(false);
        return false;
    }

    SkMatrix foregroundMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(foregroundTex);
    foregroundMatrix.preTranslate(SkIntToScalar(backgroundOffset.fX-foregroundOffset.fX),
                                  SkIntToScalar(backgroundOffset.fY-foregroundOffset.fY));


    SkRect srcRect;
    src.getBounds(&srcRect);

    SkAutoTUnref<GrFragmentProcessor> foregroundDomain(GrTextureDomainEffect::Create(
        paint.getProcessorDataManager(),
        foregroundTex, foregroundMatrix,
        GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
        GrTextureDomain::kDecal_Mode,
        GrTextureParams::kNone_FilterMode)
    );

    paint.addColorProcessor(foregroundDomain.get());
    paint.addColorProcessor(xferProcessor)->unref();

    GrDrawContext* drawContext = context->drawContext();
    if (!drawContext) {
        return false;
    }

    drawContext->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, 
                          SkMatrix::I(), srcRect);

    offset->fX = backgroundOffset.fX;
    offset->fY = backgroundOffset.fY;
    WrapTexture(dst, src.width(), src.height(), result);
    return true;
}
bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
                                             SkBitmap* result, SkIPoint* offset) const {
    SkBitmap colorBM = src;
    SkIPoint colorOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPU(1, proxy, src, ctx, &colorBM, &colorOffset)) {
        return false;
    }
    SkBitmap displacementBM = src;
    SkIPoint displacementOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPU(0, proxy, src, ctx, &displacementBM, &displacementOffset)) {
        return false;
    }
    SkIRect bounds;
    // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to
    // pad the color bitmap to bounds here.
    if (!this->applyCropRect(ctx, colorBM, colorOffset, &bounds)) {
        return false;
    }
    SkIRect displBounds;
    if (!this->applyCropRect(ctx, proxy, displacementBM,
                             &displacementOffset, &displBounds, &displacementBM)) {
        return false;
    }
    if (!bounds.intersect(displBounds)) {
        return false;
    }
    GrTexture* color = colorBM.getTexture();
    GrTexture* displacement = displacementBM.getTexture();
    GrContext* context = color->getContext();

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = bounds.width();
    desc.fHeight = bounds.height();
    desc.fConfig = kSkia8888_GrPixelConfig;

    auto constraint = GrTextureProvider::FromImageFilter(ctx.sizeConstraint());
    SkAutoTUnref<GrTexture> dst(context->textureProvider()->createTexture(desc, constraint));

    if (!dst) {
        return false;
    }

    SkVector scale = SkVector::Make(fScale, fScale);
    ctx.ctm().mapVectors(&scale, 1);

    GrPaint paint;
    SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
    offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
                              SkIntToScalar(colorOffset.fY - displacementOffset.fY));

    paint.addColorFragmentProcessor(
        GrDisplacementMapEffect::Create(fXChannelSelector,
                                        fYChannelSelector,
                                        scale,
                                        displacement,
                                        offsetMatrix,
                                        color,
                                        colorBM.dimensions()))->unref();
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    SkIRect colorBounds = bounds;
    colorBounds.offset(-colorOffset);
    SkMatrix matrix;
    matrix.setTranslate(-SkIntToScalar(colorBounds.x()),
                        -SkIntToScalar(colorBounds.y()));

    SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
    if (!drawContext) {
        return false;
    }

    drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(colorBounds));
    offset->fX = bounds.left();
    offset->fY = bounds.top();
    WrapTexture(dst, bounds.width(), bounds.height(), result);
    return true;
}
bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
                                           const SkBitmap& src,
                                           const Context& ctx,
                                           SkBitmap* result,
                                           SkIPoint* offset) const {
    SkBitmap background = src;
    SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPU(0, proxy, src, ctx, &background, &backgroundOffset)) {
        return false;
    }

    GrTexture* backgroundTex = background.getTexture();
    if (nullptr == backgroundTex) {
        SkASSERT(false);
        return false;
    }

    SkBitmap foreground = src;
    SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
    if (!this->filterInputGPU(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
        return false;
    }
    GrTexture* foregroundTex = foreground.getTexture();
    GrContext* context = foregroundTex->getContext();
    SkIRect bounds = background.bounds().makeOffset(backgroundOffset.x(), backgroundOffset.y());
    bounds.join(foreground.bounds().makeOffset(foregroundOffset.x(), foregroundOffset.y()));
    if (bounds.isEmpty()) {
        return false;
    }

    const GrFragmentProcessor* xferFP = nullptr;

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = bounds.width();
    desc.fHeight = bounds.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
    if (!dst) {
        return false;
    }

    GrPaint paint;
    SkMatrix backgroundMatrix;
    backgroundMatrix.setIDiv(backgroundTex->width(), backgroundTex->height());
    backgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX),
                                  SkIntToScalar(-backgroundOffset.fY));
    SkAutoTUnref<const GrFragmentProcessor> bgFP(GrTextureDomainEffect::Create(
        backgroundTex, backgroundMatrix,
        GrTextureDomain::MakeTexelDomain(backgroundTex, background.bounds()),
        GrTextureDomain::kDecal_Mode,
        GrTextureParams::kNone_FilterMode)
    );
    if (!fMode || !fMode->asFragmentProcessor(&xferFP, bgFP)) {
        // canFilterImageGPU() should've taken care of this
        SkASSERT(false);
        return false;
    }

    SkMatrix foregroundMatrix;
    foregroundMatrix.setIDiv(foregroundTex->width(), foregroundTex->height());
    foregroundMatrix.preTranslate(SkIntToScalar(-foregroundOffset.fX),
                                  SkIntToScalar(-foregroundOffset.fY));


    SkAutoTUnref<const GrFragmentProcessor> foregroundFP(GrTextureDomainEffect::Create(
        foregroundTex, foregroundMatrix,
        GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
        GrTextureDomain::kDecal_Mode,
        GrTextureParams::kNone_FilterMode)
    );

    paint.addColorFragmentProcessor(foregroundFP.get());
    if (xferFP) {
        paint.addColorFragmentProcessor(xferFP)->unref();
    }
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

    SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
    if (!drawContext) {
        return false;
    }

    SkMatrix matrix;
    matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
    drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(bounds));

    offset->fX = bounds.left();
    offset->fY = bounds.top();
    GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result);
    return true;
}
Esempio n. 10
0
static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset,
                              const CopyParams& copyParams) {
    SkASSERT(!subset || !subset->isEmpty());
    GrContext* context = inputTexture->getContext();
    SkASSERT(context);
    const GrCaps* caps = context->caps();

    // Either it's a cache miss or the original wasn't cached to begin with.
    GrSurfaceDesc rtDesc = inputTexture->desc();
    rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
    rtDesc.fWidth = copyParams.fWidth;
    rtDesc.fHeight = copyParams.fHeight;
    rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);

    // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
    // fail.
    if (!caps->isConfigRenderable(rtDesc.fConfig, false)) {
        if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) {
            if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
                rtDesc.fConfig = kAlpha_8_GrPixelConfig;
            } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
                rtDesc.fConfig = kSkia8888_GrPixelConfig;
            } else {
                return nullptr;
            }
        } else if (kRGB_GrColorComponentFlags ==
                   (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) {
            if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
                rtDesc.fConfig = kSkia8888_GrPixelConfig;
            } else {
                return nullptr;
            }
        } else {
            return nullptr;
        }
    }

    SkAutoTUnref<GrTexture> copy(context->textureProvider()->createTexture(rtDesc,
                                                                           SkBudgeted::kYes));
    if (!copy) {
        return nullptr;
    }

    // TODO: If no scaling is being performed then use copySurface.

    GrPaint paint;
    paint.setGammaCorrect(true);

    // TODO: Initializing these values for no reason cause the compiler is complaining
    SkScalar sx = 0.f;
    SkScalar sy = 0.f;
    if (subset) {
        sx = 1.f / inputTexture->width();
        sy = 1.f / inputTexture->height();
    }

    if (copyParams.fFilter != GrTextureParams::kNone_FilterMode && subset &&
        (subset->width() != copyParams.fWidth || subset->height() != copyParams.fHeight)) {
        SkRect domain;
        domain.fLeft = (subset->fLeft + 0.5f) * sx;
        domain.fTop = (subset->fTop + 0.5f)* sy;
        domain.fRight = (subset->fRight - 0.5f) * sx;
        domain.fBottom = (subset->fBottom - 0.5f) * sy;
        // This would cause us to read values from outside the subset. Surely, the caller knows
        // better!
        SkASSERT(copyParams.fFilter != GrTextureParams::kMipMap_FilterMode);
        paint.addColorFragmentProcessor(
            GrTextureDomainEffect::Make(inputTexture, SkMatrix::I(), domain,
                                        GrTextureDomain::kClamp_Mode,
                                        copyParams.fFilter));
    } else {
        GrTextureParams params(SkShader::kClamp_TileMode, copyParams.fFilter);
        paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
    }
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

    SkRect localRect;
    if (subset) {
        localRect = SkRect::Make(*subset);
        localRect.fLeft *= sx;
        localRect.fTop *= sy;
        localRect.fRight *= sx;
        localRect.fBottom *= sy;
    } else {
        localRect = SkRect::MakeWH(1.f, 1.f);
    }

    sk_sp<GrDrawContext> drawContext(context->drawContext(sk_ref_sp(copy->asRenderTarget())));
    if (!drawContext) {
        return nullptr;
    }

    SkRect dstRect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
    drawContext->fillRectToRect(GrNoClip(), paint, SkMatrix::I(), dstRect, localRect);
    return copy.release();
}
Esempio n. 11
0
// creates a new texture that is the input texture scaled up. If optionalKey is valid it will be
// set on the new texture. stretch controls whether the scaling is done using nearest or bilerp
// filtering and the size to stretch the texture to.
GrTexture* stretch_texture(GrTexture* inputTexture, const SkGrStretch& stretch,
                           SkPixelRef* pixelRef,
                           const GrUniqueKey& optionalKey) {
    SkASSERT(SkGrStretch::kNone_Type != stretch.fType);

    GrContext* context = inputTexture->getContext();
    SkASSERT(context);
    const GrCaps* caps = context->caps();

    // Either it's a cache miss or the original wasn't cached to begin with.
    GrSurfaceDesc rtDesc = inputTexture->desc();
    rtDesc.fFlags =  rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
    rtDesc.fWidth  = stretch.fWidth;
    rtDesc.fHeight = stretch.fHeight;
    rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);

    // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
    // fail.
    if (!caps->isConfigRenderable(rtDesc.fConfig, false)) {
        if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) {
            if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
                rtDesc.fConfig = kAlpha_8_GrPixelConfig;
            } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
                rtDesc.fConfig = kSkia8888_GrPixelConfig;
            } else {
                return nullptr;
            }
        } else if (kRGB_GrColorComponentFlags ==
                   (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) {
            if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
                rtDesc.fConfig = kSkia8888_GrPixelConfig;
            } else {
                return nullptr;
            }
        } else {
            return nullptr;
        }
    }

    SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optionalKey, rtDesc,
                                                               pixelRef, nullptr,0));
    if (!stretched) {
        return nullptr;
    }
    GrPaint paint;

    // If filtering is not desired then we want to ensure all texels in the resampled image are
    // copies of texels from the original.
    GrTextureParams params(SkShader::kClamp_TileMode,
                           SkGrStretch::kBilerp_Type == stretch.fType ?
                              GrTextureParams::kBilerp_FilterMode :
                              GrTextureParams::kNone_FilterMode);
    paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);

    SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
    SkRect localRect = SkRect::MakeWH(1.f, 1.f);

    SkAutoTUnref<GrDrawContext> drawContext(context->drawContext());
    if (!drawContext) {
        return nullptr;
    }

    drawContext->drawNonAARectToRect(stretched->asRenderTarget(), GrClip::WideOpen(), paint,
                                     SkMatrix::I(), rect, localRect);

    return stretched.detach();
}
Esempio n. 12
0
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.reset(background->asTextureRef(context));
    }

    if (foreground) {
        foregroundTex.reset(foreground->asTextureRef(context));
    }

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = bounds.width();
    desc.fHeight = bounds.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
    if (!dst) {
        return nullptr;
    }

    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));
        }

        SkAutoTUnref<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);
        }
    } else {
        paint.addColorFragmentProcessor(bgFP);
    }

    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

    SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
    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,
                                       dst.get());
}
Esempio n. 13
0
static sk_sp<SkSpecialImage> apply_morphology(SkSpecialImage* input,
                                              const SkIRect& rect,
                                              GrMorphologyEffect::MorphologyType morphType,
                                              SkISize radius) {
    SkAutoTUnref<GrTexture> srcTexture(SkRef(input->peekTexture()));
    SkASSERT(srcTexture);
    GrContext* context = srcTexture->getContext();

    // setup new clip
    GrClip clip(SkRect::MakeWH(SkIntToScalar(srcTexture->width()),
                               SkIntToScalar(srcTexture->height())));

    SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = rect.width();
    desc.fHeight = rect.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    SkIRect srcRect = rect;

    SkASSERT(radius.width() > 0 || radius.height() > 0);

    if (radius.fWidth > 0) {
        GrTexture* scratch = context->textureProvider()->createApproxTexture(desc);
        if (!scratch) {
            return nullptr;
        }
        SkAutoTUnref<GrDrawContext> dstDrawContext(
                                                context->drawContext(scratch->asRenderTarget()));
        if (!dstDrawContext) {
            return nullptr;
        }

        apply_morphology_pass(dstDrawContext, clip, srcTexture,
                              srcRect, dstRect, radius.fWidth, morphType,
                              Gr1DKernelEffect::kX_Direction);
        SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
                                              dstRect.width(), radius.fHeight);
        GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphType ?
                                SK_ColorWHITE :
                                SK_ColorTRANSPARENT;
        dstDrawContext->clear(&clearRect, clearColor, false);

        srcTexture.reset(scratch);
        srcRect = dstRect;
    }
    if (radius.fHeight > 0) {
        GrTexture* scratch = context->textureProvider()->createApproxTexture(desc);
        if (!scratch) {
            return nullptr;
        }
        SkAutoTUnref<GrDrawContext> dstDrawContext(
                                                context->drawContext(scratch->asRenderTarget()));
        if (!dstDrawContext) {
            return nullptr;
        }

        apply_morphology_pass(dstDrawContext, clip, srcTexture,
                              srcRect, dstRect, radius.fHeight, morphType,
                              Gr1DKernelEffect::kY_Direction);

        srcTexture.reset(scratch);
    }

    return SkSpecialImage::MakeFromGpu(input->internal_getProxy(),
                                       SkIRect::MakeWH(rect.width(), rect.height()),
                                       kNeedNewImageUniqueID_SpecialImage,
                                       srcTexture);
}