sk_sp<GrTextureProxy> GrTextureProducer::refTextureProxyForParams(
        const GrSamplerState& sampler,
        SkColorSpace* dstColorSpace,
        sk_sp<SkColorSpace>* proxyColorSpace,
        SkScalar scaleAdjust[2]) {
    // Check that the caller pre-initialized scaleAdjust
    SkASSERT(!scaleAdjust || (scaleAdjust[0] == 1 && scaleAdjust[1] == 1));
    // Check that if the caller passed nullptr for scaleAdjust that we're in the case where there
    // can be no scaling.
    SkDEBUGCODE(bool expectNoScale = (sampler.filter() != GrSamplerState::Filter::kMipMap &&
                                      !sampler.isRepeated()));
    SkASSERT(scaleAdjust || expectNoScale);

    int mipCount = SkMipMap::ComputeLevelCount(this->width(), this->height());
    bool willBeMipped = GrSamplerState::Filter::kMipMap == sampler.filter() && mipCount &&
                        fContext->contextPriv().caps()->mipMapSupport();

    auto result =
            this->onRefTextureProxyForParams(sampler, dstColorSpace, proxyColorSpace, willBeMipped,
                                             scaleAdjust);

    // Check to make sure that if we say the texture willBeMipped that the returned texture has mip
    // maps, unless the config is not copyable.
    SkASSERT(!result || !willBeMipped || result->mipMapped() == GrMipMapped::kYes ||
             !fContext->contextPriv().caps()->isConfigCopyable(result->config()));

    // Check that the "no scaling expected" case always returns a proxy of the same size as the
    // producer.
    SkASSERT(!result || !expectNoScale ||
             (result->width() == this->width() && result->height() == this->height()));
    return result;
}
Esempio n. 2
0
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
        const SkMatrix& origTextureMatrix,
        const SkRect& constraintRect,
        FilterConstraint filterConstraint,
        bool coordsLimitedToConstraintRect,
        const GrSamplerState::Filter* filterOrNullForBicubic,
        SkColorSpace* dstColorSpace) {
    SkMatrix textureMatrix = origTextureMatrix;

    SkRect domain;
    GrSamplerState samplerState;
    if (filterOrNullForBicubic) {
        samplerState.setFilterMode(*filterOrNullForBicubic);
    }
    SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
    sk_sp<GrTextureProxy> proxy(
            this->refTextureProxySafeForParams(samplerState, scaleAdjust));
    if (!proxy) {
        return nullptr;
    }
    // If we made a copy then we only copied the contentArea, in which case the new texture is all
    // content.
    if (proxy.get() != this->originalProxy()) {
        textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
    }

    DomainMode domainMode =
        DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
                            proxy.get(), filterOrNullForBicubic, &domain);
    if (kTightCopy_DomainMode == domainMode) {
        // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
        // non-int constraint rect)
        // For now: treat as bilerp and ignore what goes on above level 0.

        // We only expect MIP maps to require a tight copy.
        SkASSERT(filterOrNullForBicubic &&
                 GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic);
        static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
        domainMode =
            DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
                                proxy.get(), &kBilerp, &domain);
        SkASSERT(kTightCopy_DomainMode != domainMode);
    }
    SkASSERT(kNoDomain_DomainMode == domainMode ||
             (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
    GrPixelConfig config = proxy->config();
    auto fp = CreateFragmentProcessorForDomainAndFilter(std::move(proxy), textureMatrix,
                                                        domainMode, domain, filterOrNullForBicubic);
    return GrColorSpaceXformEffect::Make(std::move(fp), fColorSpace, config, dstColorSpace);
}
Esempio n. 3
0
bool GrGpu::IsACopyNeededForTextureParams(const GrCaps* caps, GrTextureProxy* texProxy,
                                          int width, int height,
                                          const GrSamplerState& textureParams,
                                          GrTextureProducer::CopyParams* copyParams,
                                          SkScalar scaleAdjust[2]) {

    if (texProxy) {
        // If the texture format itself doesn't support repeat wrap mode or mipmapping (and
        // those capabilities are required) force a copy.
        if ((textureParams.isRepeated() && texProxy->texPriv().isClampOnly()) ||
            (GrSamplerState::Filter::kMipMap == textureParams.filter() &&
                                                    texProxy->texPriv().doesNotSupportMipMaps())) {
            copyParams->fFilter = GrSamplerState::Filter::kNearest;
            copyParams->fWidth = texProxy->width();
            copyParams->fHeight = texProxy->height();
            return true;
        }
    }

    if (textureParams.isRepeated() && !caps->npotTextureTileSupport() &&
        (!SkIsPow2(width) || !SkIsPow2(height))) {
        SkASSERT(scaleAdjust);
        copyParams->fWidth = GrNextPow2(width);
        copyParams->fHeight = GrNextPow2(height);
        SkASSERT(scaleAdjust);
        scaleAdjust[0] = ((SkScalar) copyParams->fWidth) / width;
        scaleAdjust[1] = ((SkScalar) copyParams->fHeight) / height;
        switch (textureParams.filter()) {
            case GrSamplerState::Filter::kNearest:
                copyParams->fFilter = GrSamplerState::Filter::kNearest;
                break;
            case GrSamplerState::Filter::kBilerp:
            case GrSamplerState::Filter::kMipMap:
                // We are only ever scaling up so no reason to ever indicate kMipMap.
                copyParams->fFilter = GrSamplerState::Filter::kBilerp;
                break;
        }
        return true;
    }
    return false;
}
Esempio n. 4
0
sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams(const GrSamplerState& params,
                                                                      SkScalar scaleAdjust[2]) {
    sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
    CopyParams copyParams;

    if (!fContext) {
        // The texture was abandoned.
        return nullptr;
    }

    if (!GrGpu::IsACopyNeededForTextureParams(fContext->caps(),
                                              proxy.get(), proxy->width(), proxy->height(),
                                              params, &copyParams, scaleAdjust)) {
        return proxy;
    }

    bool willBeMipped = GrSamplerState::Filter::kMipMap == params.filter();
    return this->refTextureProxyCopy(copyParams, willBeMipped);
}
Esempio n. 5
0
GrVkSampler::Key GrVkSampler::GenerateKey(const GrSamplerState& samplerState,
                                          const GrVkYcbcrConversionInfo& ycbcrInfo) {
    const int kTileModeXShift = 2;
    const int kTileModeYShift = 4;

    SkASSERT(static_cast<int>(samplerState.filter()) <= 3);
    uint8_t samplerKey = static_cast<uint16_t>(samplerState.filter());

    SkASSERT(static_cast<int>(samplerState.wrapModeX()) <= 3);
    samplerKey |= (static_cast<uint8_t>(samplerState.wrapModeX()) << kTileModeXShift);

    SkASSERT(static_cast<int>(samplerState.wrapModeY()) <= 3);
    samplerKey |= (static_cast<uint8_t>(samplerState.wrapModeY()) << kTileModeYShift);

    return {samplerKey, GrVkSamplerYcbcrConversion::GenerateKey(ycbcrInfo)};
}