/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrTextureMaker.h"
#include "GrContext.h"
#include "GrGpu.h"
#include "GrResourceProvider.h"
sk_sp<GrTextureProxy> GrTextureMaker::refTextureProxyForParams(const GrSamplerParams& params,
SkColorSpace* dstColorSpace,
sk_sp<SkColorSpace>* texColorSpace,
SkScalar scaleAdjust[2]) {
CopyParams copyParams;
bool willBeMipped = params.filterMode() == GrSamplerParams::kMipMap_FilterMode;
if (!fContext->caps()->mipMapSupport()) {
willBeMipped = false;
}
if (texColorSpace) {
*texColorSpace = this->getColorSpace(dstColorSpace);
}
if (!fContext->getGpu()->isACopyNeededForTextureParams(this->width(), this->height(), params,
©Params, scaleAdjust)) {
return this->refOriginalTextureProxy(willBeMipped, dstColorSpace);
}
GrUniqueKey copyKey;
this->makeCopyKey(copyParams, ©Key, dstColorSpace);
if (copyKey.isValid()) {
sk_sp<GrTextureProxy> result(fContext->resourceProvider()->findProxyByUniqueKey(copyKey));
if (result) {
return result;
}
}
sk_sp<GrTextureProxy> result(this->generateTextureProxyForParams(copyParams, willBeMipped,
dstColorSpace));
if (!result) {
return nullptr;
}
if (copyKey.isValid()) {
fContext->resourceProvider()->assignUniqueKeyToProxy(copyKey, result.get());
this->didCacheCopy(copyKey);
}
return result;
}
sk_sp<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
const SkMatrix& textureMatrix,
const SkRect& constraintRect,
FilterConstraint filterConstraint,
bool coordsLimitedToConstraintRect,
const GrSamplerParams::FilterMode* filterOrNullForBicubic,
SkColorSpace* dstColorSpace) {
const GrSamplerParams::FilterMode* fmForDetermineDomain = filterOrNullForBicubic;
if (filterOrNullForBicubic && GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic &&
kYes_FilterConstraint == filterConstraint) {
// TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
// read outside the constraint rect. However, as in the adjuster case, we aren't currently
// doing that.
// We instead we compute the domain as though were bilerping which is only correct if we
// only sample level 0.
static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
fmForDetermineDomain = &kBilerp;
}
GrSamplerParams params;
if (filterOrNullForBicubic) {
params.reset(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
} else {
// Bicubic doesn't use filtering for it's texture accesses.
params.reset(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
}
sk_sp<SkColorSpace> texColorSpace;
SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
sk_sp<GrTextureProxy> proxy(this->refTextureProxyForParams(params, dstColorSpace,
&texColorSpace,
scaleAdjust));
if (!proxy) {
return nullptr;
}
SkMatrix adjustedMatrix = textureMatrix;
adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
SkRect domain;
DomainMode domainMode =
DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
proxy.get(),
nullptr, fmForDetermineDomain, &domain);
SkASSERT(kTightCopy_DomainMode != domainMode);
sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
dstColorSpace);
return CreateFragmentProcessorForDomainAndFilter(fContext->resourceProvider(), std::move(proxy),
std::move(colorSpaceXform),
adjustedMatrix, domainMode, domain,
filterOrNullForBicubic);
}
sk_sp<GrTextureProxy> GrTextureMaker::generateTextureProxyForParams(const CopyParams& copyParams,
bool willBeMipped,
SkColorSpace* dstColorSpace) {
sk_sp<GrTextureProxy> original(this->refOriginalTextureProxy(willBeMipped, dstColorSpace));
if (!original) {
return nullptr;
}
return CopyOnGpu(fContext, std::move(original), nullptr, copyParams);
}