OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 "GrClipMaskManager.h" | 8 #include "GrClipMaskManager.h" |
9 #include "GrCaps.h" | 9 #include "GrCaps.h" |
10 #include "GrDrawingManager.h" | 10 #include "GrDrawingManager.h" |
11 #include "GrDrawContextPriv.h" | 11 #include "GrDrawContextPriv.h" |
12 #include "GrDrawTarget.h" | |
13 #include "GrGpuResourcePriv.h" | 12 #include "GrGpuResourcePriv.h" |
14 #include "GrPaint.h" | 13 #include "GrPaint.h" |
15 #include "GrPathRenderer.h" | 14 #include "GrPathRenderer.h" |
16 #include "GrRenderTarget.h" | 15 #include "GrRenderTarget.h" |
17 #include "GrRenderTargetPriv.h" | 16 #include "GrRenderTargetPriv.h" |
18 #include "GrResourceProvider.h" | 17 #include "GrResourceProvider.h" |
19 #include "GrStencilAttachment.h" | 18 #include "GrStencilAttachment.h" |
20 #include "GrSWMaskHelper.h" | 19 #include "GrSWMaskHelper.h" |
21 #include "SkRasterClip.h" | 20 #include "SkRasterClip.h" |
22 #include "SkTLazy.h" | 21 #include "SkTLazy.h" |
23 #include "batches/GrRectBatchFactory.h" | 22 #include "batches/GrRectBatchFactory.h" |
24 #include "effects/GrConvexPolyEffect.h" | 23 #include "effects/GrConvexPolyEffect.h" |
25 #include "effects/GrPorterDuffXferProcessor.h" | 24 #include "effects/GrPorterDuffXferProcessor.h" |
26 #include "effects/GrRRectEffect.h" | 25 #include "effects/GrRRectEffect.h" |
27 #include "effects/GrTextureDomain.h" | 26 #include "effects/GrTextureDomain.h" |
28 | 27 |
29 typedef SkClipStack::Element Element; | 28 typedef SkClipStack::Element Element; |
30 | 29 |
30 static const int kMaxAnalyticElements = 4; | |
31 | |
31 //////////////////////////////////////////////////////////////////////////////// | 32 //////////////////////////////////////////////////////////////////////////////// |
32 // set up the draw state to enable the aa clipping mask. Besides setting up the | 33 // set up the draw state to enable the aa clipping mask. Besides setting up the |
33 // stage matrix this also alters the vertex layout | 34 // stage matrix this also alters the vertex layout |
34 static sk_sp<const GrFragmentProcessor> create_fp_for_mask(GrTexture* result, | 35 static sk_sp<const GrFragmentProcessor> create_fp_for_mask(GrTexture* result, |
35 const SkIRect &devBou nd) { | 36 const SkIRect &devBou nd) { |
36 SkMatrix mat; | 37 SkMatrix mat; |
37 // We use device coords to compute the texture coordinates. We set our matri x to be a | 38 // We use device coords to compute the texture coordinates. We set our matri x to be a |
38 // translation to the devBound, and then a scaling matrix to normalized coor ds. | 39 // translation to the devBound, and then a scaling matrix to normalized coor ds. |
39 mat.setIDiv(result->width(), result->height()); | 40 mat.setIDiv(result->width(), result->height()); |
40 mat.preTranslate(SkIntToScalar(-devBound.fLeft), | 41 mat.preTranslate(SkIntToScalar(-devBound.fLeft), |
41 SkIntToScalar(-devBound.fTop)); | 42 SkIntToScalar(-devBound.fTop)); |
42 | 43 |
43 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); | 44 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); |
44 return sk_sp<const GrFragmentProcessor>(GrTextureDomainEffect::Create( | 45 return sk_sp<const GrFragmentProcessor>(GrTextureDomainEffect::Create( |
45 result, | 46 result, |
46 mat, | 47 mat, |
47 GrTextureDomain::MakeTexelDomain(result , domainTexels), | 48 GrTextureDomain::MakeTexelDomain(result , domainTexels), |
48 GrTextureDomain::kDecal_Mode, | 49 GrTextureDomain::kDecal_Mode, |
49 GrTextureParams::kNone_FilterMode, | 50 GrTextureParams::kNone_FilterMode, |
50 kDevice_GrCoordSet)); | 51 kDevice_GrCoordSet)); |
51 } | 52 } |
52 | 53 |
53 static void draw_non_aa_rect(GrDrawTarget* drawTarget, | 54 void GrClipMaskManager::DrawNonAARect(GrDrawContext* drawContext, |
54 const GrPipelineBuilder& pipelineBuilder, | 55 const GrFixedClip& clip, |
55 const GrClip& clip, | 56 const SkMatrix& viewMatrix, |
56 GrColor color, | 57 const SkRect& rect, |
57 const SkMatrix& viewMatrix, | 58 bool doAA, |
58 const SkRect& rect) { | 59 const GrUserStencilSettings* stencilSettin gs) { |
59 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v iewMatrix, rect, | 60 drawContext->drawContextPriv().stencilRect(clip, stencilSettings, doAA, view Matrix, rect); |
60 nullptr, nullptr)); | |
61 drawTarget->drawBatch(pipelineBuilder, clip, batch); | |
62 } | 61 } |
63 | 62 |
64 // Does the path in 'element' require SW rendering? If so, return true (and, | 63 // Does the path in 'element' require SW rendering? If so, return true (and, |
65 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set | 64 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set |
66 // 'prOut' to the non-SW path renderer that will do the job). | 65 // 'prOut' to the non-SW path renderer that will do the job). |
67 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, | 66 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, |
68 bool hasUserStencilSettings, | 67 bool hasUserStencilSettings, |
69 const GrRenderTarget* rt, | 68 const GrDrawContext* drawContext, |
70 const SkMatrix& viewMatrix, | 69 const SkMatrix& viewMatrix, |
71 const Element* element, | 70 const Element* element, |
72 GrPathRenderer** prOut, | 71 GrPathRenderer** prOut, |
73 bool needsStencil) { | 72 bool needsStencil) { |
74 if (Element::kRect_Type == element->getType()) { | 73 if (Element::kRect_Type == element->getType()) { |
75 // rects can always be drawn directly w/o using the software path | 74 // rects can always be drawn directly w/o using the software path |
76 // TODO: skip rrects once we're drawing them directly. | 75 // TODO: skip rrects once we're drawing them directly. |
77 if (prOut) { | 76 if (prOut) { |
78 *prOut = nullptr; | 77 *prOut = nullptr; |
79 } | 78 } |
(...skipping 21 matching lines...) Expand all Loading... | |
101 : GrPathRendererChain::kColor_DrawType; | 100 : GrPathRendererChain::kColor_DrawType; |
102 } | 101 } |
103 | 102 |
104 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 103 GrPathRenderer::CanDrawPathArgs canDrawArgs; |
105 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); | 104 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); |
106 canDrawArgs.fViewMatrix = &viewMatrix; | 105 canDrawArgs.fViewMatrix = &viewMatrix; |
107 canDrawArgs.fPath = &path; | 106 canDrawArgs.fPath = &path; |
108 canDrawArgs.fStyle = &GrStyle::SimpleFill(); | 107 canDrawArgs.fStyle = &GrStyle::SimpleFill(); |
109 canDrawArgs.fAntiAlias = element->isAA(); | 108 canDrawArgs.fAntiAlias = element->isAA(); |
110 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; | 109 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; |
111 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled(); | 110 canDrawArgs.fIsStencilBufferMSAA = drawContext->isStencilBufferMultisamp led(); |
112 | 111 |
113 // the 'false' parameter disallows use of the SW path renderer | 112 // the 'false' parameter disallows use of the SW path renderer |
114 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA rgs, false, type); | 113 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA rgs, false, type); |
115 if (prOut) { | 114 if (prOut) { |
116 *prOut = pr; | 115 *prOut = pr; |
117 } | 116 } |
118 return SkToBool(!pr); | 117 return SkToBool(!pr); |
119 } | 118 } |
120 } | 119 } |
121 | 120 |
122 // Determines whether it is possible to draw the element to both the stencil buf fer and the | |
123 // alpha mask simultaneously. If so and the element is a path a compatible path renderer is | |
124 // also returned. | |
125 GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context, | |
126 GrTexture* texture, | |
127 const SkMatrix& viewMatrix, | |
128 const SkClipStack::Element* e lement) { | |
129 GrPathRenderer* pr; | |
130 constexpr bool kNeedsStencil = true; | |
131 constexpr bool kHasUserStencilSettings = false; | |
132 PathNeedsSWRenderer(context, | |
133 kHasUserStencilSettings, | |
134 texture->asRenderTarget(), | |
135 viewMatrix, | |
136 element, | |
137 &pr, | |
138 kNeedsStencil); | |
139 return pr; | |
140 } | |
141 | |
142 GrContext* GrClipMaskManager::getContext() { | |
143 return fDrawTarget->cmmAccess().context(); | |
144 } | |
145 | |
146 const GrCaps* GrClipMaskManager::caps() const { | |
147 return fDrawTarget->caps(); | |
148 } | |
149 | |
150 GrResourceProvider* GrClipMaskManager::resourceProvider() { | |
151 return fDrawTarget->cmmAccess().resourceProvider(); | |
152 } | |
153 /* | 121 /* |
154 * This method traverses the clip stack to see if the GrSoftwarePathRenderer | 122 * This method traverses the clip stack to see if the GrSoftwarePathRenderer |
155 * will be used on any element. If so, it returns true to indicate that the | 123 * will be used on any element. If so, it returns true to indicate that the |
156 * entire clip should be rendered in SW and then uploaded en masse to the gpu. | 124 * entire clip should be rendered in SW and then uploaded en masse to the gpu. |
157 */ | 125 */ |
158 bool GrClipMaskManager::UseSWOnlyPath(GrContext* context, | 126 bool GrClipMaskManager::UseSWOnlyPath(GrContext* context, |
159 const GrPipelineBuilder& pipelineBuilder, | 127 const GrPipelineBuilder& pipelineBuilder, |
160 const GrRenderTarget* rt, | 128 const GrDrawContext* drawContext, |
161 const SkVector& clipToMaskOffset, | 129 const SkVector& clipToMaskOffset, |
162 const GrReducedClip::ElementList& elements ) { | 130 const GrReducedClip::ElementList& elements ) { |
163 // TODO: generalize this function so that when | 131 // TODO: generalize this function so that when |
164 // a clip gets complex enough it can just be done in SW regardless | 132 // a clip gets complex enough it can just be done in SW regardless |
165 // of whether it would invoke the GrSoftwarePathRenderer. | 133 // of whether it would invoke the GrSoftwarePathRenderer. |
166 | 134 |
167 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip | 135 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip |
168 // space. | 136 // space. |
169 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY); | 137 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY); |
170 | 138 |
171 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { | 139 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { |
172 const Element* element = iter.get(); | 140 const Element* element = iter.get(); |
173 | 141 |
174 SkRegion::Op op = element->getOp(); | 142 SkRegion::Op op = element->getOp(); |
175 bool invert = element->isInverseFilled(); | 143 bool invert = element->isInverseFilled(); |
176 bool needsStencil = invert || | 144 bool needsStencil = invert || |
177 SkRegion::kIntersect_Op == op || SkRegion::kReverseD ifference_Op == op; | 145 SkRegion::kIntersect_Op == op || SkRegion::kReverseD ifference_Op == op; |
178 | 146 |
179 if (PathNeedsSWRenderer(context, pipelineBuilder.hasUserStencilSettings( ), | 147 if (PathNeedsSWRenderer(context, pipelineBuilder.hasUserStencilSettings( ), |
180 rt, translate, element, nullptr, needsStencil)) { | 148 drawContext, translate, element, nullptr, needsS tencil)) { |
181 return true; | 149 return true; |
182 } | 150 } |
183 } | 151 } |
184 return false; | 152 return false; |
185 } | 153 } |
186 | 154 |
187 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis t& elements, | 155 static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen ts, |
188 bool abortIfAA, | 156 bool abortIfAA, |
189 SkVector& clipToRTOffset, | 157 SkVector& clipToRTOffset, |
190 const SkRect* drawBounds, | 158 const SkRect* drawBounds, |
191 sk_sp<const GrFragmentProcessor >* resultFP) { | 159 sk_sp<const GrFragmentProcessor>* result FP) { |
192 SkRect boundsInClipSpace; | 160 SkRect boundsInClipSpace; |
193 if (drawBounds) { | 161 if (drawBounds) { |
194 boundsInClipSpace = *drawBounds; | 162 boundsInClipSpace = *drawBounds; |
195 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); | 163 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); |
196 } | 164 } |
197 SkASSERT(elements.count() <= kMaxAnalyticElements); | 165 SkASSERT(elements.count() <= kMaxAnalyticElements); |
198 const GrFragmentProcessor* fps[kMaxAnalyticElements]; | 166 const GrFragmentProcessor* fps[kMaxAnalyticElements]; |
199 for (int i = 0; i < kMaxAnalyticElements; ++i) { | 167 for (int i = 0; i < kMaxAnalyticElements; ++i) { |
200 fps[i] = nullptr; | 168 fps[i] = nullptr; |
201 } | 169 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
277 } | 245 } |
278 for (int i = 0; i < fpCnt; ++i) { | 246 for (int i = 0; i < fpCnt; ++i) { |
279 fps[i]->unref(); | 247 fps[i]->unref(); |
280 } | 248 } |
281 return !failed; | 249 return !failed; |
282 } | 250 } |
283 | 251 |
284 //////////////////////////////////////////////////////////////////////////////// | 252 //////////////////////////////////////////////////////////////////////////////// |
285 // sort out what kind of clip mask needs to be created: alpha, stencil, | 253 // sort out what kind of clip mask needs to be created: alpha, stencil, |
286 // scissor, or entirely software | 254 // scissor, or entirely software |
287 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, | 255 bool GrClipMaskManager::SetupClipping(GrContext* context, |
256 const GrPipelineBuilder& pipelineBuilder, | |
257 GrDrawContext* drawContext, | |
288 const GrClipStackClip& clip, | 258 const GrClipStackClip& clip, |
289 const SkRect* devBounds, | 259 const SkRect* devBounds, |
290 GrAppliedClip* out) { | 260 GrAppliedClip* out) { |
291 if (!clip.clipStack() || clip.clipStack()->isWideOpen()) { | 261 if (!clip.clipStack() || clip.clipStack()->isWideOpen()) { |
292 return true; | 262 return true; |
293 } | 263 } |
294 | 264 |
295 GrReducedClip::ElementList elements; | 265 GrReducedClip::ElementList elements; |
296 int32_t genID = 0; | 266 int32_t genID = 0; |
297 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat e; | 267 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat e; |
298 SkIRect clipSpaceIBounds; | 268 SkIRect clipSpaceIBounds; |
299 bool requiresAA = false; | 269 bool requiresAA = false; |
300 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | |
301 | 270 |
302 // GrDrawTarget should have filtered this for us | 271 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(drawContext->width(), drawConte xt->height()); |
303 SkASSERT(rt); | |
304 | |
305 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | |
306 clipSpaceRTIBounds.offset(clip.origin()); | 272 clipSpaceRTIBounds.offset(clip.origin()); |
307 | 273 |
308 SkIRect clipSpaceReduceQueryBounds; | 274 SkIRect clipSpaceReduceQueryBounds; |
309 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 | 275 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 |
310 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { | 276 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { |
311 SkIRect devIBounds = devBounds->roundOut(); | 277 SkIRect devIBounds = devBounds->roundOut(); |
312 devIBounds.offset(clip.origin()); | 278 devIBounds.offset(clip.origin()); |
313 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, devIBounds )) { | 279 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, devIBounds )) { |
314 return false; | 280 return false; |
315 } | 281 } |
(...skipping 23 matching lines...) Expand all Loading... | |
339 // isect convex_poly | 305 // isect convex_poly |
340 // isect convex_poly | 306 // isect convex_poly |
341 // when drawing rounded div borders. This could probably be tuned based on a | 307 // when drawing rounded div borders. This could probably be tuned based on a |
342 // configuration's relative costs of switching RTs to generate a mask vs | 308 // configuration's relative costs of switching RTs to generate a mask vs |
343 // longer shaders. | 309 // longer shaders. |
344 if (elements.count() <= kMaxAnalyticElements) { | 310 if (elements.count() <= kMaxAnalyticElements) { |
345 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), | 311 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), |
346 SkIntToScalar(-clip.origin().fY) }; | 312 SkIntToScalar(-clip.origin().fY) }; |
347 // When there are multiple samples we want to do per-sample clipping, no t compute a | 313 // When there are multiple samples we want to do per-sample clipping, no t compute a |
348 // fractional pixel coverage. | 314 // fractional pixel coverage. |
349 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); | 315 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); |
350 if (disallowAnalyticAA && !rt->numColorSamples()) { | 316 if (disallowAnalyticAA && !drawContext->numColorSamples()) { |
351 // With a single color sample, any coverage info is lost from color once it hits the | 317 // With a single color sample, any coverage info is lost from color once it hits the |
352 // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe | 318 // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe |
353 // is multisampled. | 319 // is multisampled. |
354 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || | 320 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || |
355 pipelineBuilder.hasUserStencilSettings(); | 321 pipelineBuilder.hasUserStencilSettings(); |
356 } | 322 } |
357 sk_sp<const GrFragmentProcessor> clipFP; | 323 sk_sp<const GrFragmentProcessor> clipFP; |
358 if (elements.isEmpty() || | 324 if (elements.isEmpty() || |
359 (requiresAA && | 325 (requiresAA && |
360 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo RTOffset, devBounds, | 326 get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTO ffset, devBounds, |
361 &clipFP))) { | 327 &clipFP))) { |
362 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 328 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
363 scissorSpaceIBounds.offset(-clip.origin()); | 329 scissorSpaceIBounds.offset(-clip.origin()); |
364 if (nullptr == devBounds || | 330 if (!devBounds || !SkRect::Make(scissorSpaceIBounds).contains(*devBo unds)) { |
365 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { | |
366 out->makeScissoredFPBased(clipFP, scissorSpaceIBounds); | 331 out->makeScissoredFPBased(clipFP, scissorSpaceIBounds); |
367 return true; | 332 return true; |
368 } | 333 } |
369 out->makeFPBased(clipFP); | 334 out->makeFPBased(clipFP); |
370 return true; | 335 return true; |
371 } | 336 } |
372 } | 337 } |
373 | 338 |
374 // If the stencil buffer is multisampled we can use it to do everything. | 339 // If the stencil buffer is multisampled we can use it to do everything. |
375 if (!rt->isStencilBufferMultisampled() && requiresAA) { | 340 if (!drawContext->isStencilBufferMultisampled() && requiresAA) { |
376 sk_sp<GrTexture> result; | 341 sk_sp<GrTexture> result; |
377 | 342 |
378 // The top-left of the mask corresponds to the top-left corner of the bo unds. | 343 // The top-left of the mask corresponds to the top-left corner of the bo unds. |
379 SkVector clipToMaskOffset = { | 344 SkVector clipToMaskOffset = { |
380 SkIntToScalar(-clipSpaceIBounds.fLeft), | 345 SkIntToScalar(-clipSpaceIBounds.fLeft), |
381 SkIntToScalar(-clipSpaceIBounds.fTop) | 346 SkIntToScalar(-clipSpaceIBounds.fTop) |
382 }; | 347 }; |
383 | 348 |
384 if (UseSWOnlyPath(this->getContext(), pipelineBuilder, rt, clipToMaskOff set, elements)) { | 349 if (UseSWOnlyPath(context, pipelineBuilder, drawContext, |
350 clipToMaskOffset, elements)) { | |
385 // The clip geometry is complex enough that it will be more efficien t to create it | 351 // The clip geometry is complex enough that it will be more efficien t to create it |
386 // entirely in software | 352 // entirely in software |
387 result = CreateSoftwareClipMask(this->getContext()->textureProvider( ), | 353 result = CreateSoftwareClipMask(context->textureProvider(), |
388 genID, | 354 genID, |
389 initialState, | 355 initialState, |
390 elements, | 356 elements, |
391 clipToMaskOffset, | 357 clipToMaskOffset, |
392 clipSpaceIBounds); | 358 clipSpaceIBounds); |
393 } else { | 359 } else { |
394 result = CreateAlphaClipMask(this->getContext(), | 360 result = CreateAlphaClipMask(context, |
395 genID, | 361 genID, |
396 initialState, | 362 initialState, |
397 elements, | 363 elements, |
398 clipToMaskOffset, | 364 clipToMaskOffset, |
399 clipSpaceIBounds); | 365 clipSpaceIBounds); |
400 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug | 366 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug |
401 SkASSERT(result); | 367 SkASSERT(result); |
402 } | 368 } |
403 | 369 |
404 if (result) { | 370 if (result) { |
405 // The mask's top left coord should be pinned to the rounded-out top left corner of | 371 // The mask's top left coord should be pinned to the rounded-out top left corner of |
406 // clipSpace bounds. We determine the mask's position WRT to the ren der target here. | 372 // clipSpace bounds. We determine the mask's position WRT to the ren der target here. |
407 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 373 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
408 rtSpaceMaskBounds.offset(-clip.origin()); | 374 rtSpaceMaskBounds.offset(-clip.origin()); |
409 out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds) ); | 375 out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds) ); |
410 return true; | 376 return true; |
411 } | 377 } |
412 // if alpha clip mask creation fails fall through to the non-AA code pat hs | 378 // if alpha clip mask creation fails fall through to the non-AA code pat hs |
413 } | 379 } |
414 | 380 |
415 // use the stencil clip if we can't represent the clip as a rectangle. | 381 // use the stencil clip if we can't represent the clip as a rectangle. |
416 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); | 382 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); |
417 this->createStencilClipMask(rt, | 383 CreateStencilClipMask(context, |
418 genID, | 384 drawContext, |
419 initialState, | 385 genID, |
420 elements, | 386 initialState, |
421 clipSpaceIBounds, | 387 elements, |
422 clipSpaceToStencilSpaceOffset); | 388 clipSpaceIBounds, |
389 clipSpaceToStencilSpaceOffset); | |
423 | 390 |
424 // This must occur after createStencilClipMask. That function may change the scissor. Also, it | 391 // This must occur after createStencilClipMask. That function may change the scissor. Also, it |
425 // only guarantees that the stencil mask is correct within the bounds it was passed, so we must | 392 // only guarantees that the stencil mask is correct within the bounds it was passed, so we must |
426 // use both stencil and scissor test to the bounds for the final draw. | 393 // use both stencil and scissor test to the bounds for the final draw. |
427 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 394 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
428 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 395 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
429 out->makeScissoredStencil(true, scissorSpaceIBounds); | 396 out->makeScissoredStencil(true, scissorSpaceIBounds); |
430 return true; | 397 return true; |
431 } | 398 } |
432 | 399 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 | 569 |
603 sk_sp<GrTexture> texture(dc->asTexture()); | 570 sk_sp<GrTexture> texture(dc->asTexture()); |
604 SkASSERT(texture); | 571 SkASSERT(texture); |
605 texture->resourcePriv().setUniqueKey(key); | 572 texture->resourcePriv().setUniqueKey(key); |
606 return texture; | 573 return texture; |
607 } | 574 } |
608 | 575 |
609 //////////////////////////////////////////////////////////////////////////////// | 576 //////////////////////////////////////////////////////////////////////////////// |
610 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 577 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
611 // (as opposed to canvas) coordinates | 578 // (as opposed to canvas) coordinates |
612 bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, | 579 bool GrClipMaskManager::CreateStencilClipMask(GrContext* context, |
580 GrDrawContext* drawContext, | |
613 int32_t elementsGenID, | 581 int32_t elementsGenID, |
614 GrReducedClip::InitialState initia lState, | 582 GrReducedClip::InitialState initia lState, |
615 const GrReducedClip::ElementList& elements, | 583 const GrReducedClip::ElementList& elements, |
616 const SkIRect& clipSpaceIBounds, | 584 const SkIRect& clipSpaceIBounds, |
617 const SkIPoint& clipSpaceToStencil Offset) { | 585 const SkIPoint& clipSpaceToStencil Offset) { |
618 SkASSERT(rt); | 586 SkASSERT(drawContext); |
619 | 587 |
620 GrStencilAttachment* stencilAttachment = this->resourceProvider()->attachSte ncilAttachment(rt); | 588 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach StencilAttachment( |
589 drawContext->accessRenderTar get()); | |
621 if (nullptr == stencilAttachment) { | 590 if (nullptr == stencilAttachment) { |
622 return false; | 591 return false; |
623 } | 592 } |
624 | 593 |
594 // TODO: these need to be swapped over to using a StencilAttachmentProxy | |
625 if (stencilAttachment->mustRenderClip(elementsGenID, clipSpaceIBounds, clipS paceToStencilOffset)) { | 595 if (stencilAttachment->mustRenderClip(elementsGenID, clipSpaceIBounds, clipS paceToStencilOffset)) { |
626 stencilAttachment->setLastClip(elementsGenID, clipSpaceIBounds, clipSpac eToStencilOffset); | 596 stencilAttachment->setLastClip(elementsGenID, clipSpaceIBounds, clipSpac eToStencilOffset); |
627 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space. | 597 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space. |
628 SkVector translate = { | 598 SkVector translate = { |
629 SkIntToScalar(clipSpaceToStencilOffset.fX), | 599 SkIntToScalar(clipSpaceToStencilOffset.fX), |
630 SkIntToScalar(clipSpaceToStencilOffset.fY) | 600 SkIntToScalar(clipSpaceToStencilOffset.fY) |
631 }; | 601 }; |
632 SkMatrix viewMatrix; | 602 SkMatrix viewMatrix; |
633 viewMatrix.setTranslate(translate); | 603 viewMatrix.setTranslate(translate); |
634 | 604 |
635 // We set the current clip to the bounds so that our recursive draws are scissored to them. | 605 // We set the current clip to the bounds so that our recursive draws are scissored to them. |
636 SkIRect stencilSpaceIBounds(clipSpaceIBounds); | 606 SkIRect stencilSpaceIBounds(clipSpaceIBounds); |
637 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 607 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
638 GrFixedClip clip(stencilSpaceIBounds); | 608 GrFixedClip clip(stencilSpaceIBounds); |
639 | 609 |
640 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, | 610 drawContext->drawContextPriv().clearStencilClip( |
641 GrReducedClip::kAllIn_InitialState == initialState, rt); | 611 stencilSpaceIBounds, |
612 GrReducedClip::kAllIn_InitialState = = initialState); | |
642 | 613 |
643 // walk through each clip element and perform its set op | 614 // walk through each clip element and perform its set op |
644 // with the existing clip. | 615 // with the existing clip. |
645 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge t(); iter.next()) { | 616 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge t(); iter.next()) { |
646 const Element* element = iter.get(); | 617 const Element* element = iter.get(); |
647 | 618 |
648 GrPipelineBuilder pipelineBuilder; | |
649 pipelineBuilder.setRenderTarget(rt); | |
650 | |
651 pipelineBuilder.setDisableColorXPFactory(); | |
652 | |
653 // if the target is MSAA then we want MSAA enabled when the clip is soft | |
654 if (rt->isStencilBufferMultisampled()) { | |
655 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, e lement->isAA()); | |
656 } | |
657 | |
658 bool fillInverted = false; | 619 bool fillInverted = false; |
659 // enabled at bottom of loop | 620 // enabled at bottom of loop |
660 clip.enableStencilClip(false); | 621 clip.enableStencilClip(false); |
661 | 622 |
662 // This will be used to determine whether the clip shape can be rend ered into the | 623 // This will be used to determine whether the clip shape can be rend ered into the |
663 // stencil with arbitrary stencil settings. | 624 // stencil with arbitrary stencil settings. |
664 GrPathRenderer::StencilSupport stencilSupport; | 625 GrPathRenderer::StencilSupport stencilSupport; |
665 | 626 |
666 SkRegion::Op op = element->getOp(); | 627 SkRegion::Op op = element->getOp(); |
667 | 628 |
668 GrPathRenderer* pr = nullptr; | 629 GrPathRenderer* pr = nullptr; |
669 SkPath clipPath; | 630 SkPath clipPath; |
670 if (Element::kRect_Type == element->getType()) { | 631 if (Element::kRect_Type == element->getType()) { |
671 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 632 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
672 fillInverted = false; | 633 fillInverted = false; |
673 } else { | 634 } else { |
674 element->asPath(&clipPath); | 635 element->asPath(&clipPath); |
675 fillInverted = clipPath.isInverseFillType(); | 636 fillInverted = clipPath.isInverseFillType(); |
676 if (fillInverted) { | 637 if (fillInverted) { |
677 clipPath.toggleInverseFillType(); | 638 clipPath.toggleInverseFillType(); |
678 } | 639 } |
679 | 640 |
680 SkASSERT(!pipelineBuilder.hasUserStencilSettings()); | |
681 | |
682 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 641 GrPathRenderer::CanDrawPathArgs canDrawArgs; |
683 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps (); | 642 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); |
684 canDrawArgs.fViewMatrix = &viewMatrix; | 643 canDrawArgs.fViewMatrix = &viewMatrix; |
685 canDrawArgs.fPath = &clipPath; | 644 canDrawArgs.fPath = &clipPath; |
686 canDrawArgs.fStyle = &GrStyle::SimpleFill(); | 645 canDrawArgs.fStyle = &GrStyle::SimpleFill(); |
687 canDrawArgs.fAntiAlias = false; | 646 canDrawArgs.fAntiAlias = false; |
688 canDrawArgs.fHasUserStencilSettings = pipelineBuilder.hasUserSte ncilSettings(); | 647 canDrawArgs.fHasUserStencilSettings = false; |
689 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampl ed(); | 648 canDrawArgs.fIsStencilBufferMSAA = drawContext->isStencilBufferM ultisampled(); |
690 | 649 |
691 pr = this->getContext()->drawingManager()->getPathRenderer(canDr awArgs, false, | 650 pr = context->drawingManager()->getPathRenderer(canDrawArgs, fal se, |
692 GrPat hRendererChain::kStencilOnly_DrawType, | 651 GrPathRendererCh ain::kStencilOnly_DrawType, |
693 &sten cilSupport); | 652 &stencilSupport) ; |
694 if (nullptr == pr) { | 653 if (!pr) { |
695 return false; | 654 return false; |
696 } | 655 } |
697 } | 656 } |
698 | 657 |
699 bool canRenderDirectToStencil = | 658 bool canRenderDirectToStencil = |
700 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; | 659 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; |
701 bool drawDirectToClip; // Given the renderer, the element, | 660 bool drawDirectToClip; // Given the renderer, the element, |
702 // fill rule, and set operation should | 661 // fill rule, and set operation should |
703 // we render the element directly to | 662 // we render the element directly to |
704 // stencil bit used for clipping. | 663 // stencil bit used for clipping. |
705 GrUserStencilSettings const* const* stencilPasses = | 664 GrUserStencilSettings const* const* stencilPasses = |
706 GrStencilSettings::GetClipPasses(op, canRenderDirectToStencil, f illInverted, | 665 GrStencilSettings::GetClipPasses(op, canRenderDirectToStencil, f illInverted, |
707 &drawDirectToClip); | 666 &drawDirectToClip); |
708 | 667 |
709 // draw the element to the client stencil bits if necessary | 668 // draw the element to the client stencil bits if necessary |
710 if (!drawDirectToClip) { | 669 if (!drawDirectToClip) { |
711 static constexpr GrUserStencilSettings kDrawToStencil( | 670 static constexpr GrUserStencilSettings kDrawToStencil( |
712 GrUserStencilSettings::StaticInit< | 671 GrUserStencilSettings::StaticInit< |
713 0x0000, | 672 0x0000, |
714 GrUserStencilTest::kAlways, | 673 GrUserStencilTest::kAlways, |
715 0xffff, | 674 0xffff, |
716 GrUserStencilOp::kIncMaybeClamp, | 675 GrUserStencilOp::kIncMaybeClamp, |
717 GrUserStencilOp::kIncMaybeClamp, | 676 GrUserStencilOp::kIncMaybeClamp, |
718 0xffff>() | 677 0xffff>() |
719 ); | 678 ); |
720 if (Element::kRect_Type == element->getType()) { | 679 if (Element::kRect_Type == element->getType()) { |
721 pipelineBuilder.setUserStencil(&kDrawToStencil); | 680 DrawNonAARect(drawContext, clip, viewMatrix, |
722 | 681 element->getRect(), element->isAA(), &kDrawToS tencil); |
723 draw_non_aa_rect(fDrawTarget, pipelineBuilder, clip, GrColor _WHITE, viewMatrix, | |
724 element->getRect()); | |
725 } else { | 682 } else { |
726 if (!clipPath.isEmpty()) { | 683 if (!clipPath.isEmpty()) { |
727 if (canRenderDirectToStencil) { | 684 if (canRenderDirectToStencil) { |
728 pipelineBuilder.setUserStencil(&kDrawToStencil); | 685 GrPaint paint; |
686 paint.setXPFactory(GrDisableColorXPFactory::Create() ); | |
bungeman-skia
2016/06/03 23:57:03
leak
| |
687 paint.setAntiAlias(element->isAA()); | |
729 | 688 |
730 GrPathRenderer::DrawPathArgs args; | 689 GrPathRenderer::DrawPathArgs args; |
731 args.fTarget = fDrawTarget; | 690 args.fResourceProvider = context->resourceProvider() ; |
732 args.fResourceProvider = this->getContext()->resourc eProvider(); | 691 args.fPaint = &paint; |
733 args.fPipelineBuilder = &pipelineBuilder; | 692 args.fUserStencilSettings = &kDrawToStencil; |
693 args.fDrawContext = drawContext; | |
734 args.fClip = &clip; | 694 args.fClip = &clip; |
735 args.fColor = GrColor_WHITE; | 695 args.fColor = GrColor_WHITE; |
736 args.fViewMatrix = &viewMatrix; | 696 args.fViewMatrix = &viewMatrix; |
737 args.fPath = &clipPath; | 697 args.fPath = &clipPath; |
738 args.fStyle = &GrStyle::SimpleFill(); | 698 args.fStyle = &GrStyle::SimpleFill(); |
739 args.fAntiAlias = false; | 699 args.fAntiAlias = false; |
740 args.fGammaCorrect = false; | 700 args.fGammaCorrect = false; |
741 pr->drawPath(args); | 701 pr->drawPath(args); |
742 } else { | 702 } else { |
743 GrPathRenderer::StencilPathArgs args; | 703 GrPathRenderer::StencilPathArgs args; |
744 args.fTarget = fDrawTarget; | 704 args.fResourceProvider = context->resourceProvider() ; |
745 args.fResourceProvider = this->getContext()->resourc eProvider(); | 705 args.fDrawContext = drawContext; |
746 args.fPipelineBuilder = &pipelineBuilder; | |
747 args.fClip = &clip; | 706 args.fClip = &clip; |
748 args.fViewMatrix = &viewMatrix; | 707 args.fViewMatrix = &viewMatrix; |
749 args.fPath = &clipPath; | 708 args.fPath = &clipPath; |
709 args.fIsAA = element->isAA(); | |
750 pr->stencilPath(args); | 710 pr->stencilPath(args); |
751 } | 711 } |
752 } | 712 } |
753 } | 713 } |
754 } | 714 } |
755 | 715 |
756 // now we modify the clip bit by rendering either the clip | 716 // now we modify the clip bit by rendering either the clip |
757 // element directly or a bounding rect of the entire clip. | 717 // element directly or a bounding rect of the entire clip. |
758 clip.enableStencilClip(true); | 718 clip.enableStencilClip(true); |
759 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass ; ++pass) { | 719 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass ; ++pass) { |
760 pipelineBuilder.setUserStencil(*pass); | |
761 | 720 |
762 if (drawDirectToClip) { | 721 if (drawDirectToClip) { |
763 if (Element::kRect_Type == element->getType()) { | 722 if (Element::kRect_Type == element->getType()) { |
764 draw_non_aa_rect(fDrawTarget, pipelineBuilder, clip, GrC olor_WHITE, | 723 DrawNonAARect(drawContext, clip, |
765 viewMatrix, element->getRect()); | 724 viewMatrix, element->getRect(), element->i sAA(), *pass); |
766 } else { | 725 } else { |
726 GrPaint paint; | |
727 paint.setXPFactory(GrDisableColorXPFactory::Create()); | |
bungeman-skia
2016/06/03 23:57:03
leak
| |
728 paint.setAntiAlias(element->isAA()); | |
729 | |
767 GrPathRenderer::DrawPathArgs args; | 730 GrPathRenderer::DrawPathArgs args; |
768 args.fTarget = fDrawTarget; | 731 args.fResourceProvider = context->resourceProvider(); |
769 args.fResourceProvider = this->getContext()->resourcePro vider(); | 732 args.fPaint = &paint; |
770 args.fPipelineBuilder = &pipelineBuilder; | 733 args.fUserStencilSettings = *pass; |
734 args.fDrawContext = drawContext; | |
771 args.fClip = &clip; | 735 args.fClip = &clip; |
772 args.fColor = GrColor_WHITE; | 736 args.fColor = GrColor_WHITE; |
773 args.fViewMatrix = &viewMatrix; | 737 args.fViewMatrix = &viewMatrix; |
774 args.fPath = &clipPath; | 738 args.fPath = &clipPath; |
775 args.fStyle = &GrStyle::SimpleFill(); | 739 args.fStyle = &GrStyle::SimpleFill(); |
776 args.fAntiAlias = false; | 740 args.fAntiAlias = false; |
777 args.fGammaCorrect = false; | 741 args.fGammaCorrect = false; |
778 pr->drawPath(args); | 742 pr->drawPath(args); |
779 } | 743 } |
780 } else { | 744 } else { |
781 // The view matrix is setup to do clip space -> stencil spac e translation, so | 745 // The view matrix is setup to do clip space -> stencil spac e translation, so |
782 // draw rect in clip space. | 746 // draw rect in clip space. |
783 draw_non_aa_rect(fDrawTarget, pipelineBuilder, clip, GrColor _WHITE, viewMatrix, | 747 DrawNonAARect(drawContext, clip, viewMatrix, |
784 SkRect::Make(clipSpaceIBounds)); | 748 SkRect::Make(clipSpaceIBounds), false, *pass); |
785 } | 749 } |
786 } | 750 } |
787 } | 751 } |
788 } | 752 } |
789 return true; | 753 return true; |
790 } | 754 } |
791 | 755 |
792 //////////////////////////////////////////////////////////////////////////////// | 756 //////////////////////////////////////////////////////////////////////////////// |
793 sk_sp<GrTexture> GrClipMaskManager::CreateSoftwareClipMask( | 757 sk_sp<GrTexture> GrClipMaskManager::CreateSoftwareClipMask( |
794 GrTextureProvider* texProvid er, | 758 GrTextureProvider* texProvid er, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
859 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); | 823 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); |
860 if (!result) { | 824 if (!result) { |
861 return nullptr; | 825 return nullptr; |
862 } | 826 } |
863 result->resourcePriv().setUniqueKey(key); | 827 result->resourcePriv().setUniqueKey(key); |
864 | 828 |
865 helper.toTexture(result.get()); | 829 helper.toTexture(result.get()); |
866 | 830 |
867 return result; | 831 return result; |
868 } | 832 } |
OLD | NEW |