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 |