aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTextureAdjuster.cpp
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2016-11-28 10:06:27 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-28 15:44:40 +0000
commite8e54580c3c91fd485187af040af118aa5153261 (patch)
tree27d67ccb3500d300ba40e52bef56c05b095999df /src/gpu/GrTextureAdjuster.cpp
parente9f78b41c65a78400c22a1b79007b1b9e187a745 (diff)
GrTextureProducer cleanup, phase two: Producer, Adjuster, Maker
Previously: GrTextureProducer, GrTextureAdjuster, and GrTextureMaker were all in GrTextureParamsAdjuster.h. Now they're each in their own header. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=5202 Change-Id: I17fa9057b11511aa4d3e15569ea1c378cfec4c80 Reviewed-on: https://skia-review.googlesource.com/5202 Reviewed-by: Robert Phillips <robertphillips@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src/gpu/GrTextureAdjuster.cpp')
-rw-r--r--src/gpu/GrTextureAdjuster.cpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/gpu/GrTextureAdjuster.cpp b/src/gpu/GrTextureAdjuster.cpp
new file mode 100644
index 0000000000..24d050a1ed
--- /dev/null
+++ b/src/gpu/GrTextureAdjuster.cpp
@@ -0,0 +1,167 @@
+/*
+ * 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 "GrTextureAdjuster.h"
+
+#include "GrContext.h"
+#include "GrGpu.h"
+#include "GrGpuResourcePriv.h"
+#include "GrTexture.h"
+#include "SkGrPriv.h"
+
+GrTextureAdjuster::GrTextureAdjuster(GrTexture* original, SkAlphaType alphaType,
+ const SkIRect& contentArea, uint32_t uniqueID,
+ SkColorSpace* cs)
+ : INHERITED(contentArea.width(), contentArea.height(),
+ GrPixelConfigIsAlphaOnly(original->config()))
+ , fOriginal(original)
+ , fAlphaType(alphaType)
+ , fColorSpace(cs)
+ , fUniqueID(uniqueID) {
+ SkASSERT(SkIRect::MakeWH(original->width(), original->height()).contains(contentArea));
+ if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
+ contentArea.fRight < original->width() || contentArea.fBottom < original->height()) {
+ fContentArea.set(contentArea);
+ }
+}
+
+void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
+ SkDestinationSurfaceColorMode) {
+ // Color mode is irrelevant in this case - we already have a texture so we're just sub-setting
+ GrUniqueKey baseKey;
+ GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
+ MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
+}
+
+void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) {
+ // We don't currently have a mechanism for notifications on Images!
+}
+
+GrTexture* GrTextureAdjuster::refCopy(const CopyParams& copyParams) {
+ GrTexture* texture = this->originalTexture();
+ GrContext* context = texture->getContext();
+ const SkIRect* contentArea = this->contentAreaOrNull();
+ GrUniqueKey key;
+ this->makeCopyKey(copyParams, &key, SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware);
+ if (key.isValid()) {
+ GrTexture* cachedCopy = context->textureProvider()->findAndRefTextureByUniqueKey(key);
+ if (cachedCopy) {
+ return cachedCopy;
+ }
+ }
+ GrTexture* copy = CopyOnGpu(texture, contentArea, copyParams);
+ if (copy) {
+ if (key.isValid()) {
+ copy->resourcePriv().setUniqueKey(key);
+ this->didCacheCopy(key);
+ }
+ }
+ return copy;
+}
+
+GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrSamplerParams& params,
+ SkDestinationSurfaceColorMode colorMode,
+ SkIPoint* outOffset) {
+ GrTexture* texture = this->originalTexture();
+ GrContext* context = texture->getContext();
+ CopyParams copyParams;
+ const SkIRect* contentArea = this->contentAreaOrNull();
+
+ if (!context) {
+ // The texture was abandoned.
+ return nullptr;
+ }
+
+ if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
+ // If we generate a MIP chain for texture it will read pixel values from outside the content
+ // area.
+ copyParams.fWidth = contentArea->width();
+ copyParams.fHeight = contentArea->height();
+ copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
+ } else if (!context->getGpu()->makeCopyForTextureParams(texture, params, &copyParams)) {
+ if (outOffset) {
+ if (contentArea) {
+ outOffset->set(contentArea->fLeft, contentArea->fRight);
+ } else {
+ outOffset->set(0, 0);
+ }
+ }
+ return SkRef(texture);
+ }
+
+ GrTexture* copy = this->refCopy(copyParams);
+ if (copy && outOffset) {
+ outOffset->set(0, 0);
+ }
+ return copy;
+}
+
+sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
+ const SkMatrix& origTextureMatrix,
+ const SkRect& origConstraintRect,
+ FilterConstraint filterConstraint,
+ bool coordsLimitedToConstraintRect,
+ const GrSamplerParams::FilterMode* filterOrNullForBicubic,
+ SkColorSpace* dstColorSpace,
+ SkDestinationSurfaceColorMode colorMode) {
+
+ SkMatrix textureMatrix = origTextureMatrix;
+ const SkIRect* contentArea = this->contentAreaOrNull();
+ // Convert the constraintRect to be relative to the texture rather than the content area so
+ // that both rects are in the same coordinate system.
+ SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
+ if (contentArea) {
+ SkScalar l = SkIntToScalar(contentArea->fLeft);
+ SkScalar t = SkIntToScalar(contentArea->fTop);
+ constraintRect.writable()->offset(l, t);
+ textureMatrix.postTranslate(l, t);
+ }
+
+ SkRect domain;
+ GrSamplerParams params;
+ if (filterOrNullForBicubic) {
+ params.setFilterMode(*filterOrNullForBicubic);
+ }
+ sk_sp<GrTexture> texture(this->refTextureSafeForParams(params, colorMode, nullptr));
+ if (!texture) {
+ return nullptr;
+ }
+ // If we made a copy then we only copied the contentArea, in which case the new texture is all
+ // content.
+ if (texture.get() != this->originalTexture()) {
+ contentArea = nullptr;
+ }
+
+ DomainMode domainMode =
+ DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ texture->width(), texture->height(),
+ contentArea, filterOrNullForBicubic,
+ &domain);
+ if (kTightCopy_DomainMode == domainMode) {
+ // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
+ // non-int constraint rect)
+ // For now: treat as bilerp and ignore what goes on above level 0.
+
+ // We only expect MIP maps to require a tight copy.
+ SkASSERT(filterOrNullForBicubic &&
+ GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
+ static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
+ domainMode =
+ DetermineDomainMode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
+ texture->width(), texture->height(),
+ contentArea, &kBilerp, &domain);
+ SkASSERT(kTightCopy_DomainMode != domainMode);
+ }
+ SkASSERT(kNoDomain_DomainMode == domainMode ||
+ (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
+ textureMatrix.postIDiv(texture->width(), texture->height());
+ sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
+ dstColorSpace);
+ return CreateFragmentProcessorForDomainAndFilter(texture.get(), std::move(colorSpaceXform),
+ textureMatrix, domainMode, domain,
+ filterOrNullForBicubic);
+}