Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrTextureMaker.h"
      9 
     10 #include "GrColorSpaceXform.h"
     11 #include "GrContext.h"
     12 #include "GrContextPriv.h"
     13 #include "GrGpu.h"
     14 #include "GrProxyProvider.h"
     15 
     16 sk_sp<GrTextureProxy> GrTextureMaker::refTextureProxyForParams(const GrSamplerState& params,
     17                                                                SkColorSpace* dstColorSpace,
     18                                                                sk_sp<SkColorSpace>* texColorSpace,
     19                                                                SkScalar scaleAdjust[2]) {
     20     CopyParams copyParams;
     21     bool willBeMipped = params.filter() == GrSamplerState::Filter::kMipMap;
     22 
     23     if (!fContext->caps()->mipMapSupport()) {
     24         willBeMipped = false;
     25     }
     26 
     27     if (texColorSpace) {
     28         *texColorSpace = this->getColorSpace(dstColorSpace);
     29     }
     30 
     31     GrGpu* gpu = fContext->contextPriv().getGpu();
     32     sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
     33                                                                  AllowedTexGenType::kCheap));
     34     if (original) {
     35         if (!gpu->isACopyNeededForTextureParams(original.get(), params, &copyParams, scaleAdjust)) {
     36             return original;
     37         }
     38     } else {
     39         if (!gpu->isACopyNeededForTextureParams(this->width(), this->height(),
     40                                                 params, &copyParams, scaleAdjust)) {
     41             return this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
     42                                                  AllowedTexGenType::kAny);
     43         }
     44     }
     45 
     46     GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
     47 
     48     GrSurfaceOrigin origOrigin = original ? original->origin() : kTopLeft_GrSurfaceOrigin;
     49     GrUniqueKey copyKey;
     50     this->makeCopyKey(copyParams, &copyKey, dstColorSpace);
     51     sk_sp<GrTextureProxy> cachedProxy;
     52     if (copyKey.isValid()) {
     53         cachedProxy = proxyProvider->findOrCreateProxyByUniqueKey(copyKey, origOrigin);
     54         if (cachedProxy && (!willBeMipped || GrMipMapped::kYes == cachedProxy->mipMapped())) {
     55             return cachedProxy;
     56         }
     57     }
     58 
     59     sk_sp<GrTextureProxy> result;
     60     if (original) {
     61         result = std::move(original);
     62     } else if (cachedProxy) {
     63         result = cachedProxy;
     64     } else {
     65         // Since we will be copying this texture there is no reason to make it mipped
     66         result = this->refOriginalTextureProxy(false, dstColorSpace,
     67                                                AllowedTexGenType::kAny);
     68     }
     69     if (!result) {
     70         return nullptr;
     71     }
     72 
     73     result = CopyOnGpu(fContext, std::move(result), copyParams, willBeMipped);
     74 
     75     if (!result) {
     76         return nullptr;
     77     }
     78 
     79     if (copyKey.isValid()) {
     80         SkASSERT(result->origin() == origOrigin);
     81         if (cachedProxy) {
     82             SkASSERT(GrMipMapped::kYes == result->mipMapped() &&
     83                      GrMipMapped::kNo == cachedProxy->mipMapped());
     84             // If we had a cachedProxy, that means there already is a proxy in the cache which
     85             // matches the key, but it does not have mip levels and we require them. Thus we must
     86             // remove the unique key from that proxy.
     87             proxyProvider->removeUniqueKeyFromProxy(copyKey, cachedProxy.get());
     88         }
     89         proxyProvider->assignUniqueKeyToProxy(copyKey, result.get());
     90         this->didCacheCopy(copyKey);
     91     }
     92     return result;
     93 }
     94 
     95 std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
     96         const SkMatrix& textureMatrix,
     97         const SkRect& constraintRect,
     98         FilterConstraint filterConstraint,
     99         bool coordsLimitedToConstraintRect,
    100         const GrSamplerState::Filter* filterOrNullForBicubic,
    101         SkColorSpace* dstColorSpace) {
    102     const GrSamplerState::Filter* fmForDetermineDomain = filterOrNullForBicubic;
    103     if (filterOrNullForBicubic && GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic &&
    104         kYes_FilterConstraint == filterConstraint) {
    105         // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
    106         // read outside the constraint rect. However, as in the adjuster case, we aren't currently
    107         // doing that.
    108         // We instead we compute the domain as though were bilerping which is only correct if we
    109         // only sample level 0.
    110         static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
    111         fmForDetermineDomain = &kBilerp;
    112     }
    113 
    114     GrSamplerState samplerState;
    115     if (filterOrNullForBicubic) {
    116         samplerState = GrSamplerState(GrSamplerState::WrapMode::kClamp, *filterOrNullForBicubic);
    117     } else {
    118         // Bicubic doesn't use filtering for it's texture accesses.
    119         samplerState = GrSamplerState::ClampNearest();
    120     }
    121     sk_sp<SkColorSpace> texColorSpace;
    122     SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
    123     sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(samplerState, dstColorSpace,
    124                                                                &texColorSpace, scaleAdjust));
    125     if (!proxy) {
    126         return nullptr;
    127     }
    128     SkMatrix adjustedMatrix = textureMatrix;
    129     adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
    130     SkRect domain;
    131     DomainMode domainMode =
    132         DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
    133                             proxy.get(), fmForDetermineDomain, &domain);
    134     SkASSERT(kTightCopy_DomainMode != domainMode);
    135     GrPixelConfig config = proxy->config();
    136     auto fp = CreateFragmentProcessorForDomainAndFilter(std::move(proxy), adjustedMatrix,
    137                                                         domainMode, domain, filterOrNullForBicubic);
    138     return GrColorSpaceXformEffect::Make(std::move(fp), texColorSpace.get(), config, dstColorSpace);
    139 }
    140 
    141 sk_sp<GrTextureProxy> GrTextureMaker::generateTextureProxyForParams(const CopyParams& copyParams,
    142                                                                     bool willBeMipped,
    143                                                                     SkColorSpace* dstColorSpace) {
    144     sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace,
    145                                                                  AllowedTexGenType::kAny));
    146     if (!original) {
    147         return nullptr;
    148     }
    149 
    150     return CopyOnGpu(fContext, std::move(original), copyParams, willBeMipped);
    151 }
    152