Revert "Remove copies for wrap modes in GrTextureProducer."
This reverts commit 7fba244ea9
.
Reason for revert: See if this is blocking the Chrome roll
Original change's description:
> Remove copies for wrap modes in GrTextureProducer.
>
> GrTextureEffect now supports implementing wrap modes in shaders
> for subsets and texture types with HW sampling restrictions.
>
> Change-Id: I5c93ade044465e13c5f56f7437fbbe288db0a8a8
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/271056
> Reviewed-by: Greg Daniel <egdaniel@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>
TBR=egdaniel@google.com,bsalomon@google.com
Change-Id: I14397bec8ff4ba165c28faa8f44497f47d865862
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272522
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
392846665c
commit
bf5cb0f539
@ -273,8 +273,8 @@ protected:
|
||||
}
|
||||
|
||||
static void draw_as_tex(SkCanvas* canvas, SkImage* image, SkScalar x, SkScalar y) {
|
||||
GrSurfaceProxyView view =
|
||||
as_IB(image)->refView(canvas->getGrContext(), GrSamplerState::Filter::kBilerp);
|
||||
GrSurfaceProxyView view = as_IB(image)->refView(canvas->getGrContext(),
|
||||
GrSamplerState::Filter::kBilerp, nullptr);
|
||||
if (!view) {
|
||||
// show placeholder if we have no texture
|
||||
SkPaint paint;
|
||||
|
@ -122,14 +122,13 @@ GrSurfaceProxyView GrBitmapTextureMaker::refOriginalTextureProxyView(bool willBe
|
||||
return {};
|
||||
}
|
||||
|
||||
void GrBitmapTextureMaker::makeMipMappedKey(GrUniqueKey* mipMappedKey) {
|
||||
void GrBitmapTextureMaker::makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) {
|
||||
// Destination color space is irrelevant - we always upload the bitmap's contents as-is
|
||||
if (fOriginalKey.isValid()) {
|
||||
MakeMipMappedKeyFromOriginalKey(fOriginalKey, mipMappedKey);
|
||||
MakeCopyKeyFromOrigKey(fOriginalKey, copyParams, copyKey);
|
||||
}
|
||||
}
|
||||
|
||||
void GrBitmapTextureMaker::didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey,
|
||||
uint32_t contextUniqueID) {
|
||||
GrInstallBitmapUniqueKeyInvalidator(mipMappedKey, contextUniqueID, fBitmap.pixelRef());
|
||||
void GrBitmapTextureMaker::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
|
||||
GrInstallBitmapUniqueKeyInvalidator(copyKey, contextUniqueID, fBitmap.pixelRef());
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ private:
|
||||
GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
|
||||
AllowedTexGenType onlyIfFast) override;
|
||||
|
||||
void makeMipMappedKey(GrUniqueKey* mipMappedKey) override;
|
||||
void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey, uint32_t contextUniqueID) override;
|
||||
void makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) override;
|
||||
void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override;
|
||||
|
||||
const SkBitmap fBitmap;
|
||||
const SkBackingFit fFit;
|
||||
|
@ -45,14 +45,61 @@ void GrGpu::disconnect(DisconnectType) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrGpu::IsACopyNeededForMips(const GrCaps* caps, const GrTextureProxy* texProxy,
|
||||
GrSamplerState::Filter filter) {
|
||||
SkASSERT(texProxy);
|
||||
if (filter != GrSamplerState::Filter::kMipMap || texProxy->mipMapped() == GrMipMapped::kYes ||
|
||||
!caps->mipMapSupport()) {
|
||||
return false;
|
||||
bool GrGpu::IsACopyNeededForRepeatWrapMode(const GrCaps* caps,
|
||||
GrTextureProxy* texProxy,
|
||||
SkISize dimensions,
|
||||
GrSamplerState::Filter filter,
|
||||
GrTextureProducer::CopyParams* copyParams,
|
||||
SkScalar scaleAdjust[2]) {
|
||||
if (!caps->npotTextureTileSupport() &&
|
||||
(!SkIsPow2(dimensions.width()) || !SkIsPow2(dimensions.height()))) {
|
||||
SkASSERT(scaleAdjust);
|
||||
copyParams->fDimensions = {SkNextPow2(dimensions.width()), SkNextPow2(dimensions.height())};
|
||||
SkASSERT(scaleAdjust);
|
||||
scaleAdjust[0] = ((SkScalar)copyParams->fDimensions.width()) / dimensions.width();
|
||||
scaleAdjust[1] = ((SkScalar)copyParams->fDimensions.height()) / dimensions.height();
|
||||
switch (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 SkMipMap::ComputeLevelCount(texProxy->width(), texProxy->height()) > 0;
|
||||
|
||||
if (texProxy) {
|
||||
// If the texture format itself doesn't support repeat wrap mode or mipmapping (and
|
||||
// those capabilities are required) force a copy.
|
||||
if (texProxy->hasRestrictedSampling()) {
|
||||
copyParams->fFilter = GrSamplerState::Filter::kNearest;
|
||||
copyParams->fDimensions = texProxy->dimensions();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GrGpu::IsACopyNeededForMips(const GrCaps* caps, const GrTextureProxy* texProxy,
|
||||
GrSamplerState::Filter filter,
|
||||
GrTextureProducer::CopyParams* copyParams) {
|
||||
SkASSERT(texProxy);
|
||||
int mipCount = SkMipMap::ComputeLevelCount(texProxy->width(), texProxy->height());
|
||||
bool willNeedMips = GrSamplerState::Filter::kMipMap == filter && caps->mipMapSupport() &&
|
||||
mipCount;
|
||||
// If the texture format itself doesn't support mipmapping (and those capabilities are required)
|
||||
// force a copy.
|
||||
if (willNeedMips && texProxy->mipMapped() == GrMipMapped::kNo) {
|
||||
copyParams->fFilter = GrSamplerState::Filter::kNearest;
|
||||
copyParams->fDimensions = texProxy->dimensions();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool validate_texel_levels(SkISize dimensions, GrColorType texelColorType,
|
||||
|
@ -594,12 +594,22 @@ public:
|
||||
virtual GrStencilAttachment* createStencilAttachmentForRenderTarget(
|
||||
const GrRenderTarget*, int width, int height, int numStencilSamples) = 0;
|
||||
|
||||
// Determines whether a texture will need to be rescaled in order to be used with the
|
||||
// GrSamplerState.
|
||||
static bool IsACopyNeededForRepeatWrapMode(const GrCaps*,
|
||||
GrTextureProxy* texProxy,
|
||||
SkISize dimensions,
|
||||
GrSamplerState::Filter,
|
||||
GrTextureProducer::CopyParams*,
|
||||
SkScalar scaleAdjust[2]);
|
||||
|
||||
// Determines whether a texture will need to be copied because the draw requires mips but the
|
||||
// texutre doesn't have any. This call should be only checked if IsACopyNeededForTextureParams
|
||||
// fails. If the previous call succeeds, then a copy should be done using those params and the
|
||||
// mip mapping requirements will be handled there.
|
||||
static bool IsACopyNeededForMips(const GrCaps* caps, const GrTextureProxy* texProxy,
|
||||
GrSamplerState::Filter filter);
|
||||
GrSamplerState::Filter filter,
|
||||
GrTextureProducer::CopyParams* copyParams);
|
||||
|
||||
void handleDirtyContext() {
|
||||
if (fResetBits) {
|
||||
|
@ -39,14 +39,15 @@ GrSurfaceProxyView GrImageTextureMaker::refOriginalTextureProxyView(bool willBeM
|
||||
onlyIfFast);
|
||||
}
|
||||
|
||||
void GrImageTextureMaker::makeMipMappedKey(GrUniqueKey* mipMappedKey) {
|
||||
void GrImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) {
|
||||
if (fOriginalKey.isValid() && SkImage::kAllow_CachingHint == fCachingHint) {
|
||||
GrUniqueKey cacheKey;
|
||||
fImage->makeCacheKeyFromOrigKey(fOriginalKey, &cacheKey);
|
||||
MakeMipMappedKeyFromOriginalKey(cacheKey, mipMappedKey);
|
||||
MakeCopyKeyFromOrigKey(cacheKey, stretch, paramsCopyKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrContext* context, const SkImage* client,
|
||||
@ -74,13 +75,13 @@ GrSurfaceProxyView GrYUVAImageTextureMaker::refOriginalTextureProxyView(
|
||||
}
|
||||
}
|
||||
|
||||
void GrYUVAImageTextureMaker::makeMipMappedKey(GrUniqueKey* mipMappedKey) {
|
||||
void GrYUVAImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) {
|
||||
// TODO: Do we ever want to disable caching?
|
||||
if (fOriginalKey.isValid()) {
|
||||
GrUniqueKey cacheKey;
|
||||
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
||||
GrUniqueKey::Builder builder(&cacheKey, fOriginalKey, kDomain, 0, "Image");
|
||||
MakeMipMappedKeyFromOriginalKey(cacheKey, mipMappedKey);
|
||||
MakeCopyKeyFromOrigKey(cacheKey, stretch, paramsCopyKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,12 +22,14 @@ public:
|
||||
SkImage::CachingHint chint, bool useDecal = false);
|
||||
|
||||
private:
|
||||
// TODO: consider overriding this, for the case where the underlying generator might be
|
||||
// able to efficiently produce a "stretched" texture natively (e.g. picture-backed)
|
||||
// GrTexture* generateTextureForParams(const CopyParams&) override;
|
||||
GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
|
||||
AllowedTexGenType onlyIfFast) override;
|
||||
|
||||
void makeMipMappedKey(GrUniqueKey* mipMappedKey) override;
|
||||
void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey, uint32_t contextUniqueID) override {
|
||||
}
|
||||
void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override;
|
||||
void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override {}
|
||||
|
||||
const SkImage_Lazy* fImage;
|
||||
GrUniqueKey fOriginalKey;
|
||||
@ -51,9 +53,8 @@ protected:
|
||||
GrSurfaceProxyView refOriginalTextureProxyView(bool willBeMipped,
|
||||
AllowedTexGenType onlyIfFast) override;
|
||||
|
||||
void makeMipMappedKey(GrUniqueKey* mipMappedKey) override;
|
||||
void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey, uint32_t contextUniqueID) override {
|
||||
}
|
||||
void makeCopyKey(const CopyParams& stretch, GrUniqueKey* paramsCopyKey) override;
|
||||
void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override {}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> createFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
|
@ -22,47 +22,65 @@ GrTextureAdjuster::GrTextureAdjuster(GrRecordingContext* context,
|
||||
, fOriginal(std::move(original))
|
||||
, fUniqueID(uniqueID) {}
|
||||
|
||||
void GrTextureAdjuster::makeMipMappedKey(GrUniqueKey* mipMappedKey) {
|
||||
void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) {
|
||||
// Destination color space is irrelevant - we already have a texture so we're just sub-setting
|
||||
GrUniqueKey baseKey;
|
||||
GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeSize(this->dimensions()));
|
||||
MakeMipMappedKeyFromOriginalKey(baseKey, mipMappedKey);
|
||||
MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
|
||||
}
|
||||
|
||||
void GrTextureAdjuster::didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey,
|
||||
uint32_t contextUniqueID) {
|
||||
void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
|
||||
// We don't currently have a mechanism for notifications on Images!
|
||||
}
|
||||
|
||||
GrSurfaceProxyView GrTextureAdjuster::makeMippedCopy() {
|
||||
GrSurfaceProxyView GrTextureAdjuster::copy(const CopyParams& copyParams, bool willBeMipped,
|
||||
bool copyForMipsOnly) {
|
||||
GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
|
||||
|
||||
GrUniqueKey key;
|
||||
this->makeMipMappedKey(&key);
|
||||
this->makeCopyKey(copyParams, &key);
|
||||
sk_sp<GrTextureProxy> cachedCopy;
|
||||
const GrSurfaceProxyView& originalView = this->originalProxyView();
|
||||
if (key.isValid()) {
|
||||
cachedCopy = proxyProvider->findOrCreateProxyByUniqueKey(key, this->colorType());
|
||||
if (cachedCopy) {
|
||||
return {std::move(cachedCopy), originalView.origin(), originalView.swizzle()};
|
||||
if (cachedCopy && (!willBeMipped || GrMipMapped::kYes == cachedCopy->mipMapped())) {
|
||||
// TODO: Once we no longer use CopyOnGpu which can fallback to arbitrary formats and
|
||||
// colorTypes, we can use the swizzle of the originalView.
|
||||
GrSwizzle swizzle = cachedCopy->textureSwizzleDoNotUse();
|
||||
return GrSurfaceProxyView(std::move(cachedCopy), originalView.origin(), swizzle);
|
||||
}
|
||||
}
|
||||
|
||||
GrSurfaceProxyView copyView = GrCopyBaseMipMapToTextureProxy(
|
||||
this->context(), originalView.proxy(), originalView.origin(), this->colorType());
|
||||
if (!copyView) {
|
||||
return {};
|
||||
GrSurfaceProxyView copyView;
|
||||
if (copyForMipsOnly) {
|
||||
copyView = GrCopyBaseMipMapToTextureProxy(this->context(), originalView.proxy(),
|
||||
originalView.origin(), this->colorType());
|
||||
} else {
|
||||
copyView = CopyOnGpu(this->context(), this->originalProxyViewRef(), this->colorType(),
|
||||
copyParams, willBeMipped);
|
||||
}
|
||||
if (key.isValid()) {
|
||||
SkASSERT(copyView.origin() == originalView.origin());
|
||||
proxyProvider->assignUniqueKeyToProxy(key, copyView.asTextureProxy());
|
||||
this->didCacheMipMappedCopy(key, proxyProvider->contextID());
|
||||
if (copyView.proxy()) {
|
||||
if (key.isValid()) {
|
||||
SkASSERT(copyView.origin() == originalView.origin());
|
||||
if (cachedCopy) {
|
||||
SkASSERT(GrMipMapped::kYes == copyView.asTextureProxy()->mipMapped() &&
|
||||
GrMipMapped::kNo == cachedCopy->mipMapped());
|
||||
// If we had a cachedProxy, that means there already is a proxy in the cache which
|
||||
// matches the key, but it does not have mip levels and we require them. Thus we
|
||||
// must remove the unique key from that proxy.
|
||||
SkASSERT(cachedCopy->getUniqueKey() == key);
|
||||
proxyProvider->removeUniqueKeyFromProxy(cachedCopy.get());
|
||||
}
|
||||
proxyProvider->assignUniqueKeyToProxy(key, copyView.asTextureProxy());
|
||||
this->didCacheCopy(key, proxyProvider->contextID());
|
||||
}
|
||||
}
|
||||
return copyView;
|
||||
}
|
||||
|
||||
GrSurfaceProxyView GrTextureAdjuster::onRefTextureProxyViewForParams(GrSamplerState params,
|
||||
bool willBeMipped) {
|
||||
bool willBeMipped,
|
||||
SkScalar scaleAdjust[2]) {
|
||||
if (this->context()->priv().abandoned()) {
|
||||
// The texture was abandoned.
|
||||
return {};
|
||||
@ -74,32 +92,51 @@ GrSurfaceProxyView GrTextureAdjuster::onRefTextureProxyViewForParams(GrSamplerSt
|
||||
GrSurfaceProxyView view = this->originalProxyViewRef();
|
||||
GrTextureProxy* texProxy = view.asTextureProxy();
|
||||
SkASSERT(texProxy);
|
||||
if (!GrGpu::IsACopyNeededForMips(this->context()->priv().caps(), texProxy, params.filter())) {
|
||||
return view;
|
||||
CopyParams copyParams;
|
||||
|
||||
bool needsCopyForMipsOnly = false;
|
||||
if (!params.isRepeated() ||
|
||||
!GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), texProxy,
|
||||
texProxy->dimensions(), params.filter(), ©Params,
|
||||
scaleAdjust)) {
|
||||
needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
|
||||
texProxy, params.filter(),
|
||||
©Params);
|
||||
if (!needsCopyForMipsOnly) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
GrSurfaceProxyView copy = this->makeMippedCopy();
|
||||
if (!copy) {
|
||||
GrSurfaceProxyView result = this->copy(copyParams, willBeMipped, needsCopyForMipsOnly);
|
||||
if (!result.proxy() && needsCopyForMipsOnly) {
|
||||
// If we were unable to make a copy and we only needed a copy for mips, then we will return
|
||||
// the source texture here and require that the GPU backend is able to fall back to using
|
||||
// bilerp if mips are required.
|
||||
return view;
|
||||
}
|
||||
SkASSERT(copy.asTextureProxy());
|
||||
return copy;
|
||||
SkASSERT(result.asTextureProxy());
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
|
||||
const SkMatrix& textureMatrix,
|
||||
const SkMatrix& origTextureMatrix,
|
||||
const SkRect& constraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
bool coordsLimitedToConstraintRect,
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
||||
GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic);
|
||||
if (!view) {
|
||||
SkMatrix textureMatrix = origTextureMatrix;
|
||||
|
||||
SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
|
||||
GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic, scaleAdjust);
|
||||
if (!view.proxy()) {
|
||||
return nullptr;
|
||||
}
|
||||
SkASSERT(view.asTextureProxy());
|
||||
// If we made a copy then we only copied the contentArea, in which case the new texture is all
|
||||
// content.
|
||||
if (view.proxy() != this->originalProxyView().proxy()) {
|
||||
textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
|
||||
}
|
||||
|
||||
SkRect domain;
|
||||
DomainMode domainMode =
|
||||
|
@ -33,16 +33,17 @@ public:
|
||||
uint32_t uniqueID, bool useDecal = false);
|
||||
|
||||
protected:
|
||||
void makeMipMappedKey(GrUniqueKey* mipMappedKey) override;
|
||||
void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey, uint32_t contextUniqueID) override;
|
||||
void makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) override;
|
||||
void didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) override;
|
||||
|
||||
const GrSurfaceProxyView& originalProxyView() const { return fOriginal; }
|
||||
GrSurfaceProxyView originalProxyViewRef() const { return fOriginal; }
|
||||
|
||||
private:
|
||||
GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped) override;
|
||||
GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped,
|
||||
SkScalar scaleAdjust[2]) override;
|
||||
|
||||
GrSurfaceProxyView makeMippedCopy();
|
||||
GrSurfaceProxyView copy(const CopyParams& copyParams, bool willBeMipped, bool copyOnlyForMips);
|
||||
|
||||
GrSurfaceProxyView fOriginal;
|
||||
uint32_t fUniqueID;
|
||||
|
@ -14,66 +14,102 @@
|
||||
#include "src/gpu/GrRecordingContextPriv.h"
|
||||
|
||||
GrSurfaceProxyView GrTextureMaker::onRefTextureProxyViewForParams(GrSamplerState params,
|
||||
bool willBeMipped) {
|
||||
bool willBeMipped,
|
||||
SkScalar scaleAdjust[2]) {
|
||||
if (this->width() > this->context()->priv().caps()->maxTextureSize() ||
|
||||
this->height() > this->context()->priv().caps()->maxTextureSize()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
CopyParams copyParams;
|
||||
|
||||
GrSurfaceProxyView original = this->refOriginalTextureProxyView(willBeMipped,
|
||||
AllowedTexGenType::kCheap);
|
||||
if (!original) {
|
||||
return this->refOriginalTextureProxyView(willBeMipped, AllowedTexGenType::kAny);
|
||||
}
|
||||
|
||||
GrTextureProxy* texProxy = original.asTextureProxy();
|
||||
if (!GrGpu::IsACopyNeededForMips(this->context()->priv().caps(), texProxy, params.filter())) {
|
||||
return original;
|
||||
bool needsCopyForMipsOnly = false;
|
||||
if (original.proxy()) {
|
||||
GrTextureProxy* texProxy = original.asTextureProxy();
|
||||
SkASSERT(texProxy);
|
||||
if (!params.isRepeated() ||
|
||||
!GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), texProxy,
|
||||
texProxy->dimensions(), params.filter(),
|
||||
©Params, scaleAdjust)) {
|
||||
needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
|
||||
texProxy, params.filter(),
|
||||
©Params);
|
||||
if (!needsCopyForMipsOnly) {
|
||||
return original;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!params.isRepeated() ||
|
||||
!GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), nullptr,
|
||||
this->dimensions(), params.filter(), ©Params,
|
||||
scaleAdjust)) {
|
||||
return this->refOriginalTextureProxyView(willBeMipped, AllowedTexGenType::kAny);
|
||||
}
|
||||
}
|
||||
|
||||
GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
|
||||
|
||||
GrSurfaceOrigin origOrigin = original.proxy() ? original.origin() : kTopLeft_GrSurfaceOrigin;
|
||||
GrUniqueKey mipMappedKey;
|
||||
this->makeMipMappedKey(&mipMappedKey);
|
||||
if (mipMappedKey.isValid()) {
|
||||
auto cachedProxy =
|
||||
proxyProvider->findOrCreateProxyByUniqueKey(mipMappedKey, this->colorType());
|
||||
GrUniqueKey copyKey;
|
||||
this->makeCopyKey(copyParams, ©Key);
|
||||
GrSurfaceProxyView cachedView;
|
||||
if (copyKey.isValid()) {
|
||||
auto cachedProxy = proxyProvider->findOrCreateProxyByUniqueKey(copyKey, this->colorType());
|
||||
if (cachedProxy) {
|
||||
SkASSERT(cachedProxy->mipMapped() == GrMipMapped::kYes);
|
||||
// TODO: Once we no longer use MakeMipMappedCopy which can fallback to arbitrary formats
|
||||
// and colorTypes, we can use the swizzle of the originalView.
|
||||
GrMipMapped mipped = cachedProxy->mipMapped();
|
||||
// TODO: Once we no longer use CopyOnGpu which can fallback to arbitrary formats and
|
||||
// colorTypes, we can use the swizzle of the originalView.
|
||||
GrSwizzle swizzle = cachedProxy->textureSwizzleDoNotUse();
|
||||
return GrSurfaceProxyView(std::move(cachedProxy), origOrigin, swizzle);
|
||||
cachedView = GrSurfaceProxyView(std::move(cachedProxy), origOrigin, swizzle);
|
||||
if (!willBeMipped || GrMipMapped::kYes == mipped) {
|
||||
return cachedView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GrSurfaceProxyView source;
|
||||
if (original) {
|
||||
if (original.proxy()) {
|
||||
source = std::move(original);
|
||||
} else if (cachedView.proxy()) {
|
||||
source = cachedView;
|
||||
} else {
|
||||
// Since we will be copying this texture there is no reason to make it mipped
|
||||
source = this->refOriginalTextureProxyView(false, AllowedTexGenType::kAny);
|
||||
if (!source) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (!source.proxy()) {
|
||||
return {};
|
||||
}
|
||||
SkASSERT(source.asTextureProxy());
|
||||
|
||||
GrSurfaceProxyView result = MakeMipMappedCopy(this->context(), source, this->colorType());
|
||||
GrSurfaceProxyView result =
|
||||
CopyOnGpu(this->context(), source, this->colorType(), copyParams, willBeMipped);
|
||||
|
||||
if (!result) {
|
||||
if (!result.proxy()) {
|
||||
// If we were unable to make a copy and we only needed a copy for mips, then we will return
|
||||
// the source texture here and require that the GPU backend is able to fall back to using
|
||||
// bilerp if mips are required.
|
||||
return source;
|
||||
if (needsCopyForMipsOnly) {
|
||||
return source;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
if (mipMappedKey.isValid()) {
|
||||
if (copyKey.isValid()) {
|
||||
SkASSERT(result.origin() == origOrigin);
|
||||
proxyProvider->assignUniqueKeyToProxy(mipMappedKey, result.asTextureProxy());
|
||||
this->didCacheMipMappedCopy(mipMappedKey, proxyProvider->contextID());
|
||||
if (cachedView.proxy()) {
|
||||
SkASSERT(GrMipMapped::kYes == result.asTextureProxy()->mipMapped() &&
|
||||
GrMipMapped::kNo == cachedView.asTextureProxy()->mipMapped());
|
||||
// If we had a cachedProxy, that means there already is a proxy in the cache which
|
||||
// matches the key, but it does not have mip levels and we require them. Thus we must
|
||||
// remove the unique key from that proxy.
|
||||
SkASSERT(cachedView.asTextureProxy()->getUniqueKey() == copyKey);
|
||||
proxyProvider->removeUniqueKeyFromProxy(cachedView.asTextureProxy());
|
||||
}
|
||||
proxyProvider->assignUniqueKeyToProxy(copyKey, result.asTextureProxy());
|
||||
this->didCacheCopy(copyKey, proxyProvider->contextID());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -96,10 +132,13 @@ std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
|
||||
fmForDetermineDomain = &kBilerp;
|
||||
}
|
||||
|
||||
GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic);
|
||||
if (!view) {
|
||||
SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
|
||||
GrSurfaceProxyView view = this->viewForParams(filterOrNullForBicubic, scaleAdjust);
|
||||
if (!view.proxy()) {
|
||||
return nullptr;
|
||||
}
|
||||
SkMatrix adjustedMatrix = textureMatrix;
|
||||
adjustedMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
|
||||
|
||||
SkRect domain;
|
||||
DomainMode domainMode =
|
||||
@ -107,5 +146,5 @@ std::unique_ptr<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
|
||||
view.proxy(), fmForDetermineDomain, &domain);
|
||||
SkASSERT(kTightCopy_DomainMode != domainMode);
|
||||
return this->createFragmentProcessorForDomainAndFilter(
|
||||
std::move(view), textureMatrix, domainMode, domain, filterOrNullForBicubic);
|
||||
std::move(view), adjustedMatrix, domainMode, domain, filterOrNullForBicubic);
|
||||
}
|
||||
|
@ -40,7 +40,9 @@ protected:
|
||||
AllowedTexGenType genType) = 0;
|
||||
|
||||
private:
|
||||
GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped) override;
|
||||
GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState,
|
||||
bool willBeMipped,
|
||||
SkScalar scaleAdjust[2]) override;
|
||||
|
||||
typedef GrTextureProducer INHERITED;
|
||||
};
|
||||
|
@ -21,35 +21,53 @@
|
||||
#include "src/gpu/effects/GrTextureDomain.h"
|
||||
#include "src/gpu/effects/GrTextureEffect.h"
|
||||
|
||||
GrSurfaceProxyView GrTextureProducer::MakeMipMappedCopy(GrRecordingContext* context,
|
||||
GrSurfaceProxyView inputView,
|
||||
GrColorType colorType) {
|
||||
GrSurfaceProxyView GrTextureProducer::CopyOnGpu(GrRecordingContext* context,
|
||||
GrSurfaceProxyView inputView,
|
||||
GrColorType colorType,
|
||||
const CopyParams& copyParams,
|
||||
bool dstWillRequireMipMaps) {
|
||||
SkASSERT(context);
|
||||
SkASSERT(inputView.asTextureProxy());
|
||||
|
||||
GrSurfaceProxy* proxy = inputView.proxy();
|
||||
SkRect proxyRect = proxy->getBoundsRect();
|
||||
const SkRect dstRect = SkRect::Make(copyParams.fDimensions);
|
||||
GrMipMapped mipMapped = dstWillRequireMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
|
||||
|
||||
GrSurfaceProxyView view =
|
||||
GrCopyBaseMipMapToTextureProxy(context, proxy, inputView.origin(), colorType);
|
||||
if (view) {
|
||||
return view;
|
||||
GrSurfaceProxy* proxy = inputView.proxy();
|
||||
SkRect localRect = proxy->getBoundsRect();
|
||||
|
||||
bool resizing = false;
|
||||
if (copyParams.fFilter != GrSamplerState::Filter::kNearest) {
|
||||
resizing = localRect.width() != dstRect.width() || localRect.height() != dstRect.height();
|
||||
}
|
||||
|
||||
if (copyParams.fFilter == GrSamplerState::Filter::kNearest && !resizing &&
|
||||
dstWillRequireMipMaps) {
|
||||
GrSurfaceProxyView view = GrCopyBaseMipMapToTextureProxy(context, proxy, inputView.origin(),
|
||||
colorType);
|
||||
if (view.proxy()) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
auto copyRTC = GrRenderTargetContext::MakeWithFallback(
|
||||
context, colorType, nullptr, SkBackingFit::kExact, inputView.dimensions(), 1,
|
||||
GrMipMapped::kYes, proxy->isProtected(), inputView.origin());
|
||||
context, colorType, nullptr, SkBackingFit::kExact, copyParams.fDimensions, 1,
|
||||
mipMapped, proxy->isProtected(), inputView.origin());
|
||||
if (!copyRTC) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto& caps = *context->priv().caps();
|
||||
GrPaint paint;
|
||||
auto fp = GrTextureEffect::Make(std::move(inputView), kUnknown_SkAlphaType, SkMatrix::I(),
|
||||
GrSamplerState::Filter::kNearest);
|
||||
|
||||
GrSamplerState sampler(GrSamplerState::WrapMode::kClamp, copyParams.fFilter);
|
||||
auto boundsRect = SkRect::Make(proxy->dimensions());
|
||||
auto fp = GrTextureEffect::MakeSubset(std::move(inputView), kUnknown_SkAlphaType, SkMatrix::I(),
|
||||
sampler, boundsRect, localRect, caps);
|
||||
paint.addColorFragmentProcessor(std::move(fp));
|
||||
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
|
||||
|
||||
copyRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), proxyRect);
|
||||
copyRTC->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
|
||||
localRect);
|
||||
return copyRTC->readSurfaceView();
|
||||
}
|
||||
|
||||
@ -200,7 +218,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorF
|
||||
}
|
||||
|
||||
GrSurfaceProxyView GrTextureProducer::viewForParams(
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic) {
|
||||
const GrSamplerState::Filter* filterOrNullForBicubic, SkScalar scaleAdjust[2]) {
|
||||
GrSamplerState sampler; // Default is nearest + clamp
|
||||
if (filterOrNullForBicubic) {
|
||||
sampler.setFilterMode(*filterOrNullForBicubic);
|
||||
@ -212,29 +230,36 @@ GrSurfaceProxyView GrTextureProducer::viewForParams(
|
||||
sampler.setWrapModeY(GrSamplerState::WrapMode::kClampToBorder);
|
||||
}
|
||||
}
|
||||
return this->viewForParams(sampler);
|
||||
return this->viewForParams(sampler, scaleAdjust);
|
||||
}
|
||||
|
||||
GrSurfaceProxyView GrTextureProducer::viewForParams(GrSamplerState sampler) {
|
||||
GrSurfaceProxyView GrTextureProducer::viewForParams(GrSamplerState sampler,
|
||||
SkScalar scaleAdjust[2]) {
|
||||
// Check that the caller pre-initialized scaleAdjust
|
||||
SkASSERT(!scaleAdjust || (scaleAdjust[0] == 1 && scaleAdjust[1] == 1));
|
||||
|
||||
const GrCaps* caps = this->context()->priv().caps();
|
||||
|
||||
int mipCount = SkMipMap::ComputeLevelCount(this->width(), this->height());
|
||||
bool willBeMipped = GrSamplerState::Filter::kMipMap == sampler.filter() && mipCount &&
|
||||
caps->mipMapSupport();
|
||||
|
||||
auto result = this->onRefTextureProxyViewForParams(sampler, willBeMipped);
|
||||
if (!result) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SkASSERT(result.asTextureProxy());
|
||||
auto result = this->onRefTextureProxyViewForParams(sampler, 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(!willBeMipped || result.asTextureProxy()->mipMapped() == GrMipMapped::kYes ||
|
||||
SkASSERT(!result.proxy() || !willBeMipped ||
|
||||
result.asTextureProxy()->mipMapped() == GrMipMapped::kYes ||
|
||||
!caps->isFormatCopyable(result.proxy()->backendFormat()));
|
||||
|
||||
SkASSERT(result.proxy()->dimensions() == this->dimensions());
|
||||
SkASSERT(!result.proxy() || result.asTextureProxy());
|
||||
|
||||
SkDEBUGCODE(bool expectNoScale = (sampler.filter() != GrSamplerState::Filter::kMipMap &&
|
||||
!sampler.isRepeated()));
|
||||
// Check that the "no scaling expected" case always returns a proxy of the same size as the
|
||||
// producer.
|
||||
SkASSERT(!result.proxy() || !expectNoScale ||
|
||||
result.proxy()->dimensions() == this->dimensions());
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -245,7 +270,7 @@ std::pair<GrSurfaceProxyView, GrColorType> GrTextureProducer::view(GrMipMapped w
|
||||
: GrSamplerState::Filter::kMipMap;
|
||||
GrSamplerState sampler(GrSamplerState::WrapMode::kClamp, filter);
|
||||
|
||||
auto result = this->viewForParams(sampler);
|
||||
auto result = this->viewForParams(sampler, nullptr);
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
const GrCaps* caps = this->context()->priv().caps();
|
||||
|
@ -32,6 +32,11 @@ struct SkRect;
|
||||
*/
|
||||
class GrTextureProducer : public SkNoncopyable {
|
||||
public:
|
||||
struct CopyParams {
|
||||
GrSamplerState::Filter fFilter;
|
||||
SkISize fDimensions;
|
||||
};
|
||||
|
||||
enum FilterConstraint {
|
||||
kYes_FilterConstraint,
|
||||
kNo_FilterConstraint,
|
||||
@ -66,10 +71,21 @@ public:
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
GrSurfaceProxyView viewForParams(GrSamplerState);
|
||||
GrSurfaceProxyView viewForParams(GrSamplerState, SkScalar scaleAdjust[2]);
|
||||
|
||||
GrSurfaceProxyView viewForParams(const GrSamplerState::Filter* filterOrNullForBicubic);
|
||||
GrSurfaceProxyView viewForParams(const GrSamplerState::Filter* filterOrNullForBicubic,
|
||||
SkScalar scaleAdjust[2]);
|
||||
|
||||
/**
|
||||
* Returns a texture. If willNeedMips is true then the returned texture is guaranteed to have
|
||||
@ -105,29 +121,35 @@ protected:
|
||||
GrColorType colorType() const { return fImageInfo.colorType(); }
|
||||
|
||||
/** Helper for creating a key for a copy from an original key. */
|
||||
static void MakeMipMappedKeyFromOriginalKey(const GrUniqueKey& origKey,
|
||||
GrUniqueKey* mipMappedKey) {
|
||||
SkASSERT(!mipMappedKey->isValid());
|
||||
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(mipMappedKey, origKey, kDomain, 0);
|
||||
GrUniqueKey::Builder builder(copyKey, origKey, kDomain, 3);
|
||||
builder[0] = static_cast<uint32_t>(copyParams.fFilter);
|
||||
builder[1] = copyParams.fDimensions.width();
|
||||
builder[2] = copyParams.fDimensions.height();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we need to make a copy with MIP maps the producer is asked to return a key that identifies
|
||||
* the original conteny + the addition of MIP map levels. If the producer does not want to cache
|
||||
* the copy it can simply leave the key uninitialized.
|
||||
*/
|
||||
virtual void makeMipMappedKey(GrUniqueKey* mipMappedKey) = 0;
|
||||
* 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
|
||||
* makeMipMappedKey() returns true). In that case, the maker is notified in case it
|
||||
* wants to note that for when the maker is destroyed.
|
||||
*/
|
||||
virtual void didCacheMipMappedCopy(const GrUniqueKey& mipMappedKey,
|
||||
uint32_t contextUniqueID) = 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,
|
||||
@ -135,11 +157,12 @@ protected:
|
||||
kTightCopy_DomainMode
|
||||
};
|
||||
|
||||
// TODO: Try to remove the draw fallback and directly use GrCopyBaseMipMapToTextureProxy
|
||||
// instead.
|
||||
static GrSurfaceProxyView MakeMipMappedCopy(GrRecordingContext*,
|
||||
GrSurfaceProxyView,
|
||||
GrColorType colorType);
|
||||
// This can draw to accomplish the copy, thus the recording context is needed
|
||||
static GrSurfaceProxyView CopyOnGpu(GrRecordingContext*,
|
||||
GrSurfaceProxyView inputView,
|
||||
GrColorType,
|
||||
const CopyParams& copyParams,
|
||||
bool dstWillRequireMipMaps);
|
||||
|
||||
static DomainMode DetermineDomainMode(const SkRect& constraintRect,
|
||||
FilterConstraint filterConstraint,
|
||||
@ -158,8 +181,8 @@ protected:
|
||||
GrRecordingContext* context() const { return fContext; }
|
||||
|
||||
private:
|
||||
virtual GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState,
|
||||
bool willBeMipped) = 0;
|
||||
virtual GrSurfaceProxyView onRefTextureProxyViewForParams(GrSamplerState, bool willBeMipped,
|
||||
SkScalar scaleAdjust[2]) = 0;
|
||||
|
||||
GrRecordingContext* fContext;
|
||||
const GrImageInfo fImageInfo;
|
||||
|
@ -918,13 +918,15 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
|
||||
bitmap.height() <= this->caps()->maxTileSize());
|
||||
SkASSERT(!samplerState.isRepeated());
|
||||
|
||||
GrSurfaceProxyView view = GrRefCachedBitmapView(fContext.get(), bitmap, samplerState);
|
||||
SkScalar scales[2] = {1.f, 1.f};
|
||||
GrSurfaceProxyView view = GrRefCachedBitmapView(fContext.get(), bitmap, samplerState, scales);
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute a matrix that maps the rect we will draw to the src rect.
|
||||
SkMatrix texMatrix = SkMatrix::MakeRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
|
||||
texMatrix.postScale(scales[0], scales[1]);
|
||||
|
||||
SkAlphaType srcAlphaType = bitmap.alphaType();
|
||||
|
||||
@ -1050,7 +1052,7 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const
|
||||
auto filter = paint.getFilterQuality() > kNone_SkFilterQuality
|
||||
? GrSamplerState::Filter::kBilerp
|
||||
: GrSamplerState::Filter::kNearest;
|
||||
GrSurfaceProxyView clipView = as_IB(clipImage)->refView(this->context(), filter);
|
||||
GrSurfaceProxyView clipView = as_IB(clipImage)->refView(this->context(), filter, nullptr);
|
||||
// Fold clip matrix into ctm
|
||||
ctm.preConcat(clipMatrix);
|
||||
SkMatrix inverseClipMatrix;
|
||||
@ -1343,7 +1345,7 @@ void SkGpuDevice::drawProducerLattice(GrTextureProducer* producer,
|
||||
|
||||
auto dstColorSpace = fRenderTargetContext->colorInfo().colorSpace();
|
||||
const GrSamplerState::Filter filter = compute_lattice_filter_mode(*paint);
|
||||
auto view = producer->viewForParams(&filter);
|
||||
auto view = producer->viewForParams(&filter, nullptr);
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
@ -537,7 +537,7 @@ void SkGpuDevice::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int co
|
||||
uint32_t uniqueID;
|
||||
view = image->refPinnedView(this->context(), &uniqueID);
|
||||
if (!view) {
|
||||
view = image->refView(this->context(), GrSamplerState::Filter::kBilerp);
|
||||
view = image->refView(this->context(), GrSamplerState::Filter::kBilerp, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,9 +134,9 @@ GrSurfaceProxyView GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
|
||||
}
|
||||
|
||||
GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext* ctx, const SkBitmap& bitmap,
|
||||
GrSamplerState params) {
|
||||
GrSamplerState params, SkScalar scaleAdjust[2]) {
|
||||
GrBitmapTextureMaker maker(ctx, bitmap, GrBitmapTextureMaker::Cached::kYes);
|
||||
return maker.viewForParams(params);
|
||||
return maker.viewForParams(params, scaleAdjust);
|
||||
}
|
||||
|
||||
GrSurfaceProxyView GrMakeCachedBitmapProxyView(GrRecordingContext* context, const SkBitmap& bitmap,
|
||||
|
@ -163,12 +163,15 @@ static_assert((int)kIDA_GrBlendCoeff == (int)SkBlendModeCoeff::kIDA);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Texture management
|
||||
|
||||
/**
|
||||
* Returns a view that wraps a texture representing the bitmap that is compatible with the
|
||||
* GrSamplerState. The texture is inserted into the cache (unless the bitmap is marked volatile)
|
||||
* and can be retrieved again via this function.
|
||||
/** Returns a view that wraps a texture representing the bitmap that is compatible with the
|
||||
* GrSamplerState. The texture is inserted into the cache (unless the bitmap is marked volatile)
|
||||
* and can be retrieved again via this function.
|
||||
* The 'scaleAdjust' in/out parameter will be updated to hold any rescaling that needs to be
|
||||
* performed on the absolute texture coordinates (e.g., if the texture is resized out to
|
||||
* the next power of two). It can be null if the caller is sure the bitmap won't be resized.
|
||||
*/
|
||||
GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext*, const SkBitmap&, GrSamplerState);
|
||||
GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext*, const SkBitmap&, GrSamplerState,
|
||||
SkScalar scaleAdjust[2]);
|
||||
|
||||
/**
|
||||
* Creates a new texture with mipmap levels and copies the baseProxy into the base layer.
|
||||
|
@ -64,7 +64,8 @@ public:
|
||||
// this call will flatten a SkImage_GpuYUV to a single texture.
|
||||
virtual const GrSurfaceProxyView* view(GrRecordingContext*) const { return nullptr; }
|
||||
|
||||
virtual GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState) const = 0;
|
||||
virtual GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
|
||||
SkScalar scaleAdjust[2]) const = 0;
|
||||
virtual GrSurfaceProxyView refPinnedView(GrRecordingContext*, uint32_t* uniqueID) const {
|
||||
return {};
|
||||
}
|
||||
|
@ -186,8 +186,8 @@ bool SkImage_GpuBase::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels,
|
||||
return sContext->readPixels(dstInfo, dstPixels, dstRB, {srcX, srcY});
|
||||
}
|
||||
|
||||
GrSurfaceProxyView SkImage_GpuBase::refView(GrRecordingContext* context,
|
||||
GrSamplerState params) const {
|
||||
GrSurfaceProxyView SkImage_GpuBase::refView(GrRecordingContext* context, GrSamplerState params,
|
||||
SkScalar scaleAdjust[2]) const {
|
||||
if (!context || !fContext->priv().matches(context)) {
|
||||
SkASSERT(0);
|
||||
return {};
|
||||
@ -195,7 +195,7 @@ GrSurfaceProxyView SkImage_GpuBase::refView(GrRecordingContext* context,
|
||||
|
||||
GrTextureAdjuster adjuster(fContext.get(), *this->view(context), this->imageInfo().colorInfo(),
|
||||
this->uniqueID());
|
||||
return adjuster.viewForParams(params);
|
||||
return adjuster.viewForParams(params, scaleAdjust);
|
||||
}
|
||||
|
||||
GrBackendTexture SkImage_GpuBase::onGetBackendTexture(bool flushPendingGrContextIO,
|
||||
|
@ -28,7 +28,8 @@ public:
|
||||
bool onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
|
||||
int srcX, int srcY, CachingHint) const override;
|
||||
|
||||
GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState) const final;
|
||||
GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
|
||||
SkScalar scaleAdjust[2]) const final;
|
||||
|
||||
GrSurfaceProxyView refPinnedView(GrRecordingContext* context, uint32_t* uniqueID) const final {
|
||||
*uniqueID = this->uniqueID();
|
||||
|
@ -92,11 +92,13 @@ bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
|
||||
}
|
||||
|
||||
for (int i = 0; i < fNumViews; ++i) {
|
||||
GrTextureProducer::CopyParams copyParams;
|
||||
int mipCount = SkMipMap::ComputeLevelCount(fViews[i].proxy()->width(),
|
||||
fViews[i].proxy()->height());
|
||||
if (mipCount && GrGpu::IsACopyNeededForMips(fContext->priv().caps(),
|
||||
fViews[i].asTextureProxy(),
|
||||
GrSamplerState::Filter::kMipMap)) {
|
||||
GrSamplerState::Filter::kMipMap,
|
||||
©Params)) {
|
||||
auto mippedView = GrCopyBaseMipMapToTextureProxy(context, fViews[i].asTextureProxy(),
|
||||
fOrigin, fProxyColorTypes[i]);
|
||||
if (!mippedView.proxy()) {
|
||||
|
@ -238,13 +238,14 @@ bool SkImage_Lazy::onIsValid(GrContext* context) const {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
GrSurfaceProxyView SkImage_Lazy::refView(GrRecordingContext* context, GrSamplerState params) const {
|
||||
GrSurfaceProxyView SkImage_Lazy::refView(GrRecordingContext* context, GrSamplerState params,
|
||||
SkScalar scaleAdjust[2]) const {
|
||||
if (!context) {
|
||||
return {};
|
||||
}
|
||||
|
||||
GrImageTextureMaker textureMaker(context, this, kAllow_CachingHint);
|
||||
return textureMaker.viewForParams(params);
|
||||
return textureMaker.viewForParams(params, scaleAdjust);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -42,7 +42,8 @@ public:
|
||||
bool onReadPixels(const SkImageInfo&, void*, size_t, int srcX, int srcY,
|
||||
CachingHint) const override;
|
||||
#if SK_SUPPORT_GPU
|
||||
GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState) const override;
|
||||
GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
|
||||
SkScalar scaleAdjust[2]) const override;
|
||||
sk_sp<SkCachedData> getPlanes(SkYUVASizeInfo*, SkYUVAIndex[4],
|
||||
SkYUVColorSpace*, const void* planes[4]) override;
|
||||
#endif
|
||||
|
@ -85,7 +85,8 @@ public:
|
||||
const SkBitmap* onPeekBitmap() const override { return &fBitmap; }
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState) const override;
|
||||
GrSurfaceProxyView refView(GrRecordingContext*, GrSamplerState,
|
||||
SkScalar scaleAdjust[2]) const override;
|
||||
#endif
|
||||
|
||||
bool getROPixels(SkBitmap*, CachingHint) const override;
|
||||
@ -173,8 +174,8 @@ bool SkImage_Raster::getROPixels(SkBitmap* dst, CachingHint) const {
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
GrSurfaceProxyView SkImage_Raster::refView(GrRecordingContext* context,
|
||||
GrSamplerState params) const {
|
||||
GrSurfaceProxyView SkImage_Raster::refView(GrRecordingContext* context, GrSamplerState params,
|
||||
SkScalar scaleAdjust[2]) const {
|
||||
if (!context) {
|
||||
return {};
|
||||
}
|
||||
@ -183,10 +184,10 @@ GrSurfaceProxyView SkImage_Raster::refView(GrRecordingContext* context,
|
||||
if (GrSurfaceProxyView view = this->refPinnedView(context, &uniqueID)) {
|
||||
GrTextureAdjuster adjuster(context, std::move(view), fBitmap.info().colorInfo(),
|
||||
fPinnedUniqueID);
|
||||
return adjuster.viewForParams(params);
|
||||
return adjuster.viewForParams(params, scaleAdjust);
|
||||
}
|
||||
|
||||
return GrRefCachedBitmapView(context, fBitmap, params);
|
||||
return GrRefCachedBitmapView(context, fBitmap, params, scaleAdjust);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -209,7 +210,8 @@ bool SkImage_Raster::onPinAsTexture(GrContext* ctx) const {
|
||||
} else {
|
||||
SkASSERT(fPinnedCount == 0);
|
||||
SkASSERT(fPinnedUniqueID == 0);
|
||||
fPinnedView = GrRefCachedBitmapView(ctx, fBitmap, GrSamplerState::Filter::kNearest);
|
||||
fPinnedView =
|
||||
GrRefCachedBitmapView(ctx, fBitmap, GrSamplerState::Filter::kNearest, nullptr);
|
||||
if (!fPinnedView) {
|
||||
return false;
|
||||
}
|
||||
|
@ -213,13 +213,16 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
||||
fImage->width(), fImage->height(), args.fFilterQuality, *args.fViewMatrix, *lm,
|
||||
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
|
||||
GrSamplerState samplerState(wm, textureFilterMode);
|
||||
GrSurfaceProxyView view = as_IB(fImage)->refView(args.fContext, samplerState);
|
||||
SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
|
||||
GrSurfaceProxyView view = as_IB(fImage)->refView(args.fContext, samplerState, scaleAdjust);
|
||||
if (!view) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkAlphaType srcAlphaType = fImage->alphaType();
|
||||
|
||||
lmInverse.postScale(scaleAdjust[0], scaleAdjust[1]);
|
||||
|
||||
const auto& caps = *args.fContext->priv().caps();
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> inner;
|
||||
|
@ -970,19 +970,20 @@ static void test_cross_context_image(skiatest::Reporter* reporter, const GrConte
|
||||
sk_sp<SkImage> refImg(imageMaker(ctx));
|
||||
|
||||
// Any context should be able to borrow the texture at this point
|
||||
GrSurfaceProxyView view = as_IB(refImg)->refView(ctx, GrSamplerState::Filter::kNearest);
|
||||
GrSurfaceProxyView view =
|
||||
as_IB(refImg)->refView(ctx, GrSamplerState::Filter::kNearest, nullptr);
|
||||
REPORTER_ASSERT(reporter, view);
|
||||
|
||||
// But once it's borrowed, no other context should be able to borrow
|
||||
otherTestContext->makeCurrent();
|
||||
GrSurfaceProxyView otherView =
|
||||
as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest);
|
||||
as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest, nullptr);
|
||||
REPORTER_ASSERT(reporter, !otherView);
|
||||
|
||||
// Original context (that's already borrowing) should be okay
|
||||
testContext->makeCurrent();
|
||||
GrSurfaceProxyView viewSecondRef =
|
||||
as_IB(refImg)->refView(ctx, GrSamplerState::Filter::kNearest);
|
||||
as_IB(refImg)->refView(ctx, GrSamplerState::Filter::kNearest, nullptr);
|
||||
REPORTER_ASSERT(reporter, viewSecondRef);
|
||||
|
||||
// Release first ref from the original context
|
||||
@ -991,7 +992,7 @@ static void test_cross_context_image(skiatest::Reporter* reporter, const GrConte
|
||||
// We released one proxy but not the other from the current borrowing context. Make sure
|
||||
// a new context is still not able to borrow the texture.
|
||||
otherTestContext->makeCurrent();
|
||||
otherView = as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest);
|
||||
otherView = as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest, nullptr);
|
||||
REPORTER_ASSERT(reporter, !otherView);
|
||||
|
||||
// Release second ref from the original context
|
||||
@ -1000,7 +1001,7 @@ static void test_cross_context_image(skiatest::Reporter* reporter, const GrConte
|
||||
|
||||
// Now we should be able to borrow the texture from the other context
|
||||
otherTestContext->makeCurrent();
|
||||
otherView = as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest);
|
||||
otherView = as_IB(refImg)->refView(otherCtx, GrSamplerState::Filter::kNearest, nullptr);
|
||||
REPORTER_ASSERT(reporter, otherView);
|
||||
|
||||
// Release everything
|
||||
@ -1041,7 +1042,8 @@ DEF_GPUTEST(SkImage_CrossContextGrayAlphaConfigs, reporter, options) {
|
||||
sk_sp<SkImage> image = SkImage::MakeCrossContextFromPixmap(ctx, pixmap, false);
|
||||
REPORTER_ASSERT(reporter, image);
|
||||
|
||||
GrSurfaceProxyView view = as_IB(image)->refView(ctx, GrSamplerState::Filter::kNearest);
|
||||
GrSurfaceProxyView view =
|
||||
as_IB(image)->refView(ctx, GrSamplerState::Filter::kNearest, nullptr);
|
||||
REPORTER_ASSERT(reporter, view);
|
||||
|
||||
bool expectAlpha = kAlpha_8_SkColorType == ct;
|
||||
|
Loading…
Reference in New Issue
Block a user