GrTextureAdjuster.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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. #include "include/private/GrRecordingContext.h"
  8. #include "src/gpu/GrColorSpaceXform.h"
  9. #include "src/gpu/GrGpu.h"
  10. #include "src/gpu/GrProxyProvider.h"
  11. #include "src/gpu/GrRecordingContextPriv.h"
  12. #include "src/gpu/GrTextureAdjuster.h"
  13. #include "src/gpu/SkGr.h"
  14. GrTextureAdjuster::GrTextureAdjuster(GrRecordingContext* context,
  15. sk_sp<GrTextureProxy> original,
  16. GrColorType colorType,
  17. SkAlphaType alphaType,
  18. uint32_t uniqueID,
  19. SkColorSpace* cs,
  20. bool useDecal)
  21. : INHERITED(context, original->width(), original->height(),
  22. GrColorSpaceInfo(colorType, alphaType, sk_ref_sp(cs)), useDecal)
  23. , fOriginal(std::move(original))
  24. , fUniqueID(uniqueID) {}
  25. void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) {
  26. // Destination color space is irrelevant - we already have a texture so we're just sub-setting
  27. GrUniqueKey baseKey;
  28. GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
  29. MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
  30. }
  31. void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
  32. // We don't currently have a mechanism for notifications on Images!
  33. }
  34. sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams,
  35. bool willBeMipped) {
  36. GrProxyProvider* proxyProvider = this->context()->priv().proxyProvider();
  37. GrUniqueKey key;
  38. this->makeCopyKey(copyParams, &key);
  39. sk_sp<GrTextureProxy> cachedCopy;
  40. if (key.isValid()) {
  41. cachedCopy = proxyProvider->findOrCreateProxyByUniqueKey(key,
  42. this->originalProxy()->origin());
  43. if (cachedCopy && (!willBeMipped || GrMipMapped::kYes == cachedCopy->mipMapped())) {
  44. return cachedCopy;
  45. }
  46. }
  47. sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
  48. sk_sp<GrTextureProxy> copy = CopyOnGpu(this->context(), std::move(proxy), this->colorType(),
  49. copyParams, willBeMipped);
  50. if (copy) {
  51. if (key.isValid()) {
  52. SkASSERT(copy->origin() == this->originalProxy()->origin());
  53. if (cachedCopy) {
  54. SkASSERT(GrMipMapped::kYes == copy->mipMapped() &&
  55. GrMipMapped::kNo == cachedCopy->mipMapped());
  56. // If we had a cachedProxy, that means there already is a proxy in the cache which
  57. // matches the key, but it does not have mip levels and we require them. Thus we
  58. // must remove the unique key from that proxy.
  59. SkASSERT(cachedCopy->getUniqueKey() == key);
  60. proxyProvider->removeUniqueKeyFromProxy(cachedCopy.get());
  61. }
  62. proxyProvider->assignUniqueKeyToProxy(key, copy.get());
  63. this->didCacheCopy(key, proxyProvider->contextID());
  64. }
  65. }
  66. return copy;
  67. }
  68. sk_sp<GrTextureProxy> GrTextureAdjuster::onRefTextureProxyForParams(
  69. const GrSamplerState& params,
  70. bool willBeMipped,
  71. SkScalar scaleAdjust[2]) {
  72. sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
  73. CopyParams copyParams;
  74. if (this->context()->priv().abandoned()) {
  75. // The texture was abandoned.
  76. return nullptr;
  77. }
  78. SkASSERT(this->width() <= this->context()->priv().caps()->maxTextureSize() &&
  79. this->height() <= this->context()->priv().caps()->maxTextureSize());
  80. bool needsCopyForMipsOnly = false;
  81. if (!params.isRepeated() ||
  82. !GrGpu::IsACopyNeededForRepeatWrapMode(this->context()->priv().caps(), proxy.get(),
  83. proxy->width(), proxy->height(), params.filter(),
  84. &copyParams, scaleAdjust)) {
  85. needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(this->context()->priv().caps(),
  86. proxy.get(), params.filter(),
  87. &copyParams);
  88. if (!needsCopyForMipsOnly) {
  89. return proxy;
  90. }
  91. }
  92. sk_sp<GrTextureProxy> result = this->refTextureProxyCopy(copyParams, willBeMipped);
  93. if (!result && needsCopyForMipsOnly) {
  94. // If we were unable to make a copy and we only needed a copy for mips, then we will return
  95. // the source texture here and require that the GPU backend is able to fall back to using
  96. // bilerp if mips are required.
  97. return this->originalProxyRef();
  98. }
  99. return result;
  100. }
  101. std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
  102. const SkMatrix& origTextureMatrix,
  103. const SkRect& constraintRect,
  104. FilterConstraint filterConstraint,
  105. bool coordsLimitedToConstraintRect,
  106. const GrSamplerState::Filter* filterOrNullForBicubic) {
  107. SkMatrix textureMatrix = origTextureMatrix;
  108. SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
  109. sk_sp<GrTextureProxy> proxy(
  110. this->refTextureProxyForParams(filterOrNullForBicubic, scaleAdjust));
  111. if (!proxy) {
  112. return nullptr;
  113. }
  114. // If we made a copy then we only copied the contentArea, in which case the new texture is all
  115. // content.
  116. if (proxy.get() != this->originalProxy()) {
  117. textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
  118. }
  119. SkRect domain;
  120. DomainMode domainMode =
  121. DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
  122. proxy.get(), filterOrNullForBicubic, &domain);
  123. if (kTightCopy_DomainMode == domainMode) {
  124. // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
  125. // non-int constraint rect)
  126. // For now: treat as bilerp and ignore what goes on above level 0.
  127. // We only expect MIP maps to require a tight copy.
  128. SkASSERT(filterOrNullForBicubic &&
  129. GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic);
  130. static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
  131. domainMode =
  132. DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
  133. proxy.get(), &kBilerp, &domain);
  134. SkASSERT(kTightCopy_DomainMode != domainMode);
  135. }
  136. SkASSERT(kNoDomain_DomainMode == domainMode ||
  137. (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
  138. return this->createFragmentProcessorForDomainAndFilter(
  139. std::move(proxy), textureMatrix, domainMode, domain, filterOrNullForBicubic);
  140. }