예제 #1
0
// Create a mask of 'devPath' and place the result in 'mask'.
static GrTexture* create_mask_GPU(GrContext* context,
                                  SkRect* maskRect,
                                  const SkPath& devPath,
                                  const GrStrokeInfo& strokeInfo,
                                  bool doAA,
                                  int sampleCnt) {
    // This mask will ultimately be drawn as a non-AA rect (see draw_mask).
    // Non-AA rects have a bad habit of snapping arbitrarily. Integerize here
    // so the mask draws in a reproducible manner.
    *maskRect = SkRect::Make(maskRect->roundOut());

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = SkScalarCeilToInt(maskRect->width());
    desc.fHeight = SkScalarCeilToInt(maskRect->height());
    desc.fSampleCnt = doAA ? sampleCnt : 0;
    // We actually only need A8, but it often isn't supported as a
    // render target so default to RGBA_8888
    desc.fConfig = kRGBA_8888_GrPixelConfig;

    if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, desc.fSampleCnt > 0)) {
        desc.fConfig = kAlpha_8_GrPixelConfig;
    }

    GrTexture* mask = context->textureProvider()->createApproxTexture(desc);
    if (nullptr == mask) {
        return nullptr;
    }

    SkRect clipRect = SkRect::MakeWH(maskRect->width(), maskRect->height());

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

    drawContext->clear(nullptr, 0x0, true);

    GrPaint tempPaint;
    tempPaint.setAntiAlias(doAA);
    tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);

    // setup new clip
    GrClip clip(clipRect);

    // Draw the mask into maskTexture with the path's integerized top-left at
    // the origin using tempPaint.
    SkMatrix translate;
    translate.setTranslate(-maskRect->fLeft, -maskRect->fTop);
    drawContext->drawPath(clip, tempPaint, translate, devPath, strokeInfo);
    return mask;
}
예제 #2
0
파일: GrBlurUtils.cpp 프로젝트: tiftof/skia
// Create a mask of 'devPath' and place the result in 'mask'.
static GrTexture* create_mask_GPU(GrContext* context,
                                  const SkRect& maskRect,
                                  const SkPath& devPath,
                                  const GrStrokeInfo& strokeInfo,
                                  bool doAA,
                                  int sampleCnt) {
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = SkScalarCeilToInt(maskRect.width());
    desc.fHeight = SkScalarCeilToInt(maskRect.height());
    desc.fSampleCnt = doAA ? sampleCnt : 0;
    // We actually only need A8, but it often isn't supported as a
    // render target so default to RGBA_8888
    desc.fConfig = kRGBA_8888_GrPixelConfig;

    if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, desc.fSampleCnt > 0)) {
        desc.fConfig = kAlpha_8_GrPixelConfig;
    }

    GrTexture* mask = context->textureProvider()->createApproxTexture(desc);
    if (nullptr == mask) {
        return nullptr;
    }

    SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());

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

    drawContext->clear(mask->asRenderTarget(), nullptr, 0x0, true);

    GrPaint tempPaint;
    tempPaint.setAntiAlias(doAA);
    tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);

    // setup new clip
    GrClip clip(clipRect);

    // Draw the mask into maskTexture with the path's top-left at the origin using tempPaint.
    SkMatrix translate;
    translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
    drawContext->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, devPath, strokeInfo);
    return mask;
}
예제 #3
0
// Create a mask of 'devPath' and place the result in 'mask'.
static sk_sp<GrTexture> create_mask_GPU(GrContext* context,
                                        const SkIRect& maskRect,
                                        const SkPath& devPath,
                                        SkStrokeRec::InitStyle fillOrHairline,
                                        bool doAA,
                                        int sampleCnt) {
    if (!doAA) {
        // Don't need MSAA if mask isn't AA
        sampleCnt = 0;
    }

    // We actually only need A8, but it often isn't supported as a
    // render target so default to RGBA_8888
    GrPixelConfig config = kRGBA_8888_GrPixelConfig;
    if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, sampleCnt > 0)) {
        config = kAlpha_8_GrPixelConfig;
    }

    sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kApprox,
                                                             maskRect.width(), 
                                                             maskRect.height(),
                                                             config,
                                                             sampleCnt));
    if (!drawContext) {
        return nullptr;
    }

    drawContext->clear(nullptr, 0x0, true);

    GrPaint tempPaint;
    tempPaint.setAntiAlias(doAA);
    tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);

    // setup new clip
    const SkIRect clipRect = SkIRect::MakeWH(maskRect.width(), maskRect.height());
    GrFixedClip clip(clipRect);

    // Draw the mask into maskTexture with the path's integerized top-left at
    // the origin using tempPaint.
    SkMatrix translate;
    translate.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop));
    drawContext->drawPath(clip, tempPaint, translate, devPath, GrStyle(fillOrHairline));
    return drawContext->asTexture();;
}
예제 #4
0
// Create a mask of 'devPath' and place the result in 'mask'.
static sk_sp<GrTexture> create_mask_GPU(GrContext* context,
                                        const SkIRect& maskRect,
                                        const SkPath& devPath,
                                        SkStrokeRec::InitStyle fillOrHairline,
                                        bool doAA,
                                        int sampleCnt) {
    if (!doAA) {
        // Don't need MSAA if mask isn't AA
        sampleCnt = 0;
    }

    sk_sp<GrDrawContext> drawContext(context->makeDrawContextWithFallback(SkBackingFit::kApprox,
                                                                          maskRect.width(), 
                                                                          maskRect.height(),
                                                                          kAlpha_8_GrPixelConfig,
                                                                          nullptr,
                                                                          sampleCnt));
    if (!drawContext) {
        return nullptr;
    }

    drawContext->clear(nullptr, 0x0, true);

    GrPaint tempPaint;
    tempPaint.setAntiAlias(doAA);
    tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);

    // setup new clip
    const SkIRect clipRect = SkIRect::MakeWH(maskRect.width(), maskRect.height());
    GrFixedClip clip(clipRect);

    // Draw the mask into maskTexture with the path's integerized top-left at
    // the origin using tempPaint.
    SkMatrix translate;
    translate.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop));
    drawContext->drawPath(clip, tempPaint, translate, devPath, GrStyle(fillOrHairline));
    return drawContext->asTexture();;
}
예제 #5
0
sk_sp<GrTexture> GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
                                                        int32_t elementsGenID,
                                                        GrReducedClip::InitialState initialState,
                                                        const GrReducedClip::ElementList& elements,
                                                        const SkVector& clipToMaskOffset,
                                                        const SkIRect& clipSpaceIBounds) {
    GrResourceProvider* resourceProvider = context->resourceProvider();
    GrUniqueKey key;
    GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
    if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
        return sk_sp<GrTexture>(texture);
    }

    // There's no texture in the cache. Let's try to allocate it then.
    GrPixelConfig config = kRGBA_8888_GrPixelConfig;
    if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
        config = kAlpha_8_GrPixelConfig;
    }

    sk_sp<GrDrawContext> dc(context->newDrawContext(SkBackingFit::kApprox,
                                                    clipSpaceIBounds.width(),
                                                    clipSpaceIBounds.height(),
                                                    config));
    if (!dc) {
        return nullptr;
    }
    
    // The texture may be larger than necessary, this rect represents the part of the texture
    // we populate with a rasterization of the clip.
    SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());

    // The scratch texture that we are drawing into can be substantially larger than the mask. Only
    // clear the part that we care about.
    dc->clear(&maskSpaceIBounds,
              GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
              true);

    // Set the matrix so that rendered clip elements are transformed to mask space from clip
    // space.
    const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);

    // It is important that we use maskSpaceIBounds as the stencil rect in the below loop.
    // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first
    // pass must not set values outside of this bounds or stencil values outside the rect won't be
    // cleared.

    // walk through each clip element and perform its set op
    for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
        const Element* element = iter.get();
        SkRegion::Op op = element->getOp();
        bool invert = element->isInverseFilled();
        if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
            GrFixedClip clip(maskSpaceIBounds);

            // draw directly into the result with the stencil set to make the pixels affected
            // by the clip shape be non-zero.
            static constexpr GrUserStencilSettings kStencilInElement(
                 GrUserStencilSettings::StaticInit<
                     0xffff,
                     GrUserStencilTest::kAlways,
                     0xffff,
                     GrUserStencilOp::kReplace,
                     GrUserStencilOp::kReplace,
                     0xffff>()
            );
            if (!stencil_element(dc.get(), clip, &kStencilInElement,
                                 translate, element)) {
                return nullptr;
            }

            // Draw to the exterior pixels (those with a zero stencil value).
            static constexpr GrUserStencilSettings kDrawOutsideElement(
                 GrUserStencilSettings::StaticInit<
                     0x0000,
                     GrUserStencilTest::kEqual,
                     0xffff,
                     GrUserStencilOp::kZero,
                     GrUserStencilOp::kZero,
                     0xffff>()
            );
            if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideElement,
                                                          op, !invert, false,
                                                          translate,
                                                          SkRect::Make(clipSpaceIBounds))) {
                return nullptr;
            }
        } else {
            // all the remaining ops can just be directly draw into the accumulation buffer
            GrPaint paint;
            paint.setAntiAlias(element->isAA());
            paint.setCoverageSetOpXPFactory(op, false);

            draw_element(dc.get(), GrNoClip(), paint, translate, element);
        }
    }

    sk_sp<GrTexture> texture(dc->asTexture());
    SkASSERT(texture);
    texture->resourcePriv().setUniqueKey(key);
    return texture;
}