/*
|
* Copyright 2016 Google Inc.
|
*
|
* Use of this source code is governed by a BSD-style license that can be
|
* found in the LICENSE file.
|
*/
|
|
#ifndef GrTextureProducer_DEFINED
|
#define GrTextureProducer_DEFINED
|
|
#include "GrResourceKey.h"
|
#include "GrSamplerState.h"
|
#include "SkImageInfo.h"
|
#include "SkNoncopyable.h"
|
|
class GrContext;
|
class GrFragmentProcessor;
|
class GrTexture;
|
class GrTextureProxy;
|
class SkColorSpace;
|
class SkMatrix;
|
struct SkRect;
|
|
/**
|
* Different GPUs and API extensions have different requirements with respect to what texture
|
* sampling parameters may be used with textures of various types. This class facilitates making
|
* texture compatible with a given GrSamplerState. There are two immediate subclasses defined
|
* below. One is a base class for sources that are inherently texture-backed (e.g. a texture-backed
|
* SkImage). It supports subsetting the original texture. The other is for use cases where the
|
* source can generate a texture that represents some content (e.g. cpu pixels, SkPicture, ...).
|
*/
|
class GrTextureProducer : public SkNoncopyable {
|
public:
|
struct CopyParams {
|
GrSamplerState::Filter fFilter;
|
int fWidth;
|
int fHeight;
|
};
|
|
enum FilterConstraint {
|
kYes_FilterConstraint,
|
kNo_FilterConstraint,
|
};
|
|
/**
|
* Helper for creating a fragment processor to sample the texture with a given filtering mode.
|
* It attempts to avoid making texture copies or using domains whenever possible.
|
*
|
* @param textureMatrix Matrix used to access the texture. It is applied to
|
* the local coords. The post-transformed coords should
|
* be in texel units (rather than normalized) with
|
* respect to this Producer's bounds (width()/height()).
|
* @param constraintRect A rect that represents the area of the texture to be
|
* sampled. It must be contained in the Producer's
|
* bounds as defined by width()/height().
|
* @param filterConstriant Indicates whether filtering is limited to
|
* constraintRect.
|
* @param coordsLimitedToConstraintRect Is it known that textureMatrix*localCoords is bound
|
* by the portion of the texture indicated by
|
* constraintRect (without consideration of filter
|
* width, just the raw coords).
|
* @param filterOrNullForBicubic If non-null indicates the filter mode. If null means
|
* use bicubic filtering.
|
**/
|
virtual std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
const SkMatrix& textureMatrix,
|
const SkRect& constraintRect,
|
FilterConstraint filterConstraint,
|
bool coordsLimitedToConstraintRect,
|
const GrSamplerState::Filter* filterOrNullForBicubic) = 0;
|
|
/**
|
* Returns a texture that is safe for use with the params.
|
*
|
* If the size of the returned texture does not match width()/height() then the contents of the
|
* original may have been scaled to fit the texture or the original may have been copied into
|
* a subrect of the copy. 'scaleAdjust' must be applied to the normalized texture coordinates
|
* in order to correct for the latter case.
|
*
|
* If the GrSamplerState is known to clamp and use kNearest or kBilerp filter mode then the
|
* proxy will always be unscaled and nullptr can be passed for scaleAdjust. There is a weird
|
* contract that if scaleAdjust is not null it must be initialized to {1, 1} before calling
|
* this method. (TODO: Fix this and make this function always initialize scaleAdjust).
|
*/
|
sk_sp<GrTextureProxy> refTextureProxyForParams(const GrSamplerState&,
|
SkScalar scaleAdjust[2]);
|
|
sk_sp<GrTextureProxy> refTextureProxyForParams(GrSamplerState::Filter filter,
|
SkScalar scaleAdjust[2]) {
|
return this->refTextureProxyForParams(
|
GrSamplerState(GrSamplerState::WrapMode::kClamp, filter), scaleAdjust);
|
}
|
|
/**
|
* Returns a texture. If willNeedMips is true then the returned texture is guaranteed to have
|
* allocated mip map levels. This can be a performance win if future draws with the texture
|
* require mip maps.
|
*/
|
// TODO: Once we remove support for npot textures, we should add a flag for must support repeat
|
// wrap mode. To support that flag now would require us to support scaleAdjust array like in
|
// refTextureProxyForParams, however the current public API that uses this call does not expose
|
// that array.
|
sk_sp<GrTextureProxy> refTextureProxy(GrMipMapped willNeedMips);
|
|
virtual ~GrTextureProducer() {}
|
|
int width() const { return fWidth; }
|
int height() const { return fHeight; }
|
bool isAlphaOnly() const { return fIsAlphaOnly; }
|
virtual SkAlphaType alphaType() const = 0;
|
virtual SkColorSpace* colorSpace() const = 0;
|
virtual SkColorSpace* targetColorSpace() const { return nullptr; }
|
|
protected:
|
friend class GrTextureProducer_TestAccess;
|
|
GrTextureProducer(GrContext* context, int width, int height, bool isAlphaOnly)
|
: fContext(context)
|
, fWidth(width)
|
, fHeight(height)
|
, fIsAlphaOnly(isAlphaOnly) {}
|
|
/** Helper for creating a key for a copy from an original key. */
|
static void MakeCopyKeyFromOrigKey(const GrUniqueKey& origKey,
|
const CopyParams& copyParams,
|
GrUniqueKey* copyKey) {
|
SkASSERT(!copyKey->isValid());
|
if (origKey.isValid()) {
|
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
|
builder[0] = static_cast<uint32_t>(copyParams.fFilter);
|
builder[1] = copyParams.fWidth;
|
builder[2] = copyParams.fHeight;
|
}
|
}
|
|
/**
|
* If we need to make a copy in order to be compatible with GrTextureParams producer is asked to
|
* return a key that identifies its original content + the CopyParms parameter. If the producer
|
* does not want to cache the stretched version (e.g. the producer is volatile), this should
|
* simply return without initializing the copyKey. If the texture generated by this producer
|
* depends on the destination color space, then that information should also be incorporated
|
* in the key.
|
*/
|
virtual void makeCopyKey(const CopyParams&, GrUniqueKey* copyKey) = 0;
|
|
/**
|
* If a stretched version of the texture is generated, it may be cached (assuming that
|
* makeCopyKey() returns true). In that case, the maker is notified in case it
|
* wants to note that for when the maker is destroyed.
|
*/
|
virtual void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) = 0;
|
|
enum DomainMode {
|
kNoDomain_DomainMode,
|
kDomain_DomainMode,
|
kTightCopy_DomainMode
|
};
|
|
static sk_sp<GrTextureProxy> CopyOnGpu(GrContext*, sk_sp<GrTextureProxy> inputProxy,
|
const CopyParams& copyParams,
|
bool dstWillRequireMipMaps);
|
|
static DomainMode DetermineDomainMode(const SkRect& constraintRect,
|
FilterConstraint filterConstraint,
|
bool coordsLimitedToConstraintRect,
|
GrTextureProxy*,
|
const GrSamplerState::Filter* filterModeOrNullForBicubic,
|
SkRect* domainRect);
|
|
static std::unique_ptr<GrFragmentProcessor> CreateFragmentProcessorForDomainAndFilter(
|
sk_sp<GrTextureProxy> proxy,
|
const SkMatrix& textureMatrix,
|
DomainMode,
|
const SkRect& domain,
|
const GrSamplerState::Filter* filterOrNullForBicubic);
|
|
GrContext* fContext;
|
|
private:
|
virtual sk_sp<GrTextureProxy> onRefTextureProxyForParams(const GrSamplerState&,
|
bool willBeMipped,
|
SkScalar scaleAdjust[2]) = 0;
|
|
const int fWidth;
|
const int fHeight;
|
const bool fIsAlphaOnly;
|
|
typedef SkNoncopyable INHERITED;
|
};
|
|
#endif
|