Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: src/gpu/GrClipStackClip.cpp

Issue 2138083002: skip call to clip::apply when clip is wide open Base URL: https://chromium.googlesource.com/skia.git@llist
Patch Set: rm gcmm Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrClipStackClip.h ('k') | src/gpu/GrDrawTarget.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "GrClipStackClip.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 "GrGpuResourcePriv.h" 12 #include "GrGpuResourcePriv.h"
13 #include "GrPaint.h" 13 #include "GrPaint.h"
14 #include "GrPathRenderer.h" 14 #include "GrPathRenderer.h"
15 #include "GrRenderTarget.h" 15 #include "GrRenderTarget.h"
16 #include "GrRenderTargetPriv.h" 16 #include "GrRenderTargetPriv.h"
17 #include "GrResourceProvider.h" 17 #include "GrResourceProvider.h"
18 #include "GrStencilAttachment.h" 18 #include "GrStencilAttachment.h"
19 #include "GrSWMaskHelper.h" 19 #include "GrSWMaskHelper.h"
20 #include "SkRasterClip.h" 20 #include "SkRasterClip.h"
21 #include "SkTLazy.h" 21 #include "SkTLazy.h"
22 #include "batches/GrRectBatchFactory.h" 22 #include "batches/GrRectBatchFactory.h"
23 #include "effects/GrConvexPolyEffect.h" 23 #include "effects/GrConvexPolyEffect.h"
24 #include "effects/GrPorterDuffXferProcessor.h" 24 #include "effects/GrPorterDuffXferProcessor.h"
25 #include "effects/GrRRectEffect.h" 25 #include "effects/GrRRectEffect.h"
26 #include "effects/GrTextureDomain.h" 26 #include "effects/GrTextureDomain.h"
27 27
28 typedef SkClipStack::Element Element; 28 typedef SkClipStack::Element Element;
29 29
30 bool GrClipStackClip::quickContains(const SkRect& rect) const {
31 if (!fStack) {
32 return true;
33 }
34 return fStack->quickContains(rect.makeOffset(SkIntToScalar(fOrigin.x()),
35 SkIntToScalar(fOrigin.y())));
36 }
37
38 void GrClipStackClip::getConservativeBounds(int width, int height, SkIRect* devR esult,
39 bool* isIntersectionOfRects) const {
40 if (!fStack) {
41 devResult->setXYWH(0, 0, width, height);
42 if (isIntersectionOfRects) {
43 *isIntersectionOfRects = true;
44 }
45 return;
46 }
47 SkRect devBounds;
48 fStack->getConservativeBounds(-fOrigin.x(), -fOrigin.y(), width, height, &de vBounds,
49 isIntersectionOfRects);
50 devBounds.roundOut(devResult);
51 }
52
30 static const int kMaxAnalyticElements = 4; 53 static const int kMaxAnalyticElements = 4;
31 54
32 //////////////////////////////////////////////////////////////////////////////// 55 ////////////////////////////////////////////////////////////////////////////////
33 // set up the draw state to enable the aa clipping mask. Besides setting up the 56 // set up the draw state to enable the aa clipping mask. Besides setting up the
34 // stage matrix this also alters the vertex layout 57 // stage matrix this also alters the vertex layout
35 static sk_sp<GrFragmentProcessor> create_fp_for_mask(GrTexture* result, 58 static sk_sp<GrFragmentProcessor> create_fp_for_mask(GrTexture* result,
36 const SkIRect &devBound) { 59 const SkIRect &devBound) {
37 SkMatrix mat; 60 SkMatrix mat;
38 // We use device coords to compute the texture coordinates. We set our matri x to be a 61 // We use device coords to compute the texture coordinates. We set our matri x to be a
39 // translation to the devBound, and then a scaling matrix to normalized coor ds. 62 // translation to the devBound, and then a scaling matrix to normalized coor ds.
40 mat.setIDiv(result->width(), result->height()); 63 mat.setIDiv(result->width(), result->height());
41 mat.preTranslate(SkIntToScalar(-devBound.fLeft), 64 mat.preTranslate(SkIntToScalar(-devBound.fLeft),
42 SkIntToScalar(-devBound.fTop)); 65 SkIntToScalar(-devBound.fTop));
43 66
44 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); 67 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height());
45 return sk_sp<GrFragmentProcessor>(GrTextureDomainEffect::Make( 68 return sk_sp<GrFragmentProcessor>(GrTextureDomainEffect::Make(
46 result, 69 result,
47 mat, 70 mat,
48 GrTextureDomain::MakeTexelDomain(result , domainTexels), 71 GrTextureDomain::MakeTexelDomain(result , domainTexels),
49 GrTextureDomain::kDecal_Mode, 72 GrTextureDomain::kDecal_Mode,
50 GrTextureParams::kNone_FilterMode, 73 GrTextureParams::kNone_FilterMode,
51 kDevice_GrCoordSet)); 74 kDevice_GrCoordSet));
52 } 75 }
53 76
54 // Does the path in 'element' require SW rendering? If so, return true (and, 77 // Does the path in 'element' require SW rendering? If so, return true (and,
55 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set 78 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set
56 // 'prOut' to the non-SW path renderer that will do the job). 79 // 'prOut' to the non-SW path renderer that will do the job).
57 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, 80 bool GrClipStackClip::PathNeedsSWRenderer(GrContext* context,
58 bool hasUserStencilSettings, 81 bool hasUserStencilSettings,
59 const GrDrawContext* drawContext, 82 const GrDrawContext* drawContext,
60 const SkMatrix& viewMatrix, 83 const SkMatrix& viewMatrix,
61 const Element* element, 84 const Element* element,
62 GrPathRenderer** prOut, 85 GrPathRenderer** prOut,
63 bool needsStencil) { 86 bool needsStencil) {
64 if (Element::kRect_Type == element->getType()) { 87 if (Element::kRect_Type == element->getType()) {
65 // rects can always be drawn directly w/o using the software path 88 // rects can always be drawn directly w/o using the software path
66 // TODO: skip rrects once we're drawing them directly. 89 // TODO: skip rrects once we're drawing them directly.
67 if (prOut) { 90 if (prOut) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 } 130 }
108 return SkToBool(!pr); 131 return SkToBool(!pr);
109 } 132 }
110 } 133 }
111 134
112 /* 135 /*
113 * This method traverses the clip stack to see if the GrSoftwarePathRenderer 136 * This method traverses the clip stack to see if the GrSoftwarePathRenderer
114 * will be used on any element. If so, it returns true to indicate that the 137 * will be used on any element. If so, it returns true to indicate that the
115 * entire clip should be rendered in SW and then uploaded en masse to the gpu. 138 * entire clip should be rendered in SW and then uploaded en masse to the gpu.
116 */ 139 */
117 bool GrClipMaskManager::UseSWOnlyPath(GrContext* context, 140 bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
118 const GrPipelineBuilder& pipelineBuilder, 141 const GrPipelineBuilder& pipelineBuilder,
119 const GrDrawContext* drawContext, 142 const GrDrawContext* drawContext,
120 const SkVector& clipToMaskOffset, 143 const SkVector& clipToMaskOffset,
121 const GrReducedClip::ElementList& elements ) { 144 const GrReducedClip::ElementList& elements) {
122 // TODO: generalize this function so that when 145 // TODO: generalize this function so that when
123 // a clip gets complex enough it can just be done in SW regardless 146 // a clip gets complex enough it can just be done in SW regardless
124 // of whether it would invoke the GrSoftwarePathRenderer. 147 // of whether it would invoke the GrSoftwarePathRenderer.
125 148
126 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip 149 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
127 // space. 150 // space.
128 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY); 151 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY);
129 152
130 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 153 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
131 const Element* element = iter.get(); 154 const Element* element = iter.get();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 iter.next(); 238 iter.next();
216 } 239 }
217 240
218 *resultFP = nullptr; 241 *resultFP = nullptr;
219 if (fps.count()) { 242 if (fps.count()) {
220 *resultFP = GrFragmentProcessor::RunInSeries(fps.begin(), fps.count()); 243 *resultFP = GrFragmentProcessor::RunInSeries(fps.begin(), fps.count());
221 } 244 }
222 return true; 245 return true;
223 } 246 }
224 247
225 ////////////////////////////////////////////////////////////////////////////////
226 // sort out what kind of clip mask needs to be created: alpha, stencil,
227 // scissor, or entirely software
228 bool GrClipMaskManager::SetupClipping(GrContext* context,
229 const GrPipelineBuilder& pipelineBuilder,
230 GrDrawContext* drawContext,
231 const GrClipStackClip& clip,
232 const SkRect* origDevBounds,
233 GrAppliedClip* out) {
234 if (!clip.clipStack() || clip.clipStack()->isWideOpen()) {
235 return true;
236 }
237
238 GrReducedClip::ElementList elements;
239 int32_t genID = 0;
240 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat e;
241 SkIRect clipSpaceIBounds;
242 bool requiresAA = false;
243
244 SkIRect clipSpaceReduceQueryBounds;
245 SkRect devBounds;
246 if (origDevBounds) {
247 if (!devBounds.intersect(SkRect::MakeIWH(drawContext->width(), drawConte xt->height()),
248 *origDevBounds)) {
249 return false;
250 }
251 devBounds.roundOut(&clipSpaceReduceQueryBounds);
252 clipSpaceReduceQueryBounds.offset(clip.origin());
253 } else {
254 devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height()) ;
255 clipSpaceReduceQueryBounds.setXYWH(0, 0, drawContext->width(), drawConte xt->height());
256 clipSpaceReduceQueryBounds.offset(clip.origin());
257 }
258 GrReducedClip::ReduceClipStack(*clip.clipStack(),
259 clipSpaceReduceQueryBounds,
260 &elements,
261 &genID,
262 &initialState,
263 &clipSpaceIBounds,
264 &requiresAA);
265 if (elements.isEmpty()) {
266 if (GrReducedClip::kAllOut_InitialState == initialState) {
267 return false;
268 } else {
269 SkIRect scissorSpaceIBounds(clipSpaceIBounds);
270 scissorSpaceIBounds.offset(-clip.origin());
271 if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) {
272 out->makeScissored(scissorSpaceIBounds);
273 }
274 return true;
275 }
276 }
277
278 // An element count of 4 was chosen because of the common pattern in Blink o f:
279 // isect RR
280 // diff RR
281 // isect convex_poly
282 // isect convex_poly
283 // when drawing rounded div borders. This could probably be tuned based on a
284 // configuration's relative costs of switching RTs to generate a mask vs
285 // longer shaders.
286 if (elements.count() <= kMaxAnalyticElements) {
287 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX),
288 SkIntToScalar(-clip.origin().fY) };
289 // When there are multiple samples we want to do per-sample clipping, no t compute a
290 // fractional pixel coverage.
291 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled();
292 if (disallowAnalyticAA && !drawContext->numColorSamples()) {
293 // With a single color sample, any coverage info is lost from color once it hits the
294 // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe
295 // is multisampled.
296 disallowAnalyticAA = pipelineBuilder.isHWAntialias() ||
297 pipelineBuilder.hasUserStencilSettings();
298 }
299 sk_sp<GrFragmentProcessor> clipFP;
300 if (requiresAA &&
301 get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTOf fset, devBounds,
302 &clipFP)) {
303 SkIRect scissorSpaceIBounds(clipSpaceIBounds);
304 scissorSpaceIBounds.offset(-clip.origin());
305 if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) {
306 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds );
307 return true;
308 }
309 out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBounds ));
310 return true;
311 }
312 }
313
314 // If the stencil buffer is multisampled we can use it to do everything.
315 if (!drawContext->isStencilBufferMultisampled() && requiresAA) {
316 sk_sp<GrTexture> result;
317
318 // The top-left of the mask corresponds to the top-left corner of the bo unds.
319 SkVector clipToMaskOffset = {
320 SkIntToScalar(-clipSpaceIBounds.fLeft),
321 SkIntToScalar(-clipSpaceIBounds.fTop)
322 };
323
324 if (UseSWOnlyPath(context, pipelineBuilder, drawContext,
325 clipToMaskOffset, elements)) {
326 // The clip geometry is complex enough that it will be more efficien t to create it
327 // entirely in software
328 result = CreateSoftwareClipMask(context->textureProvider(),
329 genID,
330 initialState,
331 elements,
332 clipToMaskOffset,
333 clipSpaceIBounds);
334 } else {
335 result = CreateAlphaClipMask(context,
336 genID,
337 initialState,
338 elements,
339 clipToMaskOffset,
340 clipSpaceIBounds);
341 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug
342 SkASSERT(result);
343 }
344
345 if (result) {
346 // The mask's top left coord should be pinned to the rounded-out top left corner of
347 // clipSpace bounds. We determine the mask's position WRT to the ren der target here.
348 SkIRect rtSpaceMaskBounds = clipSpaceIBounds;
349 rtSpaceMaskBounds.offset(-clip.origin());
350 out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds) ,
351 SkRect::Make(rtSpaceMaskBounds));
352 return true;
353 }
354 // if alpha clip mask creation fails fall through to the non-AA code pat hs
355 }
356
357 // use the stencil clip if we can't represent the clip as a rectangle.
358 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin();
359 CreateStencilClipMask(context,
360 drawContext,
361 genID,
362 initialState,
363 elements,
364 clipSpaceIBounds,
365 clipSpaceToStencilSpaceOffset);
366
367 // This must occur after createStencilClipMask. That function may change the scissor. Also, it
368 // only guarantees that the stencil mask is correct within the bounds it was passed, so we must
369 // use both stencil and scissor test to the bounds for the final draw.
370 SkIRect scissorSpaceIBounds(clipSpaceIBounds);
371 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
372 out->makeScissoredStencil(scissorSpaceIBounds);
373 return true;
374 }
375
376 static bool stencil_element(GrDrawContext* dc, 248 static bool stencil_element(GrDrawContext* dc,
377 const GrFixedClip& clip, 249 const GrFixedClip& clip,
378 const GrUserStencilSettings* ss, 250 const GrUserStencilSettings* ss,
379 const SkMatrix& viewMatrix, 251 const SkMatrix& viewMatrix,
380 const SkClipStack::Element* element) { 252 const SkClipStack::Element* element) {
381 253
382 // TODO: Draw rrects directly here. 254 // TODO: Draw rrects directly here.
383 switch (element->getType()) { 255 switch (element->getType()) {
384 case Element::kEmpty_Type: 256 case Element::kEmpty_Type:
385 SkDEBUGFAIL("Should never get here with an empty element."); 257 SkDEBUGFAIL("Should never get here with an empty element.");
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 // Create a 8-bit clip mask in alpha 312 // Create a 8-bit clip mask in alpha
441 313
442 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey * key) { 314 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey * key) {
443 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 315 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
444 GrUniqueKey::Builder builder(key, kDomain, 3); 316 GrUniqueKey::Builder builder(key, kDomain, 3);
445 builder[0] = clipGenID; 317 builder[0] = clipGenID;
446 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16); 318 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16);
447 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); 319 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16);
448 } 320 }
449 321
450 sk_sp<GrTexture> GrClipMaskManager::CreateAlphaClipMask(GrContext* context, 322 sk_sp<GrTexture> CreateAlphaClipMask(GrContext* context,
451 int32_t elementsGenID, 323 int32_t elementsGenID,
452 GrReducedClip::InitialSt ate initialState, 324 GrReducedClip::InitialSt ate initialState,
453 const GrReducedClip::Ele mentList& elements, 325 const GrReducedClip::Ele mentList& elements,
454 const SkVector& clipToMa skOffset, 326 const SkVector& clipToMa skOffset,
455 const SkIRect& clipSpace IBounds) { 327 const SkIRect& clipSpace IBounds) {
456 GrResourceProvider* resourceProvider = context->resourceProvider(); 328 GrResourceProvider* resourceProvider = context->resourceProvider();
457 GrUniqueKey key; 329 GrUniqueKey key;
458 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); 330 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
459 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key) ) { 331 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key) ) {
460 return sk_sp<GrTexture>(texture); 332 return sk_sp<GrTexture>(texture);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 417
546 sk_sp<GrTexture> texture(dc->asTexture()); 418 sk_sp<GrTexture> texture(dc->asTexture());
547 SkASSERT(texture); 419 SkASSERT(texture);
548 texture->resourcePriv().setUniqueKey(key); 420 texture->resourcePriv().setUniqueKey(key);
549 return texture; 421 return texture;
550 } 422 }
551 423
552 //////////////////////////////////////////////////////////////////////////////// 424 ////////////////////////////////////////////////////////////////////////////////
553 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device 425 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device
554 // (as opposed to canvas) coordinates 426 // (as opposed to canvas) coordinates
555 bool GrClipMaskManager::CreateStencilClipMask(GrContext* context, 427 bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
556 GrDrawContext* drawContext, 428 GrDrawContext* drawContext,
557 int32_t elementsGenID, 429 int32_t elementsGenID,
558 GrReducedClip::InitialState initia lState, 430 GrReducedClip::InitialState initialS tate,
559 const GrReducedClip::ElementList& elements, 431 const GrReducedClip::ElementList& el ements,
560 const SkIRect& clipSpaceIBounds, 432 const SkIRect& clipSpaceIBounds,
561 const SkIPoint& clipSpaceToStencil Offset) { 433 const SkIPoint& clipSpaceToStencilOf fset) {
562 SkASSERT(drawContext); 434 SkASSERT(drawContext);
563 435
564 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach StencilAttachment( 436 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach StencilAttachment(
565 drawContext->accessRenderTar get()); 437 drawContext->accessRenderTar get());
566 if (nullptr == stencilAttachment) { 438 if (nullptr == stencilAttachment) {
567 return false; 439 return false;
568 } 440 }
569 441
570 // TODO: these need to be swapped over to using a StencilAttachmentProxy 442 // TODO: these need to be swapped over to using a StencilAttachmentProxy
571 if (stencilAttachment->mustRenderClip(elementsGenID, clipSpaceIBounds, clipS paceToStencilOffset)) { 443 if (stencilAttachment->mustRenderClip(elementsGenID, clipSpaceIBounds, clipS paceToStencilOffset)) {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 drawContext->drawContextPriv().stencilRect(clip, *pass, fals e, viewMatrix, 600 drawContext->drawContextPriv().stencilRect(clip, *pass, fals e, viewMatrix,
729 SkRect::Make(clip SpaceIBounds)); 601 SkRect::Make(clip SpaceIBounds));
730 } 602 }
731 } 603 }
732 } 604 }
733 } 605 }
734 return true; 606 return true;
735 } 607 }
736 608
737 //////////////////////////////////////////////////////////////////////////////// 609 ////////////////////////////////////////////////////////////////////////////////
738 sk_sp<GrTexture> GrClipMaskManager::CreateSoftwareClipMask( 610 sk_sp<GrTexture> CreateSoftwareClipMask(
739 GrTextureProvider* texProvid er, 611 GrTextureProvider* texProvid er,
740 int32_t elementsGenID, 612 int32_t elementsGenID,
741 GrReducedClip::InitialState initialState, 613 GrReducedClip::InitialState initialState,
742 const GrReducedClip::Element List& elements, 614 const GrReducedClip::Element List& elements,
743 const SkVector& clipToMaskOf fset, 615 const SkVector& clipToMaskOf fset,
744 const SkIRect& clipSpaceIBou nds) { 616 const SkIRect& clipSpaceIBou nds) {
745 GrUniqueKey key; 617 GrUniqueKey key;
746 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); 618 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
747 if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) { 619 if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) {
748 return sk_sp<GrTexture>(texture); 620 return sk_sp<GrTexture>(texture);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); 677 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc));
806 if (!result) { 678 if (!result) {
807 return nullptr; 679 return nullptr;
808 } 680 }
809 result->resourcePriv().setUniqueKey(key); 681 result->resourcePriv().setUniqueKey(key);
810 682
811 helper.toTexture(result.get()); 683 helper.toTexture(result.get());
812 684
813 return result; 685 return result;
814 } 686 }
687
688 bool GrClipStackClip::apply(GrContext* context,
689 const GrPipelineBuilder& pipelineBuilder, GrDrawCont ext* drawContext,
690 const SkRect* origDevBounds, GrAppliedClip* out) con st {
691 //////////////////////////////////////////////////////////////////////////// ////
692 // sort out what kind of clip mask needs to be created: alpha, stencil,
693 // scissor, or entirely software
694
695 GrReducedClip::ElementList elements;
696 int32_t genID = 0;
697 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat e;
698 SkIRect clipSpaceIBounds;
699 bool requiresAA = false;
700
701 SkIRect clipSpaceReduceQueryBounds;
702 SkRect devBounds;
703 if (origDevBounds) {
704 if (!devBounds.intersect(SkRect::MakeIWH(drawContext->width(), drawConte xt->height()),
705 *origDevBounds)) {
706 return false;
707 }
708 devBounds.roundOut(&clipSpaceReduceQueryBounds);
709 clipSpaceReduceQueryBounds.offset(this->origin());
710 } else {
711 devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height()) ;
712 clipSpaceReduceQueryBounds.setXYWH(0, 0, drawContext->width(), drawConte xt->height());
713 clipSpaceReduceQueryBounds.offset(this->origin());
714 }
715 GrReducedClip::ReduceClipStack(*this->clipStack(),
716 clipSpaceReduceQueryBounds,
717 &elements,
718 &genID,
719 &initialState,
720 &clipSpaceIBounds,
721 &requiresAA);
722 if (elements.isEmpty()) {
723 if (GrReducedClip::kAllOut_InitialState == initialState) {
724 return false;
725 } else {
726 SkIRect scissorSpaceIBounds(clipSpaceIBounds);
727 scissorSpaceIBounds.offset(-this->origin());
728 if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) {
729 out->makeScissored(scissorSpaceIBounds);
730 }
731 return true;
732 }
733 }
734
735 // An element count of 4 was chosen because of the common pattern in Blink o f:
736 // isect RR
737 // diff RR
738 // isect convex_poly
739 // isect convex_poly
740 // when drawing rounded div borders. This could probably be tuned based on a
741 // configuration's relative costs of switching RTs to generate a mask vs
742 // longer shaders.
743 if (elements.count() <= kMaxAnalyticElements) {
744 SkVector clipToRTOffset = { SkIntToScalar(-this->origin().fX),
745 SkIntToScalar(-this->origin().fY) };
746 // When there are multiple samples we want to do per-sample clipping, no t compute a
747 // fractional pixel coverage.
748 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled();
749 if (disallowAnalyticAA && !drawContext->numColorSamples()) {
750 // With a single color sample, any coverage info is lost from color once it hits the
751 // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe
752 // is multisampled.
753 disallowAnalyticAA = pipelineBuilder.isHWAntialias() ||
754 pipelineBuilder.hasUserStencilSettings();
755 }
756 sk_sp<GrFragmentProcessor> clipFP;
757 if (requiresAA &&
758 get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTOf fset, devBounds,
759 &clipFP)) {
760 SkIRect scissorSpaceIBounds(clipSpaceIBounds);
761 scissorSpaceIBounds.offset(-this->origin());
762 if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) {
763 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds );
764 return true;
765 }
766 out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBounds ));
767 return true;
768 }
769 }
770
771 // If the stencil buffer is multisampled we can use it to do everything.
772 if (!drawContext->isStencilBufferMultisampled() && requiresAA) {
773 sk_sp<GrTexture> result;
774
775 // The top-left of the mask corresponds to the top-left corner of the bo unds.
776 SkVector clipToMaskOffset = {
777 SkIntToScalar(-clipSpaceIBounds.fLeft),
778 SkIntToScalar(-clipSpaceIBounds.fTop)
779 };
780
781 if (UseSWOnlyPath(context, pipelineBuilder, drawContext,
782 clipToMaskOffset, elements)) {
783 // The clip geometry is complex enough that it will be more efficien t to create it
784 // entirely in software
785 result = CreateSoftwareClipMask(context->textureProvider(),
786 genID,
787 initialState,
788 elements,
789 clipToMaskOffset,
790 clipSpaceIBounds);
791 } else {
792 result = CreateAlphaClipMask(context,
793 genID,
794 initialState,
795 elements,
796 clipToMaskOffset,
797 clipSpaceIBounds);
798 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug
799 SkASSERT(result);
800 }
801
802 if (result) {
803 // The mask's top left coord should be pinned to the rounded-out top left corner of
804 // clipSpace bounds. We determine the mask's position WRT to the ren der target here.
805 SkIRect rtSpaceMaskBounds = clipSpaceIBounds;
806 rtSpaceMaskBounds.offset(-this->origin());
807 out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds) ,
808 SkRect::Make(rtSpaceMaskBounds));
809 return true;
810 }
811 // if alpha clip mask creation fails fall through to the non-AA code pat hs
812 }
813
814 // use the stencil clip if we can't represent the clip as a rectangle.
815 SkIPoint clipSpaceToStencilSpaceOffset = -this->origin();
816 CreateStencilClipMask(context,
817 drawContext,
818 genID,
819 initialState,
820 elements,
821 clipSpaceIBounds,
822 clipSpaceToStencilSpaceOffset);
823
824 // This must occur after createStencilClipMask. That function may change the scissor. Also, it
825 // only guarantees that the stencil mask is correct within the bounds it was passed, so we must
826 // use both stencil and scissor test to the bounds for the final draw.
827 SkIRect scissorSpaceIBounds(clipSpaceIBounds);
828 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
829 out->makeScissoredStencil(scissorSpaceIBounds);
830 return true;
831 }
OLDNEW
« no previous file with comments | « src/gpu/GrClipStackClip.h ('k') | src/gpu/GrDrawTarget.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698