コード例 #1
0
ファイル: GrTextureToYUVPlanes.cpp プロジェクト: OwenTan/skia
static bool convert_texture(GrTexture* src, GrDrawContext* dst, int dstW, int dstH,
                            SkYUVColorSpace colorSpace, MakeFPProc proc) {

    SkScalar xScale = SkIntToScalar(src->width()) / dstW / src->width();
    SkScalar yScale = SkIntToScalar(src->height()) / dstH / src->height();
    GrTextureParams::FilterMode filter;
    if (dstW == src->width() && dstW == src->height()) {
        filter = GrTextureParams::kNone_FilterMode;
    } else {
        filter = GrTextureParams::kBilerp_FilterMode;
    }

    sk_sp<GrFragmentProcessor> fp(
            GrSimpleTextureEffect::Make(src, SkMatrix::MakeScale(xScale, yScale), filter));
    if (!fp) {
        return false;
    }
    fp = proc(std::move(fp), colorSpace);
    if (!fp) {
        return false;
    }
    GrPaint paint;
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    paint.addColorFragmentProcessor(std::move(fp));
    dst->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::MakeIWH(dstW, dstH));
    return true;
}
コード例 #2
0
sk_sp<SkImage> SkImage_Gpu::onMakeColorSpace(sk_sp<SkColorSpace> colorSpace) const {
    sk_sp<SkColorSpace> srcSpace = fColorSpace ? fColorSpace : SkColorSpace::MakeSRGB();
    auto xform = GrNonlinearColorSpaceXformEffect::Make(srcSpace.get(), colorSpace.get());
    if (!xform) {
        return sk_ref_sp(const_cast<SkImage_Gpu*>(this));
    }

    sk_sp<GrRenderTargetContext> renderTargetContext(fContext->makeRenderTargetContext(
        SkBackingFit::kExact, this->width(), this->height(), kRGBA_8888_GrPixelConfig, nullptr));
    if (!renderTargetContext) {
        return nullptr;
    }

    GrPaint paint;
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    paint.addColorTextureProcessor(fContext->resourceProvider(), fProxy, nullptr, SkMatrix::I());
    paint.addColorFragmentProcessor(std::move(xform));

    const SkRect rect = SkRect::MakeIWH(this->width(), this->height());

    renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect);

    if (!renderTargetContext->asTextureProxy()) {
        return nullptr;
    }

    // MDB: this call is okay bc we know 'renderTargetContext' was exact
    return sk_make_sp<SkImage_Gpu>(fContext, kNeedNewImageUniqueID,
                                   fAlphaType, renderTargetContext->asTextureProxyRef(),
                                   std::move(colorSpace), fBudgeted);

}
コード例 #3
0
static void test_path(GrContext* ctx,
                      GrRenderTargetContext* renderTargetContext,
                      const SkPath& path,
                      const SkMatrix& matrix = SkMatrix::I(),
                      GrAAType aaType = GrAAType::kNone,
                      std::unique_ptr<GrFragmentProcessor> fp = nullptr) {
    GrTessellatingPathRenderer tess;

    GrPaint paint;
    paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
    if (fp) {
        paint.addColorFragmentProcessor(std::move(fp));
    }

    GrNoClip noClip;
    SkIRect clipConservativeBounds = SkIRect::MakeWH(renderTargetContext->width(),
                                                     renderTargetContext->height());
    GrStyle style(SkStrokeRec::kFill_InitStyle);
    GrShape shape(path, style);
    GrPathRenderer::DrawPathArgs args{ctx,
                                      std::move(paint),
                                      &GrUserStencilSettings::kUnused,
                                      renderTargetContext,
                                      &noClip,
                                      &clipConservativeBounds,
                                      &matrix,
                                      &shape,
                                      aaType,
                                      false};
    tess.drawPath(args);
}
コード例 #4
0
static void convolve_gaussian_2d(GrDrawContext* drawContext,
                                 const GrClip& clip,
                                 const SkIRect& dstRect,
                                 const SkIPoint& srcOffset,
                                 GrTexture* texture,
                                 int radiusX,
                                 int radiusY,
                                 SkScalar sigmaX,
                                 SkScalar sigmaY,
                                 const SkIRect* srcBounds) {
    SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()),
                                               -SkIntToScalar(srcOffset.y()));
    SkISize size = SkISize::Make(2 * radiusX + 1,  2 * radiusY + 1);
    SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY);
    GrPaint paint;
    paint.setGammaCorrect(drawContext->isGammaCorrect());
    SkIRect bounds = srcBounds ? *srcBounds : SkIRect::EmptyIRect();

    sk_sp<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::MakeGaussian(
            texture, bounds, size, 1.0, 0.0, kernelOffset,
            srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_Mode,
            true, sigmaX, sigmaY));
    paint.addColorFragmentProcessor(std::move(conv));
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), 
                                         SkRect::Make(dstRect), localMatrix);
}
コード例 #5
0
ファイル: SkImageFilter.cpp プロジェクト: 03050903/skia
sk_sp<SkSpecialImage> SkImageFilter::DrawWithFP(GrContext* context,
                                                sk_sp<GrFragmentProcessor> fp,
                                                const SkIRect& bounds,
                                                sk_sp<SkColorSpace> colorSpace) {
    GrPaint paint;
    paint.addColorFragmentProcessor(std::move(fp));
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

    sk_sp<GrDrawContext> drawContext(context->makeDrawContext(SkBackingFit::kApprox,
                                                              bounds.width(), bounds.height(),
                                                              kRGBA_8888_GrPixelConfig,
                                                              std::move(colorSpace)));
    if (!drawContext) {
        return nullptr;
    }

    SkIRect dstIRect = SkIRect::MakeWH(bounds.width(), bounds.height());
    SkRect srcRect = SkRect::Make(bounds);
    SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
    GrFixedClip clip(dstIRect);
    drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);

    return SkSpecialImage::MakeFromGpu(dstIRect, kNeedNewImageUniqueID_SpecialImage,
                                       drawContext->asTexture(),
                                       sk_ref_sp(drawContext->getColorSpace()));
}
コード例 #6
0
ファイル: SkGpuBlurUtils.cpp プロジェクト: keinvo/skia
static void convolve_gaussian_2d(GrDrawContext* drawContext,
                                 const GrClip& clip,
                                 const SkRect& dstRect,
                                 const SkPoint& srcOffset,
                                 GrTexture* texture,
                                 int radiusX,
                                 int radiusY,
                                 SkScalar sigmaX,
                                 SkScalar sigmaY,
                                 const SkRect* srcBounds) {
    SkMatrix localMatrix = SkMatrix::MakeTrans(-srcOffset.x(), -srcOffset.y());
    SkISize size = SkISize::Make(2 * radiusX + 1,  2 * radiusY + 1);
    SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY);
    GrPaint paint;
    SkIRect bounds;
    if (srcBounds) {
        srcBounds->roundOut(&bounds);
    } else {
        bounds.setEmpty();
    }

    SkAutoTUnref<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::CreateGaussian(
            texture, bounds, size, 1.0, 0.0, kernelOffset,
            srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_Mode,
            true, sigmaX, sigmaY));
    paint.addColorFragmentProcessor(conv);
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix);
}
コード例 #7
0
ファイル: SkImageFilter.cpp プロジェクト: jiangzhonghui/skia
sk_sp<SkSpecialImage> SkImageFilter::DrawWithFP(GrContext* context,
                                                sk_sp<GrFragmentProcessor> fp,
                                                const SkIRect& bounds) {
    GrPaint paint;
    paint.addColorFragmentProcessor(fp.get());
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

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

    sk_sp<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
    if (!dst) {
        return nullptr;
    }

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

    SkRect srcRect = SkRect::Make(bounds);
    SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
    GrClip clip(dstRect);
    drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);

    return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()),
                                       kNeedNewImageUniqueID_SpecialImage,
                                       std::move(dst));
}
コード例 #8
0
ファイル: GrYUVProvider.cpp プロジェクト: Just-D/skia
GrTexture* GrYUVProvider::refAsTexture(GrContext* ctx, const GrSurfaceDesc& desc, bool useCache) {
    SkYUVPlanesCache::Info yuvInfo;
    void* planes[3];
    YUVScoper scoper;
    if (!scoper.init(this, &yuvInfo, planes, useCache)) {
        return nullptr;
    }

    GrSurfaceDesc yuvDesc;
    yuvDesc.fConfig = kAlpha_8_GrPixelConfig;
    SkAutoTUnref<GrTexture> yuvTextures[3];
    for (int i = 0; i < 3; ++i) {
        yuvDesc.fWidth  = yuvInfo.fSize[i].fWidth;
        yuvDesc.fHeight = yuvInfo.fSize[i].fHeight;
        // TODO: why do we need this check?
        bool needsExactTexture = (yuvDesc.fWidth  != yuvInfo.fSize[0].fWidth) ||
                                 (yuvDesc.fHeight != yuvInfo.fSize[0].fHeight);
        if (needsExactTexture) {
            yuvTextures[i].reset(ctx->textureProvider()->createTexture(yuvDesc, true));
        } else {
            yuvTextures[i].reset(ctx->textureProvider()->createApproxTexture(yuvDesc));
        }
        if (!yuvTextures[i] ||
            !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight,
                                         yuvDesc.fConfig, planes[i], yuvInfo.fRowBytes[i])) {
                return nullptr;
            }
    }

    GrSurfaceDesc rtDesc = desc;
    rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;

    SkAutoTUnref<GrTexture> result(ctx->textureProvider()->createTexture(rtDesc, true, nullptr, 0));
    if (!result) {
        return nullptr;
    }

    GrRenderTarget* renderTarget = result->asRenderTarget();
    SkASSERT(renderTarget);

    GrPaint paint;
    SkAutoTUnref<GrFragmentProcessor> yuvToRgbProcessor(
                                        GrYUVtoRGBEffect::Create(yuvTextures[0],
                                                                 yuvTextures[1],
                                                                 yuvTextures[2],
                                                                 yuvInfo.fSize,
                                                                 yuvInfo.fColorSpace));
    paint.addColorFragmentProcessor(yuvToRgbProcessor);
    const SkRect r = SkRect::MakeIWH(yuvInfo.fSize[0].fWidth, yuvInfo.fSize[0].fHeight);

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

    drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, SkMatrix::I(), r);

    return result.detach();
}
コード例 #9
0
ファイル: yuvtorgbeffect.cpp プロジェクト: molikto/Skia
    void onDraw(SkCanvas* canvas) override {
        GrRenderTargetContext* renderTargetContext =
            canvas->internal_private_accessTopLayerRenderTargetContext();
        if (!renderTargetContext) {
            skiagm::GM::DrawGpuOnlyMessage(canvas);
            return;
        }

        GrContext* context = canvas->getGrContext();
        if (!context) {
            return;
        }

        GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
        sk_sp<GrTextureProxy> proxy[3];

        for (int i = 0; i < 3; ++i) {
            int index = (0 == i) ? 0 : 1;
            GrSurfaceDesc desc;
            desc.fWidth = fBmp[index].width();
            desc.fHeight = fBmp[index].height();
            desc.fConfig = SkImageInfo2GrPixelConfig(fBmp[index].info(), *context->caps());
            SkASSERT(kUnknown_GrPixelConfig != desc.fConfig);

            proxy[i] = proxyProvider->createTextureProxy(
                    desc, SkBudgeted::kYes, fBmp[index].getPixels(), fBmp[index].rowBytes());
            if (!proxy[i]) {
                return;
            }
        }

        constexpr SkScalar kDrawPad = 10.f;
        constexpr SkScalar kTestPad = 10.f;
        constexpr SkScalar kColorSpaceOffset = 36.f;
        SkISize sizes[3] = {{YSIZE, YSIZE}, {USIZE, USIZE}, {VSIZE, VSIZE}};

        for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
            SkRect renderRect =
                SkRect::MakeWH(SkIntToScalar(fBmp[0].width()), SkIntToScalar(fBmp[0].height()));
            renderRect.outset(kDrawPad, kDrawPad);

            SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
            SkScalar x = kDrawPad + kTestPad;

            GrPaint grPaint;
            grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
            auto fp = GrYUVtoRGBEffect::Make(proxy[0], proxy[1], proxy[2], sizes,
                                             static_cast<SkYUVColorSpace>(space), true);
            if (fp) {
                SkMatrix viewMatrix;
                viewMatrix.setTranslate(x, y);
                grPaint.addColorFragmentProcessor(std::move(fp));
                std::unique_ptr<GrDrawOp> op(GrRectOpFactory::MakeNonAAFill(
                                std::move(grPaint), viewMatrix, renderRect, GrAAType::kNone));
                renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
            }
        }
    }
コード例 #10
0
ファイル: SkImageFilter.cpp プロジェクト: keinvo/skia
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;
}
コード例 #11
0
sk_sp<GrTextureProxy> GrTextureProducer::CopyOnGpu(GrContext* context,
                                                   sk_sp<GrTextureProxy> inputProxy,
                                                   const CopyParams& copyParams,
                                                   bool dstWillRequireMipMaps) {
    SkASSERT(context);

    const SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight);
    GrMipMapped mipMapped = dstWillRequireMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;

    SkRect localRect = SkRect::MakeWH(inputProxy->width(), inputProxy->height());

    bool needsDomain = false;
    bool resizing = false;
    if (copyParams.fFilter != GrSamplerState::Filter::kNearest) {
        bool resizing = localRect.width()  != dstRect.width() ||
                        localRect.height() != dstRect.height();
        needsDomain = resizing && !GrProxyProvider::IsFunctionallyExact(inputProxy.get());
    }

    if (copyParams.fFilter == GrSamplerState::Filter::kNearest && !needsDomain && !resizing &&
        dstWillRequireMipMaps) {
        sk_sp<GrTextureProxy> proxy = GrCopyBaseMipMapToTextureProxy(context, inputProxy.get());
        if (proxy) {
            return proxy;
        }
    }

    sk_sp<GrRenderTargetContext> copyRTC =
        context->contextPriv().makeDeferredRenderTargetContextWithFallback(
            SkBackingFit::kExact, dstRect.width(), dstRect.height(), inputProxy->config(),
            nullptr, 1, mipMapped, inputProxy->origin());
    if (!copyRTC) {
        return nullptr;
    }

    GrPaint paint;

    if (needsDomain) {
        const SkRect domain = localRect.makeInset(0.5f, 0.5f);
        // This would cause us to read values from outside the subset. Surely, the caller knows
        // better!
        SkASSERT(copyParams.fFilter != GrSamplerState::Filter::kMipMap);
        paint.addColorFragmentProcessor(
            GrTextureDomainEffect::Make(std::move(inputProxy), SkMatrix::I(), domain,
                                        GrTextureDomain::kClamp_Mode, copyParams.fFilter));
    } else {
        GrSamplerState samplerState(GrSamplerState::WrapMode::kClamp, copyParams.fFilter);
        paint.addColorTextureProcessor(std::move(inputProxy), SkMatrix::I(), samplerState);
    }
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);

    copyRTC->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
                            localRect);
    return copyRTC->asTextureProxyRef();
}
コード例 #12
0
static void apply_morphology_rect_no_bounds(GrRenderTargetContext* renderTargetContext,
                                            const GrClip& clip,
                                            sk_sp<GrTextureProxy> proxy,
                                            const SkIRect& srcRect,
                                            const SkIRect& dstRect,
                                            int radius,
                                            GrMorphologyEffect::Type morphType,
                                            GrMorphologyEffect::Direction direction) {
    GrPaint paint;
    paint.addColorFragmentProcessor(GrMorphologyEffect::Make(std::move(proxy),
                                                             direction, radius, morphType));
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
                                        SkRect::Make(dstRect), SkRect::Make(srcRect));
}
コード例 #13
0
static void apply_morphology_rect_no_bounds(GrDrawContext* drawContext,
                                            const GrClip& clip,
                                            GrTexture* texture,
                                            const SkIRect& srcRect,
                                            const SkIRect& dstRect,
                                            int radius,
                                            GrMorphologyEffect::MorphologyType morphType,
                                            Gr1DKernelEffect::Direction direction) {
    GrPaint paint;
    paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture,
                                                               direction,
                                                               radius,
                                                               morphType))->unref();
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect),
                                SkRect::Make(srcRect));
}
コード例 #14
0
ファイル: SkGpuBlurUtils.cpp プロジェクト: keinvo/skia
static void convolve_gaussian_1d(GrDrawContext* drawContext,
                                 const GrClip& clip,
                                 const SkRect& dstRect,
                                 const SkPoint& srcOffset,
                                 GrTexture* texture,
                                 Gr1DKernelEffect::Direction direction,
                                 int radius,
                                 float sigma,
                                 bool useBounds,
                                 float bounds[2]) {
    GrPaint paint;
    SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian(
        texture, direction, radius, sigma, useBounds, bounds));
    paint.addColorFragmentProcessor(conv);
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    SkMatrix localMatrix = SkMatrix::MakeTrans(-srcOffset.x(), -srcOffset.y());
    drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, localMatrix);
}
コード例 #15
0
// skbug.com/5932
static void test_basic_draw_as_src(skiatest::Reporter* reporter, GrContext* context,
                                   sk_sp<GrTextureProxy> rectProxy, uint32_t expectedPixelValues[]) {
    sk_sp<GrRenderTargetContext> rtContext(context->contextPriv().makeDeferredRenderTargetContext(
                                                     SkBackingFit::kExact, rectProxy->width(),
                                                     rectProxy->height(), rectProxy->config(),
                                                     nullptr));
    for (auto filter : {GrSamplerState::Filter::kNearest,
                        GrSamplerState::Filter::kBilerp,
                        GrSamplerState::Filter::kMipMap}) {
        rtContext->clear(nullptr, 0xDDCCBBAA, GrRenderTargetContext::CanClearFullscreen::kYes);
        auto fp = GrSimpleTextureEffect::Make(rectProxy, SkMatrix::I(), filter);
        GrPaint paint;
        paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
        paint.addColorFragmentProcessor(std::move(fp));
        rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
        test_read_pixels(reporter, rtContext.get(), expectedPixelValues,
                         "RectangleTexture-basic-draw");
    }
}
コード例 #16
0
static void convolve_gaussian_1d(GrDrawContext* drawContext,
                                 const GrClip& clip,
                                 const SkIRect& dstRect,
                                 const SkIPoint& srcOffset,
                                 GrTexture* texture,
                                 Gr1DKernelEffect::Direction direction,
                                 int radius,
                                 float sigma,
                                 bool useBounds,
                                 float bounds[2]) {
    GrPaint paint;
    paint.setGammaCorrect(drawContext->isGammaCorrect());
    sk_sp<GrFragmentProcessor> conv(GrConvolutionEffect::MakeGaussian(
        texture, direction, radius, sigma, useBounds, bounds));
    paint.addColorFragmentProcessor(std::move(conv));
    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()),
                                               -SkIntToScalar(srcOffset.y()));
    drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(),
                                         SkRect::Make(dstRect), localMatrix);
}
コード例 #17
0
ファイル: SkImageFilter.cpp プロジェクト: JavierJF/skia
sk_sp<SkSpecialImage> SkImageFilter::DrawWithFP(GrContext* context,
                                                sk_sp<GrFragmentProcessor> fp,
                                                const SkIRect& bounds) {
    GrPaint paint;
    paint.addColorFragmentProcessor(fp.get());
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

    sk_sp<GrDrawContext> drawContext(context->newDrawContext(GrContext::kLoose_BackingFit,
                                                             bounds.width(), bounds.height(),
                                                             kRGBA_8888_GrPixelConfig));
    if (!drawContext) {
        return nullptr;
    }

    SkRect srcRect = SkRect::Make(bounds);
    SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
    GrClip clip(dstRect);
    drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);

    return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()),
                                       kNeedNewImageUniqueID_SpecialImage,
                                       drawContext->asTexture());
}
コード例 #18
0
ファイル: GLProgramsTest.cpp プロジェクト: molikto/Skia
bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages, int maxLevels) {
    GrDrawingManager* drawingManager = context->contextPriv().drawingManager();
    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();

    sk_sp<GrTextureProxy> proxies[2];

    // setup dummy textures
    {
        GrSurfaceDesc dummyDesc;
        dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
        dummyDesc.fWidth = 34;
        dummyDesc.fHeight = 18;
        dummyDesc.fConfig = kRGBA_8888_GrPixelConfig;
        proxies[0] = proxyProvider->createProxy(dummyDesc, kBottomLeft_GrSurfaceOrigin,
                                                SkBackingFit::kExact, SkBudgeted::kNo);
    }
    {
        GrSurfaceDesc dummyDesc;
        dummyDesc.fFlags = kNone_GrSurfaceFlags;
        dummyDesc.fWidth = 16;
        dummyDesc.fHeight = 22;
        dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
        proxies[1] = proxyProvider->createProxy(dummyDesc, kTopLeft_GrSurfaceOrigin,
                                                SkBackingFit::kExact, SkBudgeted::kNo);
    }

    if (!proxies[0] || !proxies[1]) {
        SkDebugf("Could not allocate dummy textures");
        return false;
    }

    // dummy scissor state
    GrScissorState scissor;

    SkRandom random;
    static const int NUM_TESTS = 1024;
    for (int t = 0; t < NUM_TESTS; t++) {
        // setup random render target(can fail)
        sk_sp<GrRenderTargetContext> renderTargetContext(random_render_target_context(
            context, &random, context->caps()));
        if (!renderTargetContext) {
            SkDebugf("Could not allocate renderTargetContext");
            return false;
        }

        GrPaint paint;
        GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies);
        set_random_color_coverage_stages(&paint, &ptd, maxStages, maxLevels);
        set_random_xpf(&paint, &ptd);
        set_random_state(&paint, &random);
        GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint));
    }
    // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
    drawingManager->flush(nullptr);

    // Validate that GrFPs work correctly without an input.
    sk_sp<GrRenderTargetContext> renderTargetContext(
                 context->contextPriv().makeDeferredRenderTargetContext(SkBackingFit::kExact,
                                                                        kRenderTargetWidth,
                                                                        kRenderTargetHeight,
                                                                        kRGBA_8888_GrPixelConfig,
                                                                        nullptr));
    if (!renderTargetContext) {
        SkDebugf("Could not allocate a renderTargetContext");
        return false;
    }

    int fpFactoryCnt = GrFragmentProcessorTestFactory::Count();
    for (int i = 0; i < fpFactoryCnt; ++i) {
        // Since FP factories internally randomize, call each 10 times.
        for (int j = 0; j < 10; ++j) {
            GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies);

            GrPaint paint;
            paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
            auto fp = GrFragmentProcessorTestFactory::MakeIdx(i, &ptd);
            auto blockFP = BlockInputFragmentProcessor::Make(std::move(fp));
            paint.addColorFragmentProcessor(std::move(blockFP));
            GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint));
            drawingManager->flush(nullptr);
        }
    }

    return true;
}
コード例 #19
0
ファイル: GrYUVProvider.cpp プロジェクト: ROM-PacMe/skia
sk_sp<GrTexture> GrYUVProvider::refAsTexture(GrContext* ctx,
        const GrSurfaceDesc& desc,
        bool useCache) {
    SkYUVPlanesCache::Info yuvInfo;
    void* planes[3];
    YUVScoper scoper;
    if (!scoper.init(this, &yuvInfo, planes, useCache)) {
        return nullptr;
    }

    GrSurfaceDesc yuvDesc;
    yuvDesc.fConfig = kAlpha_8_GrPixelConfig;
    SkAutoTUnref<GrTexture> yuvTextures[3];
    for (int i = 0; i < 3; i++) {
        yuvDesc.fWidth  = yuvInfo.fSizeInfo.fSizes[i].fWidth;
        yuvDesc.fHeight = yuvInfo.fSizeInfo.fSizes[i].fHeight;
        // TODO: why do we need this check?
        bool needsExactTexture =
            (yuvDesc.fWidth  != yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth) ||
            (yuvDesc.fHeight != yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
        if (needsExactTexture) {
            yuvTextures[i].reset(ctx->textureProvider()->createTexture(yuvDesc, SkBudgeted::kYes));
        } else {
            yuvTextures[i].reset(ctx->textureProvider()->createApproxTexture(yuvDesc));
        }
        if (!yuvTextures[i] ||
                !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight, yuvDesc.fConfig,
                                             planes[i], yuvInfo.fSizeInfo.fWidthBytes[i])) {
            return nullptr;
        }
    }

    sk_sp<GrDrawContext> drawContext(ctx->newDrawContext(SkBackingFit::kExact,
                                     desc.fWidth, desc.fHeight,
                                     desc.fConfig, desc.fSampleCnt));
    if (!drawContext) {
        return nullptr;
    }

    GrPaint paint;
    sk_sp<GrFragmentProcessor> yuvToRgbProcessor(
        GrYUVEffect::MakeYUVToRGB(yuvTextures[0], yuvTextures[1], yuvTextures[2],
                                  yuvInfo.fSizeInfo.fSizes, yuvInfo.fColorSpace, false));
    paint.addColorFragmentProcessor(std::move(yuvToRgbProcessor));

    // If we're decoding an sRGB image, the result of our linear math on the YUV planes is already
    // in sRGB. (The encoding is just math on bytes, with no concept of color spaces.) So, we need
    // to output the results of that math directly to the buffer that we will then consider sRGB.
    // If we have sRGB write control, we can just tell the HW not to do the Linear -> sRGB step.
    // Otherwise, we do our shader math to go from YUV -> sRGB, manually convert sRGB -> Linear,
    // then let the HW convert Linear -> sRGB.
    if (GrPixelConfigIsSRGB(desc.fConfig)) {
        if (ctx->caps()->srgbWriteControl()) {
            paint.setDisableOutputConversionToSRGB(true);
        } else {
            paint.addColorFragmentProcessor(GrGammaEffect::Make(2.2f));
        }
    }

    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    const SkRect r = SkRect::MakeIWH(yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
                                     yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);

    drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), r);

    return drawContext->asTexture();
}
コード例 #20
0
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;
}
コード例 #21
0
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);
}
コード例 #22
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 = background->asTextureRef(context);
    }

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

    GrPaint paint;
    // SRGBTODO: AllowSRGBInputs?
    sk_sp<GrFragmentProcessor> bgFP;

    if (backgroundTex) {
        SkMatrix backgroundMatrix;
        backgroundMatrix.setIDiv(backgroundTex->width(), backgroundTex->height());
        backgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX),
                                      SkIntToScalar(-backgroundOffset.fY));
        bgFP = GrTextureDomainEffect::Make(
                            backgroundTex.get(), nullptr, backgroundMatrix,
                            GrTextureDomain::MakeTexelDomain(backgroundTex.get(),
                                                             background->subset()),
                            GrTextureDomain::kDecal_Mode,
                            GrTextureParams::kNone_FilterMode);
    } else {
        bgFP = GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK,
                                             GrConstColorProcessor::kIgnore_InputMode);
    }

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

        sk_sp<GrFragmentProcessor> foregroundFP;

        foregroundFP = GrTextureDomainEffect::Make(
                            foregroundTex.get(), nullptr, foregroundMatrix,
                            GrTextureDomain::MakeTexelDomain(foregroundTex.get(), 
                                                             foreground->subset()),
                            GrTextureDomain::kDecal_Mode,
                            GrTextureParams::kNone_FilterMode);

        paint.addColorFragmentProcessor(std::move(foregroundFP));

        // A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
        SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get()));
        if (!mode) {
            // It would be awesome to use SkXfermode::Create here but it knows better
            // than us and won't return a kSrcOver_Mode SkXfermode. That means we
            // have to get one the hard way.
            struct ProcCoeff rec;
            rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
            SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);

            mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
        }

        sk_sp<GrFragmentProcessor> xferFP(
            mode->makeFragmentProcessorForImageFilter(std::move(bgFP)));

        // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
        if (xferFP) {
            paint.addColorFragmentProcessor(std::move(xferFP));
        }
    } else {
        paint.addColorFragmentProcessor(std::move(bgFP));
    }

    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

    sk_sp<GrDrawContext> drawContext(context->makeDrawContext(SkBackingFit::kApprox,
                                                              bounds.width(), bounds.height(),
                                                              kSkia8888_GrPixelConfig,
                                                              sk_ref_sp(source->getColorSpace())));
    if (!drawContext) {
        return nullptr;
    }

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

    return SkSpecialImage::MakeFromGpu(SkIRect::MakeWH(bounds.width(), bounds.height()),
                                       kNeedNewImageUniqueID_SpecialImage,
                                       drawContext->asTexture(),
                                       sk_ref_sp(drawContext->getColorSpace()));
}
コード例 #23
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->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;
}
コード例 #24
0
ファイル: SkImage_Gpu.cpp プロジェクト: aseprite/skia
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<GrTexture> yTex(
        ctx->textureProvider()->wrapBackendTexture(yDesc, kBorrow_GrWrapOwnership));
    sk_sp<GrTexture> uTex(
        ctx->textureProvider()->wrapBackendTexture(uDesc, kBorrow_GrWrapOwnership));
    sk_sp<GrTexture> vTex;
    if (nv12) {
        vTex = uTex;
    } 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;

        vTex = sk_sp<GrTexture>(
            ctx->textureProvider()->wrapBackendTexture(vDesc, kBorrow_GrWrapOwnership));
    }
    if (!yTex || !uTex || !vTex) {
        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(yTex.get(), uTex.get(), vTex.get(), yuvSizes, colorSpace, nv12));

    const SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));

    renderTargetContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect);
    ctx->flushSurfaceWrites(renderTargetContext->accessRenderTarget());
    return sk_make_sp<SkImage_Gpu>(width, height, kNeedNewImageUniqueID,
                                   kOpaque_SkAlphaType, renderTargetContext->asTexture(),
                                   sk_ref_sp(renderTargetContext->getColorSpace()), budgeted);
}
コード例 #25
0
ファイル: SkImage_Gpu.cpp プロジェクト: shahrzadmn/skia
SkImage* SkImage::NewFromYUVTexturesCopy(GrContext* ctx , SkYUVColorSpace colorSpace,
                                         const GrBackendObject yuvTextureHandles[3],
                                         const SkISize yuvSizes[3],
                                         GrSurfaceOrigin origin) {
    const SkSurface::Budgeted budgeted = SkSurface::kYes_Budgeted;

    if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 ||
        yuvSizes[1].fWidth <= 0 || yuvSizes[1].fHeight <= 0 ||
        yuvSizes[2].fWidth <= 0 || yuvSizes[2].fHeight <= 0) {
        return nullptr;
    }
    static const GrPixelConfig kConfig = 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;

    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;

    SkAutoTUnref<GrTexture> yTex(ctx->textureProvider()->wrapBackendTexture(
        yDesc, kBorrow_GrWrapOwnership));
    SkAutoTUnref<GrTexture> uTex(ctx->textureProvider()->wrapBackendTexture(
        uDesc, kBorrow_GrWrapOwnership));
    SkAutoTUnref<GrTexture> vTex(ctx->textureProvider()->wrapBackendTexture(
        vDesc, kBorrow_GrWrapOwnership));
    if (!yTex || !uTex || !vTex) {
        return nullptr;
    }

    GrSurfaceDesc dstDesc;
    // Needs to be a render target in order to draw to it for the yuv->rgb conversion.
    dstDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    dstDesc.fOrigin = origin;
    dstDesc.fWidth = yuvSizes[0].fWidth;
    dstDesc.fHeight = yuvSizes[0].fHeight;
    dstDesc.fConfig = kRGBA_8888_GrPixelConfig;
    dstDesc.fSampleCnt = 0;

    SkAutoTUnref<GrTexture> dst(ctx->textureProvider()->createTexture(dstDesc, true));
    if (!dst) {
        return nullptr;
    }

    GrPaint paint;
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    paint.addColorFragmentProcessor(GrYUVtoRGBEffect::Create(paint.getProcessorDataManager(),
                                                             yTex, uTex, vTex, yuvSizes,
                                                             colorSpace))->unref();

    const SkRect rect = SkRect::MakeWH(SkIntToScalar(dstDesc.fWidth),
                                       SkIntToScalar(dstDesc.fHeight));
    SkAutoTUnref<GrDrawContext> drawContext(ctx->drawContext());
    if (!drawContext) {
        return nullptr;
    }

    drawContext->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, SkMatrix::I(), rect);
    ctx->flushSurfaceWrites(dst);
    return new SkImage_Gpu(dstDesc.fWidth, dstDesc.fHeight, kNeedNewImageUniqueID,
                           kOpaque_SkAlphaType, dst, budgeted);
}
コード例 #26
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;
}
コード例 #27
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();
}
コード例 #28
0
ファイル: GLProgramsTest.cpp プロジェクト: OwenTan/skia
bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages) {
    GrDrawingManager* drawingManager = context->drawingManager();

    // setup dummy textures
    GrSurfaceDesc dummyDesc;
    dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    dummyDesc.fConfig = kSkia8888_GrPixelConfig;
    dummyDesc.fWidth = 34;
    dummyDesc.fHeight = 18;
    SkAutoTUnref<GrTexture> dummyTexture1(
        context->textureProvider()->createTexture(dummyDesc, SkBudgeted::kNo, nullptr, 0));
    dummyDesc.fFlags = kNone_GrSurfaceFlags;
    dummyDesc.fConfig = kAlpha_8_GrPixelConfig;
    dummyDesc.fWidth = 16;
    dummyDesc.fHeight = 22;
    SkAutoTUnref<GrTexture> dummyTexture2(
        context->textureProvider()->createTexture(dummyDesc, SkBudgeted::kNo, nullptr, 0));

    if (!dummyTexture1 || ! dummyTexture2) {
        SkDebugf("Could not allocate dummy textures");
        return false;
    }

    GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};

    // dummy scissor state
    GrScissorState scissor;

    SkRandom random;
    static const int NUM_TESTS = 1024;
    for (int t = 0; t < NUM_TESTS; t++) {
        // setup random render target(can fail)
        sk_sp<GrDrawContext> drawContext(random_draw_context(context, &random, context->caps()));
        if (!drawContext) {
            SkDebugf("Could not allocate drawContext");
            return false;
        }

        GrPaint grPaint;

        SkAutoTUnref<GrDrawBatch> batch(GrRandomDrawBatch(&random, context));
        SkASSERT(batch);

        GrProcessorTestData ptd(&random, context, context->caps(),
                                drawContext.get(), dummyTextures);
        set_random_color_coverage_stages(&grPaint, &ptd, maxStages);
        set_random_xpf(&grPaint, &ptd);
        bool snapToCenters = set_random_state(&grPaint, &random);
        const GrUserStencilSettings* uss = get_random_stencil(&random);

        drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch, uss, snapToCenters);
    }
    // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
    drawingManager->flush();

    // Validate that GrFPs work correctly without an input.
    sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kExact,
                                                             kRenderTargetWidth,
                                                             kRenderTargetHeight,
                                                             kRGBA_8888_GrPixelConfig));
    if (!drawContext) {
        SkDebugf("Could not allocate a drawContext");
        return false;
    }

    int fpFactoryCnt = GrProcessorTestFactory<GrFragmentProcessor>::Count();
    for (int i = 0; i < fpFactoryCnt; ++i) {
        // Since FP factories internally randomize, call each 10 times.
        for (int j = 0; j < 10; ++j) {
            SkAutoTUnref<GrDrawBatch> batch(GrRandomDrawBatch(&random, context));
            SkASSERT(batch);
            GrProcessorTestData ptd(&random, context, context->caps(),
                                    drawContext.get(), dummyTextures);
            GrPaint grPaint;
            grPaint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));

            sk_sp<GrFragmentProcessor> fp(
                GrProcessorTestFactory<GrFragmentProcessor>::MakeIdx(i, &ptd));
            sk_sp<GrFragmentProcessor> blockFP(
                BlockInputFragmentProcessor::Make(std::move(fp)));
            grPaint.addColorFragmentProcessor(std::move(blockFP));

            drawContext->drawContextPriv().testingOnly_drawBatch(grPaint, batch);
            drawingManager->flush();
        }
    }

    return true;
}
コード例 #29
0
ファイル: SkImage_Gpu.cpp プロジェクト: JavierJF/skia
sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx , SkYUVColorSpace colorSpace,
                                                const GrBackendObject yuvTextureHandles[3],
                                                const SkISize yuvSizes[3],
                                                GrSurfaceOrigin origin) {
    const SkBudgeted budgeted = SkBudgeted::kYes;

    if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 ||
        yuvSizes[1].fWidth <= 0 || yuvSizes[1].fHeight <= 0 ||
        yuvSizes[2].fWidth <= 0 || yuvSizes[2].fHeight <= 0) {
        return nullptr;
    }
    static const GrPixelConfig kConfig = 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;

    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;

    SkAutoTUnref<GrTexture> yTex(ctx->textureProvider()->wrapBackendTexture(
        yDesc, kBorrow_GrWrapOwnership));
    SkAutoTUnref<GrTexture> uTex(ctx->textureProvider()->wrapBackendTexture(
        uDesc, kBorrow_GrWrapOwnership));
    SkAutoTUnref<GrTexture> vTex(ctx->textureProvider()->wrapBackendTexture(
        vDesc, kBorrow_GrWrapOwnership));
    if (!yTex || !uTex || !vTex) {
        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<GrDrawContext> drawContext(ctx->newDrawContext(GrContext::kTight_BackingFit,
                                                         width, height,
                                                         kRGBA_8888_GrPixelConfig,
                                                         0,
                                                         origin));
    if (!drawContext) {
        return nullptr;
    }

    GrPaint paint;
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    paint.addColorFragmentProcessor(GrYUVEffect::CreateYUVToRGB(yTex, uTex, vTex, yuvSizes,
                                                                colorSpace))->unref();

    const SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));

    drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect);
    ctx->flushSurfaceWrites(drawContext->accessRenderTarget());
    return sk_make_sp<SkImage_Gpu>(width, height, kNeedNewImageUniqueID,
                                   kOpaque_SkAlphaType,
                                   drawContext->asTexture().get(), budgeted);
}
コード例 #30
0
ファイル: GrYUVProvider.cpp プロジェクト: BertiKarsunke/skia
GrTexture* GrYUVProvider::refAsTexture(GrContext* ctx, const GrSurfaceDesc& desc, bool useCache) {
    SkYUVPlanesCache::Info yuvInfo;
    void* planes[3];
    YUVScoper scoper;
    if (!scoper.init(this, &yuvInfo, planes, useCache)) {
        return nullptr;
    }

    GrSurfaceDesc yuvDesc;
    yuvDesc.fConfig = kAlpha_8_GrPixelConfig;
    SkAutoTUnref<GrTexture> yuvTextures[3];
    for (int i = 0; i < 3; i++) {
        yuvDesc.fWidth  = yuvInfo.fSizeInfo.fSizes[i].fWidth;
        yuvDesc.fHeight = yuvInfo.fSizeInfo.fSizes[i].fHeight;
        // TODO: why do we need this check?
        bool needsExactTexture =
                (yuvDesc.fWidth  != yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth) ||
                (yuvDesc.fHeight != yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);
        if (needsExactTexture) {
            yuvTextures[i].reset(ctx->textureProvider()->createTexture(yuvDesc, SkBudgeted::kYes));
        } else {
            yuvTextures[i].reset(ctx->textureProvider()->createApproxTexture(yuvDesc));
        }
        if (!yuvTextures[i] ||
            !yuvTextures[i]->writePixels(0, 0, yuvDesc.fWidth, yuvDesc.fHeight, yuvDesc.fConfig,
                                         planes[i], yuvInfo.fSizeInfo.fWidthBytes[i])) {
                return nullptr;
            }
    }

    GrSurfaceDesc rtDesc = desc;
    rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;

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

    GrRenderTarget* renderTarget = result->asRenderTarget();
    SkASSERT(renderTarget);

    GrPaint paint;
    // We may be decoding an sRGB image, but the result of our linear math on the YUV planes
    // is already in sRGB in that case. Don't convert (which will make the image too bright).
    paint.setDisableOutputConversionToSRGB(true);
    SkAutoTUnref<const GrFragmentProcessor> yuvToRgbProcessor(
                                        GrYUVEffect::CreateYUVToRGB(yuvTextures[0],
                                                                    yuvTextures[1],
                                                                    yuvTextures[2],
                                                                    yuvInfo.fSizeInfo.fSizes,
                                                                    yuvInfo.fColorSpace));
    paint.addColorFragmentProcessor(yuvToRgbProcessor);
    paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
    const SkRect r = SkRect::MakeIWH(yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth,
            yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight);

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

    drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), r);

    return result.release();
}