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

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

Issue 2222873002: Encapsulate GrReducedClip result in class members (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 4 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
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 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 "GrClipStackClip.h" 8 #include "GrClipStackClip.h"
9 9
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 "GrStencilAttachment.h" 13 #include "GrStencilAttachment.h"
14 #include "GrSWMaskHelper.h" 14 #include "GrSWMaskHelper.h"
15 #include "effects/GrConvexPolyEffect.h" 15 #include "effects/GrConvexPolyEffect.h"
16 #include "effects/GrRRectEffect.h" 16 #include "effects/GrRRectEffect.h"
17 #include "effects/GrTextureDomain.h" 17 #include "effects/GrTextureDomain.h"
18 18
19 typedef SkClipStack::Element Element; 19 typedef SkClipStack::Element Element;
20 typedef GrReducedClip::InitialState InitialState; 20 typedef GrReducedClip::InitialState InitialState;
21 typedef GrReducedClip::ElementList ElementList;
21 22
22 static const int kMaxAnalyticElements = 4; 23 static const int kMaxAnalyticElements = 4;
23 24
24 bool GrClipStackClip::quickContains(const SkRect& rect) const { 25 bool GrClipStackClip::quickContains(const SkRect& rect) const {
25 if (!fStack) { 26 if (!fStack) {
26 return true; 27 return true;
27 } 28 }
28 return fStack->quickContains(rect.makeOffset(SkIntToScalar(fOrigin.x()), 29 return fStack->quickContains(rect.makeOffset(SkIntToScalar(fOrigin.x()),
29 SkIntToScalar(fOrigin.y()))); 30 SkIntToScalar(fOrigin.y())));
30 } 31 }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 128
128 /* 129 /*
129 * This method traverses the clip stack to see if the GrSoftwarePathRenderer 130 * This method traverses the clip stack to see if the GrSoftwarePathRenderer
130 * will be used on any element. If so, it returns true to indicate that the 131 * will be used on any element. If so, it returns true to indicate that the
131 * entire clip should be rendered in SW and then uploaded en masse to the gpu. 132 * entire clip should be rendered in SW and then uploaded en masse to the gpu.
132 */ 133 */
133 bool GrClipStackClip::UseSWOnlyPath(GrContext* context, 134 bool GrClipStackClip::UseSWOnlyPath(GrContext* context,
134 bool hasUserStencilSettings, 135 bool hasUserStencilSettings,
135 const GrDrawContext* drawContext, 136 const GrDrawContext* drawContext,
136 const SkVector& clipToMaskOffset, 137 const SkVector& clipToMaskOffset,
137 const GrReducedClip::ElementList& elements) { 138 const ElementList& elements) {
138 // TODO: generalize this function so that when 139 // TODO: generalize this function so that when
139 // a clip gets complex enough it can just be done in SW regardless 140 // a clip gets complex enough it can just be done in SW regardless
140 // of whether it would invoke the GrSoftwarePathRenderer. 141 // of whether it would invoke the GrSoftwarePathRenderer.
141 142
142 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip 143 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
143 // space. 144 // space.
144 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY); 145 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY);
145 146
146 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 147 for (ElementList::Iter iter(elements); iter.get(); iter.next()) {
147 const Element* element = iter.get(); 148 const Element* element = iter.get();
148 149
149 SkRegion::Op op = element->getOp(); 150 SkRegion::Op op = element->getOp();
150 bool invert = element->isInverseFilled(); 151 bool invert = element->isInverseFilled();
151 bool needsStencil = invert || 152 bool needsStencil = invert ||
152 SkRegion::kIntersect_Op == op || SkRegion::kReverseD ifference_Op == op; 153 SkRegion::kIntersect_Op == op || SkRegion::kReverseD ifference_Op == op;
153 154
154 if (PathNeedsSWRenderer(context, hasUserStencilSettings, 155 if (PathNeedsSWRenderer(context, hasUserStencilSettings,
155 drawContext, translate, element, nullptr, needsS tencil)) { 156 drawContext, translate, element, nullptr, needsS tencil)) {
156 return true; 157 return true;
157 } 158 }
158 } 159 }
159 return false; 160 return false;
160 } 161 }
161 162
162 static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen ts, 163 static bool get_analytic_clip_processor(const ElementList& elements,
163 bool abortIfAA, 164 bool abortIfAA,
164 const SkVector& clipToRTOffset, 165 const SkVector& clipToRTOffset,
165 const SkRect& drawBounds, 166 const SkRect& drawBounds,
166 sk_sp<GrFragmentProcessor>* resultFP) { 167 sk_sp<GrFragmentProcessor>* resultFP) {
167 SkRect boundsInClipSpace; 168 SkRect boundsInClipSpace;
168 boundsInClipSpace = drawBounds.makeOffset(-clipToRTOffset.fX, -clipToRTOffse t.fY); 169 boundsInClipSpace = drawBounds.makeOffset(-clipToRTOffset.fX, -clipToRTOffse t.fY);
169 SkASSERT(elements.count() <= kMaxAnalyticElements); 170 SkASSERT(elements.count() <= kMaxAnalyticElements);
170 SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps; 171 SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps;
171 GrReducedClip::ElementList::Iter iter(elements); 172 ElementList::Iter iter(elements);
172 while (iter.get()) { 173 while (iter.get()) {
173 SkRegion::Op op = iter.get()->getOp(); 174 SkRegion::Op op = iter.get()->getOp();
174 bool invert; 175 bool invert;
175 bool skip = false; 176 bool skip = false;
176 switch (op) { 177 switch (op) {
177 case SkRegion::kReplace_Op: 178 case SkRegion::kReplace_Op:
178 SkASSERT(iter.get() == elements.head()); 179 SkASSERT(iter.get() == elements.head());
179 // Fallthrough, handled same as intersect. 180 // Fallthrough, handled same as intersect.
180 case SkRegion::kIntersect_Op: 181 case SkRegion::kIntersect_Op:
181 invert = false; 182 invert = false;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 } 253 }
253 254
254 SkRect devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height ()); 255 SkRect devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height ());
255 if (origDevBounds && !devBounds.intersect(*origDevBounds)) { 256 if (origDevBounds && !devBounds.intersect(*origDevBounds)) {
256 return false; 257 return false;
257 } 258 }
258 259
259 const SkScalar clipX = SkIntToScalar(fOrigin.x()), 260 const SkScalar clipX = SkIntToScalar(fOrigin.x()),
260 clipY = SkIntToScalar(fOrigin.y()); 261 clipY = SkIntToScalar(fOrigin.y());
261 262
262 GrReducedClip::ElementList elements; 263 SkRect clipSpaceDevBounds = devBounds.makeOffset(clipX, clipY);
263 int32_t genID = 0; 264 const GrReducedClip reducedClip(*fStack, clipSpaceDevBounds);
264 SkIRect clipSpaceIBounds;
265 bool requiresAA = false;
266 265
267 InitialState initialState = GrReducedClip::ReduceClipStack(*fStack, 266 if (reducedClip.elements().isEmpty()) {
268 devBounds.makeOff set(clipX, clipY), 267 if (GrReducedClip::InitialState::kAllOut == reducedClip.initialState()) {
269 &elements,
270 &genID,
271 &clipSpaceIBounds ,
272 &requiresAA);
273 if (elements.isEmpty()) {
274 if (GrReducedClip::kAllOut_InitialState == initialState || clipSpaceIBou nds.isEmpty()) {
275 return false; 268 return false;
276 } else { 269 }
277 SkIRect scissorSpaceIBounds(clipSpaceIBounds); 270 if (!GrClip::IsInsideClip(reducedClip.iBounds(), clipSpaceDevBounds)) {
271 SkIRect scissorSpaceIBounds(reducedClip.iBounds());
278 scissorSpaceIBounds.offset(-fOrigin); 272 scissorSpaceIBounds.offset(-fOrigin);
279 if (!GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) { 273 out->makeScissored(scissorSpaceIBounds);
280 out->makeScissored(scissorSpaceIBounds);
281 }
282 return true;
283 } 274 }
275 return true;
284 } 276 }
285 277
286 // An element count of 4 was chosen because of the common pattern in Blink o f: 278 // An element count of 4 was chosen because of the common pattern in Blink o f:
287 // isect RR 279 // isect RR
288 // diff RR 280 // diff RR
289 // isect convex_poly 281 // isect convex_poly
290 // isect convex_poly 282 // isect convex_poly
291 // when drawing rounded div borders. This could probably be tuned based on a 283 // when drawing rounded div borders. This could probably be tuned based on a
292 // configuration's relative costs of switching RTs to generate a mask vs 284 // configuration's relative costs of switching RTs to generate a mask vs
293 // longer shaders. 285 // longer shaders.
294 if (elements.count() <= kMaxAnalyticElements) { 286 if (reducedClip.elements().count() <= kMaxAnalyticElements) {
295 // When there are multiple samples we want to do per-sample clipping, no t compute a 287 // When there are multiple samples we want to do per-sample clipping, no t compute a
296 // fractional pixel coverage. 288 // fractional pixel coverage.
297 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); 289 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled();
298 if (disallowAnalyticAA && !drawContext->numColorSamples()) { 290 if (disallowAnalyticAA && !drawContext->numColorSamples()) {
299 // With a single color sample, any coverage info is lost from color once it hits the 291 // With a single color sample, any coverage info is lost from color once it hits the
300 // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe 292 // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe
301 // is multisampled. 293 // is multisampled.
302 disallowAnalyticAA = useHWAA || hasUserStencilSettings; 294 disallowAnalyticAA = useHWAA || hasUserStencilSettings;
303 } 295 }
304 sk_sp<GrFragmentProcessor> clipFP; 296 sk_sp<GrFragmentProcessor> clipFP;
305 if (requiresAA && 297 if (reducedClip.requiresAA() &&
306 get_analytic_clip_processor(elements, disallowAnalyticAA, {-clipX, - clipY}, devBounds, 298 get_analytic_clip_processor(reducedClip.elements(), disallowAnalytic AA,
307 &clipFP)) { 299 {-clipX, -clipY}, devBounds, &clipFP)) {
308 SkIRect scissorSpaceIBounds(clipSpaceIBounds); 300 SkIRect scissorSpaceIBounds(reducedClip.iBounds());
309 scissorSpaceIBounds.offset(-fOrigin); 301 scissorSpaceIBounds.offset(-fOrigin);
310 if (GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) { 302 if (GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) {
311 out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBo unds)); 303 out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBo unds));
312 } else { 304 } else {
313 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds ); 305 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds );
314 } 306 }
315 return true; 307 return true;
316 } 308 }
317 } 309 }
318 310
319 // If the stencil buffer is multisampled we can use it to do everything. 311 // If the stencil buffer is multisampled we can use it to do everything.
320 if (!drawContext->isStencilBufferMultisampled() && requiresAA) { 312 if (!drawContext->isStencilBufferMultisampled() && reducedClip.requiresAA()) {
321 sk_sp<GrTexture> result; 313 sk_sp<GrTexture> result;
322 314
323 // The top-left of the mask corresponds to the top-left corner of the bo unds. 315 // The top-left of the mask corresponds to the top-left corner of the bo unds.
324 SkVector clipToMaskOffset = { 316 SkVector clipToMaskOffset = {
325 SkIntToScalar(-clipSpaceIBounds.fLeft), 317 SkIntToScalar(-reducedClip.left()),
326 SkIntToScalar(-clipSpaceIBounds.fTop) 318 SkIntToScalar(-reducedClip.top())
327 }; 319 };
328 320
329 if (UseSWOnlyPath(context, hasUserStencilSettings, drawContext, 321 if (UseSWOnlyPath(context, hasUserStencilSettings, drawContext,
330 clipToMaskOffset, elements)) { 322 clipToMaskOffset, reducedClip.elements())) {
331 // The clip geometry is complex enough that it will be more efficien t to create it 323 // The clip geometry is complex enough that it will be more efficien t to create it
332 // entirely in software 324 // entirely in software
333 result = CreateSoftwareClipMask(context->textureProvider(), 325 result = CreateSoftwareClipMask(context->textureProvider(), reducedC lip,
334 genID, 326 clipToMaskOffset);
335 initialState,
336 elements,
337 clipToMaskOffset,
338 clipSpaceIBounds);
339 } else { 327 } else {
340 result = CreateAlphaClipMask(context, 328 result = CreateAlphaClipMask(context, reducedClip, clipToMaskOffset) ;
341 genID,
342 initialState,
343 elements,
344 clipToMaskOffset,
345 clipSpaceIBounds);
346 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug 329 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug
347 SkASSERT(result); 330 SkASSERT(result);
348 } 331 }
349 332
350 if (result) { 333 if (result) {
351 // The mask's top left coord should be pinned to the rounded-out top left corner of 334 // The mask's top left coord should be pinned to the rounded-out top left corner of
352 // clipSpace bounds. We determine the mask's position WRT to the ren der target here. 335 // clipSpace bounds. We determine the mask's position WRT to the ren der target here.
353 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; 336 SkIRect rtSpaceMaskBounds = reducedClip.iBounds();
354 rtSpaceMaskBounds.offset(-fOrigin); 337 rtSpaceMaskBounds.offset(-fOrigin);
355 out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds) , 338 out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds) ,
356 SkRect::Make(rtSpaceMaskBounds)); 339 SkRect::Make(rtSpaceMaskBounds));
357 return true; 340 return true;
358 } 341 }
359 // if alpha clip mask creation fails fall through to the non-AA code pat hs 342 // if alpha clip mask creation fails fall through to the non-AA code pat hs
360 } 343 }
361 344
362 // use the stencil clip if we can't represent the clip as a rectangle. 345 // use the stencil clip if we can't represent the clip as a rectangle.
363 SkIPoint clipSpaceToStencilSpaceOffset = -fOrigin; 346 SkIPoint clipSpaceToStencilSpaceOffset = -fOrigin;
364 CreateStencilClipMask(context, 347 CreateStencilClipMask(context, drawContext, reducedClip, clipSpaceToStencilS paceOffset);
365 drawContext,
366 genID,
367 initialState,
368 elements,
369 clipSpaceIBounds,
370 clipSpaceToStencilSpaceOffset);
371 348
372 // This must occur after createStencilClipMask. That function may change the scissor. Also, it 349 // This must occur after createStencilClipMask. That function may change the scissor. Also, it
373 // only guarantees that the stencil mask is correct within the bounds it was passed, so we must 350 // only guarantees that the stencil mask is correct within the bounds it was passed, so we must
374 // use both stencil and scissor test to the bounds for the final draw. 351 // use both stencil and scissor test to the bounds for the final draw.
375 SkIRect scissorSpaceIBounds(clipSpaceIBounds); 352 if (GrClip::IsInsideClip(reducedClip.iBounds(), clipSpaceDevBounds)) {
376 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
377 if (GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) {
378 out->makeStencil(true, devBounds); 353 out->makeStencil(true, devBounds);
379 } else { 354 } else {
355 SkIRect scissorSpaceIBounds(reducedClip.iBounds());
356 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
380 out->makeScissoredStencil(scissorSpaceIBounds); 357 out->makeScissoredStencil(scissorSpaceIBounds);
381 } 358 }
382 return true; 359 return true;
383 } 360 }
384 361
385 static bool stencil_element(GrDrawContext* dc, 362 static bool stencil_element(GrDrawContext* dc,
386 const GrFixedClip& clip, 363 const GrFixedClip& clip,
387 const GrUserStencilSettings* ss, 364 const GrUserStencilSettings* ss,
388 const SkMatrix& viewMatrix, 365 const SkMatrix& viewMatrix,
389 const SkClipStack::Element* element) { 366 const SkClipStack::Element* element) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 427
451 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey * key) { 428 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey * key) {
452 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 429 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
453 GrUniqueKey::Builder builder(key, kDomain, 3); 430 GrUniqueKey::Builder builder(key, kDomain, 3);
454 builder[0] = clipGenID; 431 builder[0] = clipGenID;
455 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16); 432 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16);
456 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); 433 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16);
457 } 434 }
458 435
459 sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context, 436 sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context,
460 int32_t elementsGenID, 437 const GrReducedClip& reduc edClip,
461 GrReducedClip::InitialStat e initialState, 438 const SkVector& clipToMask Offset) {
462 const GrReducedClip::Eleme ntList& elements,
463 const SkVector& clipToMask Offset,
464 const SkIRect& clipSpaceIB ounds) {
465 GrResourceProvider* resourceProvider = context->resourceProvider(); 439 GrResourceProvider* resourceProvider = context->resourceProvider();
466 GrUniqueKey key; 440 GrUniqueKey key;
467 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); 441 GetClipMaskKey(reducedClip.genID(), reducedClip.iBounds(), &key);
468 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key) ) { 442 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key) ) {
469 return sk_sp<GrTexture>(texture); 443 return sk_sp<GrTexture>(texture);
470 } 444 }
471 445
472 // There's no texture in the cache. Let's try to allocate it then. 446 // There's no texture in the cache. Let's try to allocate it then.
473 GrPixelConfig config = kRGBA_8888_GrPixelConfig; 447 GrPixelConfig config = kRGBA_8888_GrPixelConfig;
474 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { 448 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
475 config = kAlpha_8_GrPixelConfig; 449 config = kAlpha_8_GrPixelConfig;
476 } 450 }
477 451
478 sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kApprox, 452 sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kApprox,
479 clipSpaceIBounds.width(), 453 reducedClip.width(),
480 clipSpaceIBounds.height(), 454 reducedClip.height(),
481 config, nullptr)); 455 config, nullptr));
482 if (!dc) { 456 if (!dc) {
483 return nullptr; 457 return nullptr;
484 } 458 }
485 459
486 // The texture may be larger than necessary, this rect represents the part o f the texture 460 // The texture may be larger than necessary, this rect represents the part o f the texture
487 // we populate with a rasterization of the clip. 461 // we populate with a rasterization of the clip.
488 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa ceIBounds.height()); 462 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip. height());
489 463
490 // The scratch texture that we are drawing into can be substantially larger than the mask. Only 464 // The scratch texture that we are drawing into can be substantially larger than the mask. Only
491 // clear the part that we care about. 465 // clear the part that we care about.
492 dc->clear(&maskSpaceIBounds, 466 dc->clear(&maskSpaceIBounds,
493 GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000, 467 GrReducedClip::InitialState::kAllIn == reducedClip.initialState() ? -1 : 0,
494 true); 468 true);
495 469
496 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip 470 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
497 // space. 471 // space.
498 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY); 472 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY);
499 473
500 // It is important that we use maskSpaceIBounds as the stencil rect in the b elow loop. 474 // It is important that we use maskSpaceIBounds as the stencil rect in the b elow loop.
501 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first 475 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first
502 // pass must not set values outside of this bounds or stencil values outside the rect won't be 476 // pass must not set values outside of this bounds or stencil values outside the rect won't be
503 // cleared. 477 // cleared.
504 478
505 // walk through each clip element and perform its set op 479 // walk through each clip element and perform its set op
506 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) { 480 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next() ) {
507 const Element* element = iter.get(); 481 const Element* element = iter.get();
508 SkRegion::Op op = element->getOp(); 482 SkRegion::Op op = element->getOp();
509 bool invert = element->isInverseFilled(); 483 bool invert = element->isInverseFilled();
510 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { 484 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) {
511 GrFixedClip clip(maskSpaceIBounds); 485 GrFixedClip clip(maskSpaceIBounds);
512 486
513 // draw directly into the result with the stencil set to make the pi xels affected 487 // draw directly into the result with the stencil set to make the pi xels affected
514 // by the clip shape be non-zero. 488 // by the clip shape be non-zero.
515 static constexpr GrUserStencilSettings kStencilInElement( 489 static constexpr GrUserStencilSettings kStencilInElement(
516 GrUserStencilSettings::StaticInit< 490 GrUserStencilSettings::StaticInit<
(...skipping 15 matching lines...) Expand all
532 0x0000, 506 0x0000,
533 GrUserStencilTest::kEqual, 507 GrUserStencilTest::kEqual,
534 0xffff, 508 0xffff,
535 GrUserStencilOp::kZero, 509 GrUserStencilOp::kZero,
536 GrUserStencilOp::kZero, 510 GrUserStencilOp::kZero,
537 0xffff>() 511 0xffff>()
538 ); 512 );
539 if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideEle ment, 513 if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideEle ment,
540 op, !invert, false, 514 op, !invert, false,
541 translate, 515 translate,
542 SkRect::Make(clipSpace IBounds))) { 516 SkRect::Make(reducedCl ip.iBounds()))) {
543 return nullptr; 517 return nullptr;
544 } 518 }
545 } else { 519 } else {
546 // all the remaining ops can just be directly draw into the accumula tion buffer 520 // all the remaining ops can just be directly draw into the accumula tion buffer
547 GrPaint paint; 521 GrPaint paint;
548 paint.setAntiAlias(element->isAA()); 522 paint.setAntiAlias(element->isAA());
549 paint.setCoverageSetOpXPFactory(op, false); 523 paint.setCoverageSetOpXPFactory(op, false);
550 524
551 draw_element(dc.get(), GrNoClip(), paint, translate, element); 525 draw_element(dc.get(), GrNoClip(), paint, translate, element);
552 } 526 }
553 } 527 }
554 528
555 sk_sp<GrTexture> texture(dc->asTexture()); 529 sk_sp<GrTexture> texture(dc->asTexture());
556 SkASSERT(texture); 530 SkASSERT(texture);
557 texture->resourcePriv().setUniqueKey(key); 531 texture->resourcePriv().setUniqueKey(key);
558 return texture; 532 return texture;
559 } 533 }
560 534
561 //////////////////////////////////////////////////////////////////////////////// 535 ////////////////////////////////////////////////////////////////////////////////
562 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device 536 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device
563 // (as opposed to canvas) coordinates 537 // (as opposed to canvas) coordinates
564 bool GrClipStackClip::CreateStencilClipMask(GrContext* context, 538 bool GrClipStackClip::CreateStencilClipMask(GrContext* context,
565 GrDrawContext* drawContext, 539 GrDrawContext* drawContext,
566 int32_t elementsGenID, 540 const GrReducedClip& reducedClip,
567 GrReducedClip::InitialState initialS tate,
568 const GrReducedClip::ElementList& el ements,
569 const SkIRect& clipSpaceIBounds,
570 const SkIPoint& clipSpaceToStencilOf fset) { 541 const SkIPoint& clipSpaceToStencilOf fset) {
571 SkASSERT(drawContext); 542 SkASSERT(drawContext);
572 543
573 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach StencilAttachment( 544 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach StencilAttachment(
574 drawContext->accessRenderTar get()); 545 drawContext->accessRenderTar get());
575 if (nullptr == stencilAttachment) { 546 if (nullptr == stencilAttachment) {
576 return false; 547 return false;
577 } 548 }
578 549
579 // TODO: these need to be swapped over to using a StencilAttachmentProxy 550 // TODO: these need to be swapped over to using a StencilAttachmentProxy
580 if (stencilAttachment->mustRenderClip(elementsGenID, clipSpaceIBounds, clipS paceToStencilOffset)) { 551 if (stencilAttachment->mustRenderClip(reducedClip.genID(), reducedClip.iBoun ds(),
581 stencilAttachment->setLastClip(elementsGenID, clipSpaceIBounds, clipSpac eToStencilOffset); 552 clipSpaceToStencilOffset)) {
553 stencilAttachment->setLastClip(reducedClip.genID(), reducedClip.iBounds( ),
554 clipSpaceToStencilOffset);
582 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space. 555 // Set the matrix so that rendered clip elements are transformed from cl ip to stencil space.
583 SkVector translate = { 556 SkVector translate = {
584 SkIntToScalar(clipSpaceToStencilOffset.fX), 557 SkIntToScalar(clipSpaceToStencilOffset.fX),
585 SkIntToScalar(clipSpaceToStencilOffset.fY) 558 SkIntToScalar(clipSpaceToStencilOffset.fY)
586 }; 559 };
587 SkMatrix viewMatrix; 560 SkMatrix viewMatrix;
588 viewMatrix.setTranslate(translate); 561 viewMatrix.setTranslate(translate);
589 562
590 // We set the current clip to the bounds so that our recursive draws are scissored to them. 563 // We set the current clip to the bounds so that our recursive draws are scissored to them.
591 SkIRect stencilSpaceIBounds(clipSpaceIBounds); 564 SkIRect stencilSpaceIBounds(reducedClip.iBounds());
592 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); 565 stencilSpaceIBounds.offset(clipSpaceToStencilOffset);
593 GrFixedClip clip(stencilSpaceIBounds); 566 GrFixedClip clip(stencilSpaceIBounds);
594 567
595 drawContext->drawContextPriv().clearStencilClip( 568 bool insideClip = GrReducedClip::InitialState::kAllIn == reducedClip.ini tialState();
596 stencilSpaceIBounds, 569 drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, ins ideClip);
597 GrReducedClip::kAllIn_InitialState = = initialState);
598 570
599 // walk through each clip element and perform its set op 571 // walk through each clip element and perform its set op
600 // with the existing clip. 572 // with the existing clip.
601 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge t(); iter.next()) { 573 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.ne xt()) {
602 const Element* element = iter.get(); 574 const Element* element = iter.get();
603 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis ampled(); 575 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis ampled();
604 576
605 bool fillInverted = false; 577 bool fillInverted = false;
606 // enabled at bottom of loop 578 // enabled at bottom of loop
607 clip.disableStencilClip(); 579 clip.disableStencilClip();
608 580
609 // This will be used to determine whether the clip shape can be rend ered into the 581 // This will be used to determine whether the clip shape can be rend ered into the
610 // stencil with arbitrary stencil settings. 582 // stencil with arbitrary stencil settings.
611 GrPathRenderer::StencilSupport stencilSupport; 583 GrPathRenderer::StencilSupport stencilSupport;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 args.fClip = &clip; 697 args.fClip = &clip;
726 args.fViewMatrix = &viewMatrix; 698 args.fViewMatrix = &viewMatrix;
727 args.fShape = &shape; 699 args.fShape = &shape;
728 args.fAntiAlias = false; 700 args.fAntiAlias = false;
729 args.fGammaCorrect = false; 701 args.fGammaCorrect = false;
730 pr->drawPath(args); 702 pr->drawPath(args);
731 } 703 }
732 } else { 704 } else {
733 // The view matrix is setup to do clip space -> stencil spac e translation, so 705 // The view matrix is setup to do clip space -> stencil spac e translation, so
734 // draw rect in clip space. 706 // draw rect in clip space.
735 SkRect bounds = SkRect::Make(clipSpaceIBounds); 707 SkRect bounds = SkRect::Make(reducedClip.iBounds());
736 bounds.offset(translate.fX, translate.fY); 708 bounds.offset(translate.fX, translate.fY);
737 clip.enableStencilClip(bounds); 709 clip.enableStencilClip(bounds);
738 drawContext->drawContextPriv().stencilRect(clip, *pass, fals e, viewMatrix, 710 drawContext->drawContextPriv().stencilRect(clip, *pass, fals e, viewMatrix,
739 SkRect::Make(clip SpaceIBounds)); 711 SkRect::Make(redu cedClip.iBounds()));
740 } 712 }
741 } 713 }
742 } 714 }
743 } 715 }
744 return true; 716 return true;
745 } 717 }
746 718
747 //////////////////////////////////////////////////////////////////////////////// 719 ////////////////////////////////////////////////////////////////////////////////
748 sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP rovider, 720 sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP rovider,
749 int32_t elementsGenID, 721 const GrReducedClip& re ducedClip,
750 GrReducedClip::InitialS tate initialState, 722 const SkVector& clipToM askOffset) {
751 const GrReducedClip::El ementList& elements,
752 const SkVector& clipToM askOffset,
753 const SkIRect& clipSpac eIBounds) {
754 GrUniqueKey key; 723 GrUniqueKey key;
755 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); 724 GetClipMaskKey(reducedClip.genID(), reducedClip.iBounds(), &key);
756 if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) { 725 if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) {
757 return sk_sp<GrTexture>(texture); 726 return sk_sp<GrTexture>(texture);
758 } 727 }
759 728
760 // The mask texture may be larger than necessary. We round out the clip spac e bounds and pin 729 // The mask texture may be larger than necessary. We round out the clip spac e bounds and pin
761 // the top left corner of the resulting rect to the top left of the texture. 730 // the top left corner of the resulting rect to the top left of the texture.
762 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa ceIBounds.height()); 731 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip. height());
763 732
764 GrSWMaskHelper helper(texProvider); 733 GrSWMaskHelper helper(texProvider);
765 734
766 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip 735 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
767 // space. 736 // space.
768 SkMatrix translate; 737 SkMatrix translate;
769 translate.setTranslate(clipToMaskOffset); 738 translate.setTranslate(clipToMaskOffset);
770 739
771 helper.init(maskSpaceIBounds, &translate); 740 helper.init(maskSpaceIBounds, &translate);
772 helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x0 0); 741 helper.clear(GrReducedClip::InitialState::kAllIn == reducedClip.initialState () ? 0xFF : 0x00);
773 742
774 for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get() ; iter.next()) { 743 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next() ) {
775 const Element* element = iter.get(); 744 const Element* element = iter.get();
776 SkRegion::Op op = element->getOp(); 745 SkRegion::Op op = element->getOp();
777 746
778 if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 747 if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
779 // Intersect and reverse difference require modifying pixels outside of the geometry 748 // Intersect and reverse difference require modifying pixels outside of the geometry
780 // that is being "drawn". In both cases we erase all the pixels outs ide of the geometry 749 // that is being "drawn". In both cases we erase all the pixels outs ide of the geometry
781 // but leave the pixels inside the geometry alone. For reverse diffe rence we invert all 750 // but leave the pixels inside the geometry alone. For reverse diffe rence we invert all
782 // the pixels before clearing the ones outside the geometry. 751 // the pixels before clearing the ones outside the geometry.
783 if (SkRegion::kReverseDifference_Op == op) { 752 if (SkRegion::kReverseDifference_Op == op) {
784 SkRect temp = SkRect::Make(clipSpaceIBounds); 753 SkRect temp = SkRect::Make(reducedClip.iBounds());
785 // invert the entire scene 754 // invert the entire scene
786 helper.drawRect(temp, SkRegion::kXOR_Op, false, 0xFF); 755 helper.drawRect(temp, SkRegion::kXOR_Op, false, 0xFF);
787 } 756 }
788 SkPath clipPath; 757 SkPath clipPath;
789 element->asPath(&clipPath); 758 element->asPath(&clipPath);
790 clipPath.toggleInverseFillType(); 759 clipPath.toggleInverseFillType();
791 GrShape shape(clipPath, GrStyle::SimpleFill()); 760 GrShape shape(clipPath, GrStyle::SimpleFill());
792 helper.drawShape(shape, SkRegion::kReplace_Op, element->isAA(), 0x00 ); 761 helper.drawShape(shape, SkRegion::kReplace_Op, element->isAA(), 0x00 );
793 continue; 762 continue;
794 } 763 }
795 764
796 // The other ops (union, xor, diff) only affect pixels inside 765 // The other ops (union, xor, diff) only affect pixels inside
797 // the geometry so they can just be drawn normally 766 // the geometry so they can just be drawn normally
798 if (Element::kRect_Type == element->getType()) { 767 if (Element::kRect_Type == element->getType()) {
799 helper.drawRect(element->getRect(), op, element->isAA(), 0xFF); 768 helper.drawRect(element->getRect(), op, element->isAA(), 0xFF);
800 } else { 769 } else {
801 SkPath path; 770 SkPath path;
802 element->asPath(&path); 771 element->asPath(&path);
803 GrShape shape(path, GrStyle::SimpleFill()); 772 GrShape shape(path, GrStyle::SimpleFill());
804 helper.drawShape(shape, op, element->isAA(), 0xFF); 773 helper.drawShape(shape, op, element->isAA(), 0xFF);
805 } 774 }
806 } 775 }
807 776
808 // Allocate clip mask texture 777 // Allocate clip mask texture
809 GrSurfaceDesc desc; 778 GrSurfaceDesc desc;
810 desc.fWidth = clipSpaceIBounds.width(); 779 desc.fWidth = reducedClip.width();
811 desc.fHeight = clipSpaceIBounds.height(); 780 desc.fHeight = reducedClip.height();
812 desc.fConfig = kAlpha_8_GrPixelConfig; 781 desc.fConfig = kAlpha_8_GrPixelConfig;
813 782
814 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); 783 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc));
815 if (!result) { 784 if (!result) {
816 return nullptr; 785 return nullptr;
817 } 786 }
818 result->resourcePriv().setUniqueKey(key); 787 result->resourcePriv().setUniqueKey(key);
819 788
820 helper.toTexture(result.get()); 789 helper.toTexture(result.get());
821 790
822 return result; 791 return result;
823 } 792 }
OLDNEW
« include/gpu/GrClip.h ('K') | « src/gpu/GrClipStackClip.h ('k') | src/gpu/GrReducedClip.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698