GrPixelConfig SkImageInfo2GrPixelConfig(const SkColorType type, SkColorSpace* cs,
                                        const GrCaps& caps) {
    switch (type) {
        case kUnknown_SkColorType:
            return kUnknown_GrPixelConfig;
        case kAlpha_8_SkColorType:
            return kAlpha_8_GrPixelConfig;
        case kRGB_565_SkColorType:
            return kRGB_565_GrPixelConfig;
        case kARGB_4444_SkColorType:
            return kRGBA_4444_GrPixelConfig;
        case kRGBA_8888_SkColorType:
            return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
                   ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
        // TODO: We're checking for srgbSupport, but we can then end up picking sBGRA as our pixel
        // config (which may not be supported). We need a better test here.
        case kRGB_888x_SkColorType:
            return kUnknown_GrPixelConfig;
        case kBGRA_8888_SkColorType:
            return (caps.srgbSupport() && cs && cs->gammaCloseToSRGB())
                   ? kSBGRA_8888_GrPixelConfig : kBGRA_8888_GrPixelConfig;
        case kRGBA_1010102_SkColorType:
            return kRGBA_1010102_GrPixelConfig;
        case kRGB_101010x_SkColorType:
            return kUnknown_GrPixelConfig;
        case kGray_8_SkColorType:
            return kGray_8_GrPixelConfig;
        case kRGBA_F16_SkColorType:
            return kRGBA_half_GrPixelConfig;
    }
    SkASSERT(0);    // shouldn't get here
    return kUnknown_GrPixelConfig;
}
bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps,
                                                     const GrPipelineOptimizations& optimizations) {
    if (caps.shaderCaps()->dstReadInShaderSupport() ||
        caps.shaderCaps()->dualSourceBlendingSupport()) {
        return false;
    }

    // When we have four channel coverage we always need to read the dst in order to correctly
    // blend. The one exception is when we are using srcover mode and we know the input color
    // into the XP.
    if (optimizations.fCoveragePOI.isFourChannelOutput()) {
        if (kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() &&
            !caps.shaderCaps()->dstReadInShaderSupport()) {
            return false;
        }
        return get_lcd_blend_formula(optimizations.fCoveragePOI,
                                     SkBlendMode::kSrcOver).hasSecondaryOutput();
    }

    // We fallback on the shader XP when the blend formula would use dual source blending but we
    // don't have support for it.
    static const bool kHasMixedSamples = false;
    SkASSERT(!caps.usesMixedSamples()); // We never use mixed samples without dual source blending.
    return get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI,
                             kHasMixedSamples, SkBlendMode::kSrcOver).hasSecondaryOutput();
}
Beispiel #3
0
GrCCPRAtlas::GrCCPRAtlas(const GrCaps& caps, int minWidth, int minHeight)
        : fMaxAtlasSize(caps.maxRenderTargetSize())
        , fDrawBounds{0, 0} {
    SkASSERT(fMaxAtlasSize <= caps.maxTextureSize());
    SkASSERT(SkTMax(minWidth, minHeight) <= fMaxAtlasSize);
    int initialSize = GrNextPow2(SkTMax(minWidth, minHeight));
    initialSize = SkTMax(int(kMinSize), initialSize);
    initialSize = SkTMin(initialSize, fMaxAtlasSize);
    fHeight = fWidth = initialSize;
    fTopNode = skstd::make_unique<Node>(nullptr, 0, 0, initialSize, initialSize);
}
// Deferred version
// TODO: we can probably munge the 'desc' in both the wrapped and deferred
// cases to make the sampleConfig/numSamples stuff more rational.
GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps, const GrSurfaceDesc& desc,
                                         SkBackingFit fit, SkBudgeted budgeted, uint32_t flags)
    : INHERITED(desc, fit, budgeted, flags)
    , fRenderTargetFlags(GrRenderTarget::Flags::kNone) {
    // Since we know the newly created render target will be internal, we are able to precompute
    // what the flags will ultimately end up being.
    if (caps.usesMixedSamples() && fDesc.fSampleCnt > 0) {
        fRenderTargetFlags |= GrRenderTarget::Flags::kMixedSampled;
    }
    if (caps.maxWindowRectangles() > 0) {
        fRenderTargetFlags |= GrRenderTarget::Flags::kWindowRectsSupport;
    }
}
Beispiel #5
0
static bool can_use_hw_blend_equation(GrBlendEquation equation,
                                      const GrProcOptInfo& coveragePOI,
                                      const GrCaps& caps) {
    if (!caps.advancedBlendEquationSupport()) {
        return false;
    }
    if (coveragePOI.isFourChannelOutput()) {
        return false; // LCD coverage must be applied after the blend equation.
    }
    if (caps.canUseAdvancedBlendEquation(equation)) {
        return false;
    }
    return true;
}
Beispiel #6
0
bool GrXPFactory::willNeedDstTexture(const GrCaps& caps,
                                     const GrProcOptInfo& colorPOI,
                                     const GrProcOptInfo& coveragePOI,
                                     bool hasMixedSamples) const {
    return (this->willReadDstColor(caps, colorPOI, coveragePOI, hasMixedSamples) &&
            !caps.shaderCaps()->dstReadInShaderSupport());
}
Beispiel #7
0
bool GrTextureUsageSupported(const GrCaps& caps, int width, int height, SkImageUsageType usage) {
    if (caps.npotTextureTileSupport()) {
        return true;
    }
    const bool is_pow2 = SkIsPow2(width) && SkIsPow2(height);
    return is_pow2 || kUntiled_SkImageUsageType == usage;
}
Beispiel #8
0
void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID,
                          U16CPU width, U16CPU height, SkIPoint origin,
                          const GrCaps& caps, SkImageUsageType usage) {
    const Stretch::Type stretches[] = {
        Stretch::kNone_Type,        // kUntiled_SkImageUsageType
        Stretch::kNearest_Type,     // kTiled_Unfiltered_SkImageUsageType
        Stretch::kBilerp_Type,      // kTiled_Filtered_SkImageUsageType
    };

    const bool isPow2 = SkIsPow2(width) && SkIsPow2(height);
    const bool needToStretch = !isPow2 &&
                               usage != kUntiled_SkImageUsageType &&
                               !caps.npotTextureTileSupport();

    if (needToStretch) {
        GrUniqueKey tmpKey;
        make_unstretched_key(&tmpKey, imageID, width, height, origin);

        Stretch stretch;
        stretch.fType = stretches[usage];
        stretch.fWidth = SkNextPow2(width);
        stretch.fHeight = SkNextPow2(height);
        if (!make_stretched_key(tmpKey, stretch, key)) {
            goto UNSTRETCHED;
        }
    } else {
        UNSTRETCHED:
        make_unstretched_key(key, imageID, width, height, origin);
    }
}
Beispiel #9
0
GrXferBarrierType GrXferProcessor::xferBarrierType(const GrRenderTarget* rt,
                                                   const GrCaps& caps) const {
    SkASSERT(rt);
    if (static_cast<const GrSurface*>(rt) == this->getDstTexture()) {
        // Texture barriers are required when a shader reads and renders to the same texture.
        SkASSERT(caps.textureBarrierSupport());
        return kTexture_GrXferBarrierType;
    }
    return this->onXferBarrier(rt, caps);
}
bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps,
                                             const GrProcOptInfo& colorPOI,
                                             const GrProcOptInfo& coveragePOI) const {
    if (coveragePOI.isFourChannelOutput()) {
        return false; // The LCD XP never does a dst read.
    }

    // We fallback on the shader XP when the blend formula would use dual source blending but we
    // don't have support for it.
    return !caps.shaderCaps()->dualSourceBlendingSupport() &&
           get_blend_formula(fXfermode, colorPOI, coveragePOI).hasSecondaryOutput();
}
GrXPFactory::AnalysisProperties GrXPFactory::GetAnalysisProperties(
        const GrXPFactory* factory,
        const GrProcessorAnalysisColor& color,
        const GrProcessorAnalysisCoverage& coverage,
        const GrCaps& caps) {
    AnalysisProperties result;
    if (factory) {
        result = factory->analysisProperties(color, coverage, caps);
    } else {
        result = GrPorterDuffXPFactory::SrcOverAnalysisProperties(color, coverage, caps);
    }
    SkASSERT(!(result & AnalysisProperties::kRequiresDstTexture));
    if ((result & AnalysisProperties::kReadsDstInShader) &&
        !caps.shaderCaps()->dstReadInShaderSupport()) {
        result |= AnalysisProperties::kRequiresDstTexture;
        if (caps.textureBarrierSupport()) {
            result |= AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws;
        }
    }
    return result;
}
sk_sp<const GrXferProcessor> GrXPFactory::MakeXferProcessor(const GrXPFactory* factory,
                                                            const GrProcessorAnalysisColor& color,
                                                            GrProcessorAnalysisCoverage coverage,
                                                            bool hasMixedSamples,
                                                            const GrCaps& caps) {
    SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport());
    if (factory) {
        return factory->makeXferProcessor(color, coverage, hasMixedSamples, caps);
    } else {
        return GrPorterDuffXPFactory::MakeSrcOverXferProcessor(color, coverage, hasMixedSamples,
                                                               caps);
    }
}
bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps,
                                             const GrProcOptInfo& colorPOI,
                                             const GrProcOptInfo& covPOI,
                                             bool hasMixedSamples) const {
    if (caps.shaderCaps()->dualSourceBlendingSupport()) {
        return false;
    }
    if (covPOI.isFourChannelOutput()) {
        return false; // The LCD XP will abort rather than doing a dst read.
    }
    // We fallback on the shader XP when the blend formula would use dual source blending but we
    // don't have support for it.
    return get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode).hasSecondaryOutput();
}
Beispiel #14
0
bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps,
                                             const GrProcOptInfo& colorPOI,
                                             const GrProcOptInfo& covPOI,
                                             bool hasMixedSamples) const {
    if (caps.shaderCaps()->dualSourceBlendingSupport()) {
        return false;
    }
    
    // When we have four channel coverage we always need to read the dst in order to correctly
    // blend. The one exception is when we are using srcover mode and we know the input color into
    // the XP.
    if (covPOI.isFourChannelOutput()) {
        if (SkXfermode::kSrcOver_Mode == fXfermode &&
            kRGBA_GrColorComponentFlags == colorPOI.validFlags() &&
            !caps.shaderCaps()->dstReadInShaderSupport()) {
            return false;
        }
        return get_lcd_blend_formula(covPOI, fXfermode).hasSecondaryOutput();
    }
    // We fallback on the shader XP when the blend formula would use dual source blending but we
    // don't have support for it.
    return get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode).hasSecondaryOutput();
}
int GrRenderTargetProxy::maxWindowRectangles(const GrCaps& caps) const {
    return (fRenderTargetFlags & GrRenderTarget::Flags::kWindowRectsSupport)
                   ? caps.maxWindowRectangles()
                   : 0;
}
Beispiel #16
0
GrXferBarrierType CustomXP::onXferBarrier(const GrRenderTarget* rt, const GrCaps& caps) const {
    if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport()) {
        return kBlend_GrXferBarrierType;
    }
    return kNone_GrXferBarrierType;
}
Beispiel #17
0
bool GrXPFactory::willNeedDstTexture(const GrCaps& caps,
                                     const GrPipelineOptimizations& optimizations,
                                     bool hasMixedSamples) const {
    return (this->willReadDstColor(caps, optimizations, hasMixedSamples) &&
            !caps.shaderCaps()->dstReadInShaderSupport());
}
Beispiel #18
0
GrRenderTarget::SampleConfig GrRenderTarget::ComputeSampleConfig(const GrCaps& caps,
                                                                 int sampleCnt) {
    return (caps.usesMixedSamples() && sampleCnt > 0)
                        ? GrRenderTarget::kStencil_SampleConfig
                        : GrRenderTarget::kUnified_SampleConfig;
}
Beispiel #19
0
std::unique_ptr<GrFillRRectOp> GrFillRRectOp::Make(
        GrRecordingContext* ctx, GrAAType aaType, const SkMatrix& viewMatrix, const SkRRect& rrect,
        const GrCaps& caps, GrPaint&& paint) {
    if (!caps.instanceAttribSupport()) {
        return nullptr;
    }

    Flags flags = Flags::kNone;
    if (GrAAType::kCoverage == aaType) {
        // TODO: Support perspective in a follow-on CL. This shouldn't be difficult, since we
        // already use HW derivatives. The only trick will be adjusting the AA outset to account for
        // perspective. (i.e., outset = 0.5 * z.)
        if (viewMatrix.hasPerspective()) {
            return nullptr;
        }
        if (can_use_hw_derivatives_with_coverage(*caps.shaderCaps(), viewMatrix, rrect)) {
            // HW derivatives (more specifically, fwidth()) are consistently faster on all platforms
            // in coverage mode. We use them as long as the approximation will be accurate enough.
            flags |= Flags::kUseHWDerivatives;
        }
    } else {
        if (GrAAType::kMSAA == aaType) {
            if (!caps.sampleLocationsSupport() || !caps.shaderCaps()->sampleVariablesSupport()) {
                return nullptr;
            }
        }
        if (viewMatrix.hasPerspective()) {
            // HW derivatives are consistently slower on all platforms in sample mask mode. We
            // therefore only use them when there is perspective, since then we can't interpolate
            // the symbolic screen-space gradient.
            flags |= Flags::kUseHWDerivatives | Flags::kHasPerspective;
        }
    }

    // Produce a matrix that draws the round rect from normalized [-1, -1, +1, +1] space.
    float l = rrect.rect().left(), r = rrect.rect().right(),
          t = rrect.rect().top(), b = rrect.rect().bottom();
    SkMatrix m;
    // Unmap the normalized rect [-1, -1, +1, +1] back to [l, t, r, b].
    m.setScaleTranslate((r - l)/2, (b - t)/2, (l + r)/2, (t + b)/2);
    // Map to device space.
    m.postConcat(viewMatrix);

    SkRect devBounds;
    if (!(flags & Flags::kHasPerspective)) {
        // Since m is an affine matrix that maps the rect [-1, -1, +1, +1] into the shape's
        // device-space quad, it's quite simple to find the bounding rectangle:
        devBounds = SkRect::MakeXYWH(m.getTranslateX(), m.getTranslateY(), 0, 0);
        devBounds.outset(SkScalarAbs(m.getScaleX()) + SkScalarAbs(m.getSkewX()),
                         SkScalarAbs(m.getSkewY()) + SkScalarAbs(m.getScaleY()));
    } else {
        viewMatrix.mapRect(&devBounds, rrect.rect());
    }

    if (GrAAType::kMSAA == aaType && caps.preferTrianglesOverSampleMask()) {
        // We are on a platform that prefers fine triangles instead of using the sample mask. See if
        // the round rect is large enough that it will be faster for us to send it off to the
        // default path renderer instead. The 200x200 threshold was arrived at using the
        // "shapes_rrect" benchmark on an ARM Galaxy S9.
        if (devBounds.height() * devBounds.width() > 200 * 200) {
            return nullptr;
        }
    }

    GrOpMemoryPool* pool = ctx->priv().opMemoryPool();
    return pool->allocate<GrFillRRectOp>(aaType, rrect, flags, m, std::move(paint), devBounds);
}