Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 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 "SkGpuDevice.h" | |
| 9 | |
| 10 #include "GrBlurUtils.h" | |
| 11 #include "GrCaps.h" | |
| 12 #include "GrDrawContext.h" | |
| 13 #include "GrStrokeInfo.h" | |
| 14 #include "GrTextureParamsAdjuster.h" | |
| 15 #include "SkDraw.h" | |
| 16 #include "SkGrPriv.h" | |
| 17 #include "SkMaskFilter.h" | |
| 18 #include "effects/GrBicubicEffect.h" | |
| 19 #include "effects/GrSimpleTextureEffect.h" | |
| 20 #include "effects/GrTextureDomain.h" | |
| 21 | |
| 22 static inline bool use_shader(bool textureIsAlphaOnly, const SkPaint& paint) { | |
| 23 return textureIsAlphaOnly && paint.getShader(); | |
| 24 } | |
| 25 | |
|
robertphillips
2015/11/06 20:54:51
// This could use some documentation
bsalomon
2015/11/09 19:35:22
Done.
| |
| 26 static const GrFragmentProcessor* mix_texture_fp_with_paint_color_and_shader( | |
| 27 const GrFragmentProc essor* textureFP, | |
| 28 bool textureIsAlphaO nly, | |
| 29 GrContext* context, | |
| 30 const SkMatrix& view Matrix, | |
| 31 const SkPaint& paint ) { | |
| 32 if (textureIsAlphaOnly) { | |
| 33 if (const SkShader* shader = paint.getShader()) { | |
| 34 SkAutoTUnref<const GrFragmentProcessor> shaderFP( | |
| 35 shader->asFragmentProcessor(context, | |
| 36 viewMatrix, | |
| 37 nullptr, | |
| 38 paint.getFilterQuality())); | |
| 39 if (!shaderFP) { | |
| 40 return nullptr; | |
| 41 } | |
| 42 const GrFragmentProcessor* fpSeries[] = { shaderFP, textureFP }; | |
| 43 return GrFragmentProcessor::RunInSeries(fpSeries, 2); | |
| 44 } else { | |
| 45 return GrFragmentProcessor::MulOutputByInputUnpremulColor(textureFP) ; | |
| 46 } | |
| 47 } else { | |
| 48 return GrFragmentProcessor::MulOutputByInputAlpha(textureFP); | |
| 49 } | |
| 50 } | |
| 51 | |
|
robertphillips
2015/11/06 20:54:51
Can 'adjuster' be const ?
bsalomon
2015/11/09 19:35:22
I don't think it should be. It means a subclass co
| |
| 52 void SkGpuDevice::drawTextureAdjuster(GrTextureAdjuster* adjuster, | |
| 53 bool alphaOnly, | |
| 54 const SkRect* srcRect, | |
| 55 const SkRect* dstRect, | |
| 56 SkCanvas::SrcRectConstraint constraint, | |
| 57 const SkMatrix& viewMatrix, | |
| 58 const GrClip& clip, | |
| 59 const SkPaint& paint) { | |
| 60 // Figure out the actual dst and src rect by clipping the src rect to the bo unds of the | |
| 61 // adjuster. If the src rect is clipped then the dst rect must be recomputed . Also determine | |
| 62 // the matrix that maps the src rect to the dst rect. | |
| 63 SkRect clippedSrcRect; | |
| 64 SkRect clippedDstRect; | |
| 65 SkIRect contentIBounds; | |
| 66 adjuster->getContentArea(&contentIBounds); | |
|
robertphillips
2015/11/06 20:54:51
Can 'contentBounds' be const ?
bsalomon
2015/11/09 19:35:22
sure
| |
| 67 SkRect contentBounds = SkRect::Make(contentIBounds); | |
| 68 SkMatrix srcToDstMatrix; | |
| 69 if (srcRect) { | |
|
robertphillips
2015/11/06 20:54:52
Do we need 'tempDstRect'? Can we just point at 'co
bsalomon
2015/11/09 19:35:22
Done.
| |
| 70 SkRect tempDstRect; | |
| 71 if (!dstRect) { | |
| 72 tempDstRect = contentBounds; | |
| 73 dstRect = &tempDstRect; | |
| 74 } | |
| 75 if (!contentBounds.contains(*srcRect)) { | |
| 76 clippedSrcRect = *srcRect; | |
| 77 if (!clippedSrcRect.intersect(contentBounds)) { | |
| 78 return; | |
| 79 } | |
| 80 if (!srcToDstMatrix.setRectToRect(*srcRect, *dstRect, SkMatrix::kFil l_ScaleToFit)) { | |
| 81 return; | |
| 82 } | |
| 83 srcToDstMatrix.mapRect(&clippedDstRect, clippedSrcRect); | |
| 84 } else { | |
| 85 clippedSrcRect = *srcRect; | |
| 86 clippedDstRect = *dstRect; | |
| 87 if (!srcToDstMatrix.setRectToRect(*srcRect, *dstRect, SkMatrix::kFil l_ScaleToFit)) { | |
| 88 return; | |
| 89 } | |
| 90 } | |
| 91 } else { | |
| 92 clippedSrcRect = contentBounds; | |
| 93 if (dstRect) { | |
| 94 clippedDstRect = *dstRect; | |
| 95 if (!srcToDstMatrix.setRectToRect(contentBounds, *dstRect, | |
| 96 SkMatrix::kFill_ScaleToFit)) { | |
| 97 return; | |
| 98 } | |
| 99 } else { | |
| 100 clippedDstRect = contentBounds; | |
| 101 srcToDstMatrix.reset(); | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 this->drawTextureAdjusterImpl(adjuster, alphaOnly, clippedSrcRect, clippedDs tRect, constraint, | |
| 106 viewMatrix, srcToDstMatrix, clip, paint); | |
| 107 } | |
| 108 | |
| 109 void SkGpuDevice::drawTextureAdjusterImpl(GrTextureAdjuster* adjuster, | |
| 110 bool alphaTexture, | |
| 111 const SkRect& clippedSrcRect, | |
| 112 const SkRect& clippedDstRect, | |
| 113 SkCanvas::SrcRectConstraint constraint , | |
| 114 const SkMatrix& viewMatrix, | |
| 115 const SkMatrix& srcToDstMatrix, | |
| 116 const GrClip& clip, | |
| 117 const SkPaint& paint) { | |
| 118 // Specifying the texture coords as local coordinates is an attempt to enabl e more batching | |
| 119 // by not baking anything about the srcRect, dstRect, or viewMatrix, into th e texture FP. In | |
| 120 // the future this should be an opaque optimization enabled by the combinati on of batch/GP and | |
| 121 // FP. | |
| 122 const SkMatrix* textureFPMatrix; | |
| 123 SkMatrix tempMatrix; | |
| 124 const SkMaskFilter* mf = paint.getMaskFilter(); | |
| 125 GrTexture* texture = adjuster->originalTexture(); | |
| 126 // The shader expects proper local coords, so we can't replace local coords with texture coords | |
| 127 // if the shader will be used. If we have a mask filter we will change the u nderlying geometry | |
| 128 // that is rendered. | |
| 129 bool canUseTextureCoordsAsLocalCoords = !use_shader(alphaTexture, paint) && !mf; | |
| 130 if (canUseTextureCoordsAsLocalCoords) { | |
| 131 textureFPMatrix = &SkMatrix::I(); | |
| 132 } else { | |
| 133 if (!srcToDstMatrix.invert(&tempMatrix)) { | |
| 134 return; | |
| 135 } | |
| 136 tempMatrix.postIDiv(texture->width(), texture->height()); | |
| 137 textureFPMatrix = &tempMatrix; | |
| 138 } | |
| 139 | |
| 140 bool doBicubic; | |
| 141 GrTextureParams::FilterMode fm = | |
| 142 GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewMatrix, sr cToDstMatrix, | |
| 143 &doBicubic); | |
| 144 const GrTextureParams::FilterMode* filterMode = doBicubic ? nullptr : &fm; | |
| 145 | |
| 146 GrTextureAdjuster::FilterConstraint constraintMode; | |
| 147 if (SkCanvas::kFast_SrcRectConstraint == constraint) { | |
| 148 constraintMode = GrTextureAdjuster::kNo_FilterConstraint; | |
| 149 } else { | |
| 150 constraintMode = GrTextureAdjuster::kYes_FilterConstraint; | |
| 151 } | |
| 152 | |
| 153 // If we have to outset for AA then we will generate texture coords outside the src rect. The | |
| 154 // same happens for any mask filter that extends the bounds rendered in the dst. | |
|
robertphillips
2015/11/06 20:54:52
// TODO: not all mask filters expand ?
bsalomon
2015/11/09 19:35:22
Done.
| |
| 155 bool coordsAllInsideSrcRect = !paint.isAntiAlias() && !mf; | |
| 156 | |
| 157 SkAutoTUnref<const GrFragmentProcessor> fp(adjuster->createFragmentProcessor ( | |
| 158 *textureFPMatrix, clippedSrcRect, constraintMode, coordsAllInsideSrcRect , filterMode)); | |
| 159 if (!fp) { | |
| 160 return; | |
| 161 } | |
| 162 fp.reset(mix_texture_fp_with_paint_color_and_shader(fp, alphaTexture, this-> context(), | |
| 163 viewMatrix, paint)); | |
| 164 GrPaint grPaint; | |
| 165 if (!SkPaintToGrPaintReplaceShader(fContext, paint, fp, &grPaint)) { | |
| 166 return; | |
| 167 } | |
| 168 | |
| 169 if (canUseTextureCoordsAsLocalCoords) { | |
| 170 SkRect localRect; | |
| 171 localRect.fLeft = clippedSrcRect.fLeft / texture->width(); | |
| 172 localRect.fBottom = clippedSrcRect.fBottom / texture->height(); | |
| 173 localRect.fRight = clippedSrcRect.fRight / texture->width(); | |
| 174 localRect.fTop = clippedSrcRect.fTop / texture->height(); | |
| 175 fDrawContext->fillRectToRect(clip, grPaint, viewMatrix, clippedDstRect, localRect); | |
| 176 return; | |
| 177 } | |
| 178 | |
| 179 if (!mf) { | |
| 180 fDrawContext->drawRect(clip, grPaint, viewMatrix, clippedDstRect); | |
| 181 return; | |
| 182 } | |
| 183 | |
| 184 // First see if we can do the draw + mask filter direct to the dst. | |
| 185 SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); | |
| 186 SkRRect rrect; | |
| 187 rrect.setRect(clippedDstRect); | |
| 188 if (mf->directFilterRRectMaskGPU(fContext->textureProvider(), | |
| 189 fDrawContext, | |
| 190 &grPaint, | |
| 191 clip, | |
| 192 viewMatrix, | |
| 193 rec, | |
| 194 rrect)) { | |
| 195 return; | |
| 196 } | |
| 197 SkPath rectPath; | |
| 198 rectPath.addRect(clippedDstRect); | |
| 199 GrBlurUtils::drawPathWithMaskFilter(this->context(), fDrawContext, fRenderTa rget, fClip, | |
| 200 rectPath, &grPaint, viewMatrix, mf, pain t.getPathEffect(), | |
| 201 GrStrokeInfo::FillInfo()); | |
| 202 } | |
| OLD | NEW |