blob: 579cf96ef36d30823a70b491cc0015e6813be116 [file] [log] [blame]
bsalomon045802d2015-10-20 07:58:01 -07001/*
2 * Copyright 2015 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 "GrTextureParamsAdjuster.h"
9
10#include "GrCaps.h"
11#include "GrContext.h"
12#include "GrDrawContext.h"
13#include "GrGpu.h"
bsalomon89fe56b2015-10-29 10:49:28 -070014#include "GrGpuResourcePriv.h"
15#include "GrResourceKey.h"
bsalomon045802d2015-10-20 07:58:01 -070016#include "GrTexture.h"
17#include "GrTextureParams.h"
18#include "GrTextureProvider.h"
19#include "SkCanvas.h"
20#include "SkGr.h"
21#include "SkGrPriv.h"
bsalomon89fe56b2015-10-29 10:49:28 -070022#include "effects/GrTextureDomain.h"
bsalomon045802d2015-10-20 07:58:01 -070023
bsalomon89fe56b2015-10-29 10:49:28 -070024typedef GrTextureProducer::CopyParams CopyParams;
bsalomon045802d2015-10-20 07:58:01 -070025
bsalomon89fe56b2015-10-29 10:49:28 -070026//////////////////////////////////////////////////////////////////////////////
27
28static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset,
29 const CopyParams& copyParams) {
30 SkASSERT(!subset || !subset->isEmpty());
bsalomon045802d2015-10-20 07:58:01 -070031 GrContext* context = inputTexture->getContext();
32 SkASSERT(context);
33 const GrCaps* caps = context->caps();
34
35 // Either it's a cache miss or the original wasn't cached to begin with.
36 GrSurfaceDesc rtDesc = inputTexture->desc();
bsalomon89fe56b2015-10-29 10:49:28 -070037 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
38 rtDesc.fWidth = copyParams.fWidth;
bsalomon045802d2015-10-20 07:58:01 -070039 rtDesc.fHeight = copyParams.fHeight;
40 rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);
41
42 // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
43 // fail.
44 if (!caps->isConfigRenderable(rtDesc.fConfig, false)) {
45 if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) {
46 if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
47 rtDesc.fConfig = kAlpha_8_GrPixelConfig;
48 } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
49 rtDesc.fConfig = kSkia8888_GrPixelConfig;
50 } else {
51 return nullptr;
52 }
53 } else if (kRGB_GrColorComponentFlags ==
54 (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) {
55 if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
56 rtDesc.fConfig = kSkia8888_GrPixelConfig;
57 } else {
58 return nullptr;
59 }
60 } else {
61 return nullptr;
62 }
63 }
64
65 SkAutoTUnref<GrTexture> copy(context->textureProvider()->createTexture(rtDesc, true));
66 if (!copy) {
67 return nullptr;
68 }
69
bsalomon89fe56b2015-10-29 10:49:28 -070070 // TODO: If no scaling is being performed then use copySurface.
71
bsalomon045802d2015-10-20 07:58:01 -070072 GrPaint paint;
73
bsalomon89fe56b2015-10-29 10:49:28 -070074 SkScalar sx;
75 SkScalar sy;
76 if (subset) {
77 sx = 1.f / inputTexture->width();
78 sy = 1.f / inputTexture->height();
79 }
bsalomon045802d2015-10-20 07:58:01 -070080
bsalomon89fe56b2015-10-29 10:49:28 -070081 if (copyParams.fFilter != GrTextureParams::kNone_FilterMode && subset &&
82 (subset->width() != copyParams.fWidth || subset->height() != copyParams.fHeight)) {
83 SkRect domain;
84 domain.fLeft = (subset->fLeft + 0.5f) * sx;
85 domain.fTop = (subset->fTop + 0.5f)* sy;
86 domain.fRight = (subset->fRight - 0.5f) * sx;
87 domain.fBottom = (subset->fBottom - 0.5f) * sy;
88 // This would cause us to read values from outside the subset. Surely, the caller knows
89 // better!
90 SkASSERT(copyParams.fFilter != GrTextureParams::kMipMap_FilterMode);
91 paint.addColorFragmentProcessor(
92 GrTextureDomainEffect::Create(inputTexture, SkMatrix::I(), domain,
93 GrTextureDomain::kClamp_Mode,
94 copyParams.fFilter))->unref();
95 } else {
96 GrTextureParams params(SkShader::kClamp_TileMode, copyParams.fFilter);
97 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
98 }
99
100 SkRect localRect;
101 if (subset) {
102 localRect = SkRect::Make(*subset);
103 localRect.fLeft *= sx;
104 localRect.fTop *= sy;
105 localRect.fRight *= sx;
106 localRect.fBottom *= sy;
107 } else {
108 localRect = SkRect::MakeWH(1.f, 1.f);
109 }
bsalomon045802d2015-10-20 07:58:01 -0700110
111 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(copy->asRenderTarget()));
112 if (!drawContext) {
113 return nullptr;
114 }
115
bsalomon89fe56b2015-10-29 10:49:28 -0700116 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
bsalomona2e69fc2015-11-05 10:41:43 -0800117 drawContext->fillRectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), dstRect, localRect);
bsalomon045802d2015-10-20 07:58:01 -0700118 return copy.detach();
119}
120
bsalomonc75be342015-10-29 12:34:31 -0700121GrTextureAdjuster::GrTextureAdjuster(GrTexture* original, const SkIRect& contentArea)
bsalomon89fe56b2015-10-29 10:49:28 -0700122 : fOriginal(original) {
bsalomonc75be342015-10-29 12:34:31 -0700123 if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
124 contentArea.fRight < original->width() || contentArea.fBottom < original->height()) {
125 fContentArea.set(contentArea);
bsalomon89fe56b2015-10-29 10:49:28 -0700126 }
127}
128
129GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrTextureParams& params,
130 SkIPoint* outOffset) {
131 GrTexture* texture = this->originalTexture();
132 GrContext* context = texture->getContext();
133 CopyParams copyParams;
bsalomonc75be342015-10-29 12:34:31 -0700134 const SkIRect* contentArea = this->contentArea();
bsalomon89fe56b2015-10-29 10:49:28 -0700135
bsalomonc75be342015-10-29 12:34:31 -0700136 if (contentArea && GrTextureParams::kMipMap_FilterMode == params.filterMode()) {
137 // If we generate a MIP chain for texture it will read pixel values from outside the content
138 // area.
139 copyParams.fWidth = contentArea->width();
140 copyParams.fHeight = contentArea->height();
141 copyParams.fFilter = GrTextureParams::kBilerp_FilterMode;
142 } else if (!context->getGpu()->makeCopyForTextureParams(texture->width(), texture->height(),
143 params, &copyParams)) {
bsalomon89fe56b2015-10-29 10:49:28 -0700144 if (outOffset) {
bsalomonc75be342015-10-29 12:34:31 -0700145 if (contentArea) {
146 outOffset->set(contentArea->fLeft, contentArea->fRight);
bsalomon89fe56b2015-10-29 10:49:28 -0700147 } else {
148 outOffset->set(0, 0);
149 }
150 }
151 return SkRef(texture);
152 }
153 GrUniqueKey key;
154 this->makeCopyKey(copyParams, &key);
155 if (key.isValid()) {
156 GrTexture* result = context->textureProvider()->findAndRefTextureByUniqueKey(key);
157 if (result) {
158 return result;
159 }
160 }
bsalomonc75be342015-10-29 12:34:31 -0700161 GrTexture* result = copy_on_gpu(texture, contentArea, copyParams);
bsalomon89fe56b2015-10-29 10:49:28 -0700162 if (result) {
163 if (key.isValid()) {
164 result->resourcePriv().setUniqueKey(key);
165 this->didCacheCopy(key);
166 }
167 if (outOffset) {
168 outOffset->set(0, 0);
169 }
170 }
171 return result;
172}
173
174//////////////////////////////////////////////////////////////////////////////
175
176GrTexture* GrTextureMaker::refTextureForParams(GrContext* ctx, const GrTextureParams& params) {
bsalomon045802d2015-10-20 07:58:01 -0700177 CopyParams copyParams;
178 if (!ctx->getGpu()->makeCopyForTextureParams(this->width(), this->height(), params,
179 &copyParams)) {
180 return this->refOriginalTexture(ctx);
181 }
182 GrUniqueKey copyKey;
183 this->makeCopyKey(copyParams, &copyKey);
184 if (copyKey.isValid()) {
185 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(copyKey);
186 if (result) {
187 return result;
188 }
189 }
190
191 GrTexture* result = this->generateTextureForParams(ctx, copyParams);
192 if (!result) {
193 return nullptr;
194 }
195
196 if (copyKey.isValid()) {
197 ctx->textureProvider()->assignUniqueKeyToTexture(copyKey, result);
198 this->didCacheCopy(copyKey);
199 }
200 return result;
201}
202
bsalomon89fe56b2015-10-29 10:49:28 -0700203GrTexture* GrTextureMaker::generateTextureForParams(GrContext* ctx, const CopyParams& copyParams) {
bsalomon100b8f82015-10-28 08:37:44 -0700204 SkAutoTUnref<GrTexture> original(this->refOriginalTexture(ctx));
205 if (!original) {
206 return nullptr;
bsalomon045802d2015-10-20 07:58:01 -0700207 }
bsalomon89fe56b2015-10-29 10:49:28 -0700208 return copy_on_gpu(original, nullptr, copyParams);
bsalomon045802d2015-10-20 07:58:01 -0700209}