| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 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 "GrTextureAdjuster.h" | 
 | 9 |  | 
 | 10 | #include "GrContext.h" | 
| Brian Osman | 32342f0 | 2017-03-04 08:12:46 -0500 | [diff] [blame] | 11 | #include "GrResourceProvider.h" | 
| Brian Osman | 3b65598 | 2017-03-07 16:58:08 -0500 | [diff] [blame] | 12 | #include "SkGr.h" | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 13 |  | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 14 | GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original, | 
| Robert Phillips | 0c984a0 | 2017-03-16 07:51:56 -0400 | [diff] [blame] | 15 |                                      SkAlphaType alphaType, | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 16 |                                      const SkIRect& contentArea, uint32_t uniqueID, | 
 | 17 |                                      SkColorSpace* cs) | 
 | 18 |     : INHERITED(contentArea.width(), contentArea.height(), | 
 | 19 |                 GrPixelConfigIsAlphaOnly(original->config())) | 
| Robert Phillips | 0c984a0 | 2017-03-16 07:51:56 -0400 | [diff] [blame] | 20 |     , fContext(context) | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 21 |     , fOriginal(std::move(original)) | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 22 |     , fAlphaType(alphaType) | 
 | 23 |     , fColorSpace(cs) | 
 | 24 |     , fUniqueID(uniqueID) { | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 25 |     SkASSERT(SkIRect::MakeWH(fOriginal->width(), fOriginal->height()).contains(contentArea)); | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 26 |     if (contentArea.fLeft > 0 || contentArea.fTop > 0 || | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 27 |         contentArea.fRight < fOriginal->width() || contentArea.fBottom < fOriginal->height()) { | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 28 |         fContentArea.set(contentArea); | 
 | 29 |     } | 
 | 30 | } | 
 | 31 |  | 
 | 32 | void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey, | 
| Brian Osman | 61624f0 | 2016-12-09 14:51:59 -0500 | [diff] [blame] | 33 |                                     SkColorSpace* dstColorSpace) { | 
 | 34 |     // Destination color space is irrelevant - we already have a texture so we're just sub-setting | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 35 |     GrUniqueKey baseKey; | 
 | 36 |     GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height())); | 
 | 37 |     MakeCopyKeyFromOrigKey(baseKey, params, copyKey); | 
 | 38 | } | 
 | 39 |  | 
 | 40 | void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) { | 
 | 41 |     // We don't currently have a mechanism for notifications on Images! | 
 | 42 | } | 
 | 43 |  | 
| Robert Phillips | 0c984a0 | 2017-03-16 07:51:56 -0400 | [diff] [blame] | 44 | sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams) { | 
 | 45 |     GrUniqueKey key; | 
 | 46 |     this->makeCopyKey(copyParams, &key, nullptr); | 
 | 47 |     if (key.isValid()) { | 
 | 48 |         sk_sp<GrTextureProxy> cachedCopy = fContext->resourceProvider()->findProxyByUniqueKey(key); | 
 | 49 |         if (cachedCopy) { | 
 | 50 |             return cachedCopy; | 
 | 51 |         } | 
 | 52 |     } | 
 | 53 |  | 
 | 54 |     sk_sp<GrTextureProxy> proxy = this->originalProxyRef(); | 
 | 55 |     const SkIRect* contentArea = this->contentAreaOrNull(); | 
 | 56 |  | 
 | 57 |     sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), contentArea, copyParams); | 
 | 58 |     if (copy) { | 
 | 59 |         if (key.isValid()) { | 
 | 60 |             fContext->resourceProvider()->assignUniqueKeyToProxy(key, copy.get()); | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 61 |             this->didCacheCopy(key); | 
 | 62 |         } | 
 | 63 |     } | 
 | 64 |     return copy; | 
 | 65 | } | 
 | 66 |  | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 67 | sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxySafeForParams( | 
 | 68 |                                                                  const GrSamplerParams& params, | 
 | 69 |                                                                  SkIPoint* outOffset, | 
 | 70 |                                                                  SkScalar scaleAdjust[2]) { | 
 | 71 |     sk_sp<GrTextureProxy> proxy = this->originalProxyRef(); | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 72 |     CopyParams copyParams; | 
 | 73 |     const SkIRect* contentArea = this->contentAreaOrNull(); | 
 | 74 |  | 
| Robert Phillips | 0c984a0 | 2017-03-16 07:51:56 -0400 | [diff] [blame] | 75 |     if (!fContext) { | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 76 |         // The texture was abandoned. | 
 | 77 |         return nullptr; | 
 | 78 |     } | 
 | 79 |  | 
 | 80 |     if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) { | 
 | 81 |         // If we generate a MIP chain for texture it will read pixel values from outside the content | 
 | 82 |         // area. | 
 | 83 |         copyParams.fWidth = contentArea->width(); | 
 | 84 |         copyParams.fHeight = contentArea->height(); | 
 | 85 |         copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode; | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 86 |     } else if (!fContext->getGpu()->isACopyNeededForTextureParams(proxy.get(), params, ©Params, | 
| Robert Phillips | 81444fb | 2017-03-21 09:14:35 -0400 | [diff] [blame] | 87 |                                                                   scaleAdjust)) { | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 88 |         if (outOffset) { | 
 | 89 |             if (contentArea) { | 
 | 90 |                 outOffset->set(contentArea->fLeft, contentArea->fRight); | 
 | 91 |             } else { | 
 | 92 |                 outOffset->set(0, 0); | 
 | 93 |             } | 
 | 94 |         } | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 95 |         return proxy; | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 96 |     } | 
 | 97 |  | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 98 |     sk_sp<GrTextureProxy> copy = this->refTextureProxyCopy(copyParams); | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 99 |     if (copy && outOffset) { | 
 | 100 |         outOffset->set(0, 0); | 
 | 101 |     } | 
 | 102 |     return copy; | 
 | 103 | } | 
 | 104 |  | 
 | 105 | sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor( | 
 | 106 |                                         const SkMatrix& origTextureMatrix, | 
 | 107 |                                         const SkRect& origConstraintRect, | 
 | 108 |                                         FilterConstraint filterConstraint, | 
 | 109 |                                         bool coordsLimitedToConstraintRect, | 
 | 110 |                                         const GrSamplerParams::FilterMode* filterOrNullForBicubic, | 
| Brian Osman | 61624f0 | 2016-12-09 14:51:59 -0500 | [diff] [blame] | 111 |                                         SkColorSpace* dstColorSpace) { | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 112 |  | 
 | 113 |     SkMatrix textureMatrix = origTextureMatrix; | 
 | 114 |     const SkIRect* contentArea = this->contentAreaOrNull(); | 
 | 115 |     // Convert the constraintRect to be relative to the texture rather than the content area so | 
 | 116 |     // that both rects are in the same coordinate system. | 
 | 117 |     SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect); | 
 | 118 |     if (contentArea) { | 
 | 119 |         SkScalar l = SkIntToScalar(contentArea->fLeft); | 
 | 120 |         SkScalar t = SkIntToScalar(contentArea->fTop); | 
 | 121 |         constraintRect.writable()->offset(l, t); | 
 | 122 |         textureMatrix.postTranslate(l, t); | 
 | 123 |     } | 
 | 124 |  | 
 | 125 |     SkRect domain; | 
 | 126 |     GrSamplerParams params; | 
 | 127 |     if (filterOrNullForBicubic) { | 
 | 128 |         params.setFilterMode(*filterOrNullForBicubic); | 
 | 129 |     } | 
| Robert Phillips | 67c18d6 | 2017-01-20 12:44:06 -0500 | [diff] [blame] | 130 |     SkScalar scaleAdjust[2] = { 1.0f, 1.0f }; | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 131 |     sk_sp<GrTextureProxy> proxy(this->refTextureProxySafeForParams(params, nullptr, scaleAdjust)); | 
 | 132 |     if (!proxy) { | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 133 |         return nullptr; | 
 | 134 |     } | 
 | 135 |     // If we made a copy then we only copied the contentArea, in which case the new texture is all | 
 | 136 |     // content. | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 137 |     if (proxy.get() != this->originalProxy()) { | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 138 |         contentArea = nullptr; | 
| Robert Phillips | 67c18d6 | 2017-01-20 12:44:06 -0500 | [diff] [blame] | 139 |         textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]); | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 140 |     } | 
 | 141 |  | 
 | 142 |     DomainMode domainMode = | 
 | 143 |         DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect, | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 144 |                             proxy.get(), | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 145 |                             contentArea, filterOrNullForBicubic, | 
 | 146 |                             &domain); | 
 | 147 |     if (kTightCopy_DomainMode == domainMode) { | 
 | 148 |         // TODO: Copy the texture and adjust the texture matrix (both parts need to consider | 
 | 149 |         // non-int constraint rect) | 
 | 150 |         // For now: treat as bilerp and ignore what goes on above level 0. | 
 | 151 |  | 
 | 152 |         // We only expect MIP maps to require a tight copy. | 
 | 153 |         SkASSERT(filterOrNullForBicubic && | 
 | 154 |                  GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic); | 
 | 155 |         static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode; | 
 | 156 |         domainMode = | 
 | 157 |             DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect, | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 158 |                                 proxy.get(), | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 159 |                                 contentArea, &kBilerp, &domain); | 
 | 160 |         SkASSERT(kTightCopy_DomainMode != domainMode); | 
 | 161 |     } | 
 | 162 |     SkASSERT(kNoDomain_DomainMode == domainMode || | 
 | 163 |              (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom)); | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 164 |     sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace, | 
 | 165 |                                                                        dstColorSpace); | 
| Robert Phillips | 3798c86 | 2017-03-27 11:08:16 -0400 | [diff] [blame] | 166 |     return CreateFragmentProcessorForDomainAndFilter(fContext->resourceProvider(), std::move(proxy), | 
 | 167 |                                                      std::move(colorSpaceXform), | 
| Brian Osman | e8e5458 | 2016-11-28 10:06:27 -0500 | [diff] [blame] | 168 |                                                      textureMatrix, domainMode, domain, | 
 | 169 |                                                      filterOrNullForBicubic); | 
 | 170 | } |