Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrTextureParamsAdjuster.h" | 8 #include "GrTextureParamsAdjuster.h" |
| 9 | 9 |
| 10 #include "GrCaps.h" | 10 #include "GrCaps.h" |
| 11 #include "GrContext.h" | 11 #include "GrContext.h" |
| 12 #include "GrDrawContext.h" | 12 #include "GrDrawContext.h" |
| 13 #include "GrGpu.h" | 13 #include "GrGpu.h" |
| 14 #include "GrGpuResourcePriv.h" | 14 #include "GrGpuResourcePriv.h" |
| 15 #include "GrResourceKey.h" | 15 #include "GrResourceKey.h" |
| 16 #include "GrTexture.h" | 16 #include "GrTexture.h" |
| 17 #include "GrTextureParams.h" | 17 #include "GrTextureParams.h" |
| 18 #include "GrTextureProvider.h" | 18 #include "GrTextureProvider.h" |
| 19 #include "SkCanvas.h" | 19 #include "SkCanvas.h" |
| 20 #include "SkGr.h" | 20 #include "SkGr.h" |
| 21 #include "SkGrPriv.h" | 21 #include "SkGrPriv.h" |
| 22 #include "effects/GrBicubicEffect.h" | |
| 22 #include "effects/GrTextureDomain.h" | 23 #include "effects/GrTextureDomain.h" |
| 23 | 24 |
| 24 typedef GrTextureProducer::CopyParams CopyParams; | 25 typedef GrTextureProducer::CopyParams CopyParams; |
| 25 | 26 |
| 26 ////////////////////////////////////////////////////////////////////////////// | 27 ////////////////////////////////////////////////////////////////////////////// |
| 27 | 28 |
| 28 static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset, | 29 static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset, |
| 29 const CopyParams& copyParams) { | 30 const CopyParams& copyParams) { |
| 30 SkASSERT(!subset || !subset->isEmpty()); | 31 SkASSERT(!subset || !subset->isEmpty()); |
| 31 GrContext* context = inputTexture->getContext(); | 32 GrContext* context = inputTexture->getContext(); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 result->resourcePriv().setUniqueKey(key); | 165 result->resourcePriv().setUniqueKey(key); |
| 165 this->didCacheCopy(key); | 166 this->didCacheCopy(key); |
| 166 } | 167 } |
| 167 if (outOffset) { | 168 if (outOffset) { |
| 168 outOffset->set(0, 0); | 169 outOffset->set(0, 0); |
| 169 } | 170 } |
| 170 } | 171 } |
| 171 return result; | 172 return result; |
| 172 } | 173 } |
| 173 | 174 |
| 175 enum DomainMode { | |
| 176 kNoDomain_DomainMode, | |
| 177 kDomain_DomainMode, | |
| 178 kTightCopy_DomainMode | |
| 179 }; | |
| 180 | |
| 181 /** Determines whether a texture domain is necessary and if so what domain to us e. In the case of | |
| 182 mip maps it may indicate that a copy must be made to avoid filtering outside the constraint | |
| 183 rectangle or the content area of the texture. */ | |
| 184 static DomainMode determine_domain_mode( | |
|
robertphillips
2015/11/05 20:13:24
tab these over one to avoid lining up with the cod
bsalomon
2015/11/06 15:24:26
Done.
| |
| 185 const SkRect& constraintRect, | |
| 186 GrTextureAdjuster::FilterConstraint filterConstraint, | |
| 187 bool coordsLimitedContraintRect, | |
| 188 int texW, int texH, | |
| 189 const SkIRect* textureContentArea, | |
| 190 const GrTextureParams::FilterMode* filterModeOrNullForBicubic, | |
| 191 SkRect* domainRect) { | |
|
robertphillips
2015/11/05 20:13:24
... or maybe a '\n' here ?
bsalomon
2015/11/06 15:24:26
Done.
| |
| 192 SkASSERT(SkRect::MakeIWH(texW, texH).contains(constraintRect)); | |
| 193 // We only expect a content area rect if there is some non-content area. | |
| 194 SkASSERT(!textureContentArea || | |
| 195 (!textureContentArea->contains(SkIRect::MakeWH(texW, texH)) && | |
| 196 SkRect::Make(*textureContentArea).contains(constraintRect))); | |
| 197 | |
| 198 SkRect textureBounds = SkRect::MakeIWH(texW, texH); | |
| 199 // If the src rectangle contains the whole texture then no need for a domain . | |
| 200 if (constraintRect.contains(textureBounds)) { | |
| 201 return kNoDomain_DomainMode; | |
| 202 } | |
| 203 | |
| 204 bool restrictFilterToRect = (filterConstraint == GrTextureAdjuster::kYes_Fil terConstraint); | |
| 205 | |
| 206 // If we can filter outside the constraint rect, and there is no non-content area of the | |
| 207 // texture, and we aren't going to generate sample coords outside the constr aint rect then we | |
| 208 // don't need a domain. | |
| 209 if (!restrictFilterToRect && !textureContentArea && coordsLimitedContraintRe ct) { | |
| 210 return kNoDomain_DomainMode; | |
| 211 } | |
| 212 | |
| 213 // Get the domain inset based on sampling mode (or bail if mipped) | |
| 214 SkScalar filterHalfWidth; | |
| 215 if (filterModeOrNullForBicubic) { | |
| 216 switch (*filterModeOrNullForBicubic) { | |
| 217 case GrTextureParams::kNone_FilterMode: | |
| 218 if (coordsLimitedContraintRect) { | |
| 219 return kNoDomain_DomainMode; | |
| 220 } else { | |
| 221 filterHalfWidth = 0.f; | |
| 222 } | |
| 223 break; | |
| 224 case GrTextureParams::kBilerp_FilterMode: | |
| 225 filterHalfWidth = 1.f; | |
| 226 break; | |
| 227 case GrTextureParams::kMipMap_FilterMode: | |
| 228 // No domain can save use here. | |
| 229 return kTightCopy_DomainMode; | |
| 230 } | |
| 231 } else { | |
| 232 // bicubic does nearest filtering internally. | |
| 233 filterHalfWidth = 2.f; | |
| 234 } | |
| 235 | |
|
robertphillips
2015/11/05 20:13:24
// We will inset the domain half a pixel b.c. ...
bsalomon
2015/11/06 15:24:25
Done.
| |
| 236 static const SkScalar kDomainInset = 0.5f; | |
|
robertphillips
2015/11/05 20:13:24
can -> to ?
bsalomon
2015/11/06 15:24:26
Done.
| |
| 237 // Figure out the limits of pixels we're allowed can sample from. | |
| 238 // Unless we know the amount of outset and the texture matrix we have to con servatively enforce | |
| 239 // the domain. | |
| 240 if (restrictFilterToRect) { | |
| 241 domainRect->fLeft = constraintRect.fLeft + kDomainInset; | |
| 242 domainRect->fTop = constraintRect.fTop + kDomainInset; | |
| 243 domainRect->fRight = constraintRect.fRight - kDomainInset; | |
| 244 domainRect->fBottom = constraintRect.fBottom - kDomainInset; | |
| 245 } else if (textureContentArea) { | |
| 246 // If we got here then: there is a textureContentArea, the coords are li mited to the | |
| 247 // constraint rect, and we're allowed to filter across the constraint re ct boundary. So | |
|
robertphillips
2015/11/05 20:13:24
from -> to ?
bsalomon
2015/11/06 15:24:26
Done.
| |
| 248 // we check whether the filter would reach from the edge of the content area. | |
| 249 bool needContentAreaConstraint = false; | |
| 250 // We will only set the sides that are required. | |
| 251 domainRect->setLargest(); | |
| 252 if (textureContentArea->fLeft > 0 && | |
| 253 textureContentArea->fLeft + filterHalfWidth > constraintRect.fLeft) { | |
| 254 domainRect->fLeft = textureContentArea->fLeft + kDomainInset; | |
| 255 needContentAreaConstraint = true; | |
| 256 } | |
| 257 if (textureContentArea->fTop > 0 && | |
| 258 textureContentArea->fTop + filterHalfWidth > constraintRect.fTop) { | |
| 259 domainRect->fTop = textureContentArea->fTop + kDomainInset; | |
| 260 needContentAreaConstraint = true; | |
| 261 } | |
| 262 if (textureContentArea->fRight < texW && | |
| 263 textureContentArea->fRight - filterHalfWidth < constraintRect.fRight ) { | |
| 264 domainRect->fRight = textureContentArea->fRight - kDomainInset; | |
| 265 needContentAreaConstraint = true; | |
| 266 } | |
| 267 if (textureContentArea->fBottom < texW && | |
| 268 textureContentArea->fBottom - filterHalfWidth < constraintRect.fBott om) { | |
| 269 domainRect->fBottom = textureContentArea->fBottom - kDomainInset; | |
| 270 needContentAreaConstraint = true; | |
| 271 } | |
| 272 if (!needContentAreaConstraint) { | |
| 273 return kNoDomain_DomainMode; | |
| 274 } | |
| 275 } else { | |
| 276 return kNoDomain_DomainMode; | |
| 277 } | |
| 278 | |
| 279 if (domainRect->fLeft > domainRect->fRight) { | |
| 280 domainRect->fLeft = domainRect->fRight = SkScalarAve(domainRect->fLeft, domainRect->fRight); | |
| 281 } | |
| 282 if (domainRect->fTop > domainRect->fBottom) { | |
| 283 domainRect->fTop = domainRect->fBottom = SkScalarAve(domainRect->fTop, d omainRect->fBottom); | |
| 284 } | |
|
robertphillips
2015/11/05 20:13:24
What happens to the sides that are still out at th
bsalomon
2015/11/06 15:24:26
They'd still be really large (in abs value). This
| |
| 285 domainRect->fLeft /= texW; | |
| 286 domainRect->fTop /= texH; | |
| 287 domainRect->fRight /= texW; | |
| 288 domainRect->fBottom /= texH; | |
| 289 return kDomain_DomainMode; | |
| 290 } | |
| 291 | |
| 292 const GrFragmentProcessor* GrTextureAdjuster::createFragmentProcessor( | |
| 293 const SkMatrix& textureMatrix, | |
| 294 const SkRect& constraintRect, | |
| 295 FilterConstraint filterConstraint, | |
| 296 bool coordsLimitedToConstraintRect, | |
| 297 const GrTextureParams::FilterMode* filterOrNullForBicubic) { | |
| 298 | |
| 299 const SkIRect* contentArea = this->contentArea(); | |
| 300 | |
| 301 SkRect domain; | |
| 302 GrTexture* texture = this->originalTexture(); | |
| 303 DomainMode domainMode = | |
| 304 determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToC onstraintRect, | |
| 305 texture->width(), texture->height(), | |
| 306 contentArea, filterOrNullForBicubic, | |
| 307 &domain); | |
| 308 if (kTightCopy_DomainMode == domainMode) { | |
| 309 // TODO: Copy the texture and adjust the texture matrix (both parts need to consider | |
| 310 // non-int constraint rect) | |
| 311 // For now: treat as bilerp and ignore what goes on above level 0. | |
| 312 SkASSERT(filterOrNullForBicubic && | |
| 313 GrTextureParams::kMipMap_FilterMode == *filterOrNullForBicubic) ; | |
| 314 static const GrTextureParams::FilterMode kBilerp = GrTextureParams::kBil erp_FilterMode; | |
| 315 domainMode = | |
| 316 determine_domain_mode(constraintRect, filterConstraint, coordsLimite dToConstraintRect, | |
| 317 texture->width(), texture->height(), | |
| 318 contentArea, &kBilerp, &domain); | |
| 319 SkASSERT(kTightCopy_DomainMode != domainMode); | |
| 320 filterOrNullForBicubic = &kBilerp; | |
| 321 } | |
| 322 SkASSERT(kNoDomain_DomainMode == domainMode || | |
| 323 (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom)); | |
| 324 if (filterOrNullForBicubic) { | |
| 325 if (kDomain_DomainMode == domainMode) { | |
| 326 SkASSERT(*filterOrNullForBicubic != GrTextureParams::kMipMap_FilterM ode); | |
| 327 return GrTextureDomainEffect::Create(texture, textureMatrix, domain, | |
| 328 GrTextureDomain::kClamp_Mode, | |
| 329 *filterOrNullForBicubic); | |
| 330 } else { | |
| 331 GrTextureParams params(SkShader::kClamp_TileMode, *filterOrNullForBi cubic); | |
| 332 return GrSimpleTextureEffect::Create(texture, textureMatrix, params) ; | |
| 333 } | |
| 334 } else { | |
| 335 if (kDomain_DomainMode == domainMode) { | |
| 336 return GrBicubicEffect::Create(texture, textureMatrix, domain); | |
| 337 } else { | |
| 338 static const SkShader::TileMode kClampClamp[] = | |
| 339 { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode }; | |
| 340 return GrBicubicEffect::Create(texture, textureMatrix, kClampClamp); | |
| 341 } | |
| 342 } | |
| 343 } | |
| 344 | |
| 174 ////////////////////////////////////////////////////////////////////////////// | 345 ////////////////////////////////////////////////////////////////////////////// |
| 175 | 346 |
| 176 GrTexture* GrTextureMaker::refTextureForParams(GrContext* ctx, const GrTexturePa rams& params) { | 347 GrTexture* GrTextureMaker::refTextureForParams(GrContext* ctx, const GrTexturePa rams& params) { |
| 177 CopyParams copyParams; | 348 CopyParams copyParams; |
| 178 if (!ctx->getGpu()->makeCopyForTextureParams(this->width(), this->height(), params, | 349 if (!ctx->getGpu()->makeCopyForTextureParams(this->width(), this->height(), params, |
| 179 ©Params)) { | 350 ©Params)) { |
| 180 return this->refOriginalTexture(ctx); | 351 return this->refOriginalTexture(ctx); |
| 181 } | 352 } |
| 182 GrUniqueKey copyKey; | 353 GrUniqueKey copyKey; |
| 183 this->makeCopyKey(copyParams, ©Key); | 354 this->makeCopyKey(copyParams, ©Key); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 200 return result; | 371 return result; |
| 201 } | 372 } |
| 202 | 373 |
| 203 GrTexture* GrTextureMaker::generateTextureForParams(GrContext* ctx, const CopyPa rams& copyParams) { | 374 GrTexture* GrTextureMaker::generateTextureForParams(GrContext* ctx, const CopyPa rams& copyParams) { |
| 204 SkAutoTUnref<GrTexture> original(this->refOriginalTexture(ctx)); | 375 SkAutoTUnref<GrTexture> original(this->refOriginalTexture(ctx)); |
| 205 if (!original) { | 376 if (!original) { |
| 206 return nullptr; | 377 return nullptr; |
| 207 } | 378 } |
| 208 return copy_on_gpu(original, nullptr, copyParams); | 379 return copy_on_gpu(original, nullptr, copyParams); |
| 209 } | 380 } |
| OLD | NEW |