| 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 "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 typedef GrReducedClip::InitialState InitialState; |
| 29 | 30 |
| 30 static const int kMaxAnalyticElements = 4; | 31 static const int kMaxAnalyticElements = 4; |
| 31 | 32 |
| 32 //////////////////////////////////////////////////////////////////////////////// | 33 //////////////////////////////////////////////////////////////////////////////// |
| 33 // set up the draw state to enable the aa clipping mask. Besides setting up the | 34 // set up the draw state to enable the aa clipping mask. Besides setting up the |
| 34 // stage matrix this also alters the vertex layout | 35 // stage matrix this also alters the vertex layout |
| 35 static sk_sp<GrFragmentProcessor> create_fp_for_mask(GrTexture* result, | 36 static sk_sp<GrFragmentProcessor> create_fp_for_mask(GrTexture* result, |
| 36 const SkIRect &devBound) { | 37 const SkIRect &devBound) { |
| 37 SkMatrix mat; | 38 SkMatrix mat; |
| 38 // We use device coords to compute the texture coordinates. We set our matri
x to be a | 39 // We use device coords to compute the texture coordinates. We set our matri
x to be a |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 if (PathNeedsSWRenderer(context, hasUserStencilSettings, | 140 if (PathNeedsSWRenderer(context, hasUserStencilSettings, |
| 140 drawContext, translate, element, nullptr, needsS
tencil)) { | 141 drawContext, translate, element, nullptr, needsS
tencil)) { |
| 141 return true; | 142 return true; |
| 142 } | 143 } |
| 143 } | 144 } |
| 144 return false; | 145 return false; |
| 145 } | 146 } |
| 146 | 147 |
| 147 static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen
ts, | 148 static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen
ts, |
| 148 bool abortIfAA, | 149 bool abortIfAA, |
| 149 SkVector& clipToRTOffset, | 150 const SkVector& clipToRTOffset, |
| 150 const SkRect& drawBounds, | 151 const SkRect& drawBounds, |
| 151 sk_sp<GrFragmentProcessor>* resultFP) { | 152 sk_sp<GrFragmentProcessor>* resultFP) { |
| 152 SkRect boundsInClipSpace; | 153 SkRect boundsInClipSpace; |
| 153 boundsInClipSpace = drawBounds.makeOffset(-clipToRTOffset.fX, -clipToRTOffse
t.fY); | 154 boundsInClipSpace = drawBounds.makeOffset(-clipToRTOffset.fX, -clipToRTOffse
t.fY); |
| 154 SkASSERT(elements.count() <= kMaxAnalyticElements); | 155 SkASSERT(elements.count() <= kMaxAnalyticElements); |
| 155 SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps; | 156 SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps; |
| 156 GrReducedClip::ElementList::Iter iter(elements); | 157 GrReducedClip::ElementList::Iter iter(elements); |
| 157 while (iter.get()) { | 158 while (iter.get()) { |
| 158 SkRegion::Op op = iter.get()->getOp(); | 159 SkRegion::Op op = iter.get()->getOp(); |
| 159 bool invert; | 160 bool invert; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 GrDrawContext* drawContext, | 231 GrDrawContext* drawContext, |
| 231 const GrClipStackClip& clip, | 232 const GrClipStackClip& clip, |
| 232 const SkRect* origDevBounds, | 233 const SkRect* origDevBounds, |
| 233 bool useHWAA, | 234 bool useHWAA, |
| 234 bool hasUserStencilSettings, | 235 bool hasUserStencilSettings, |
| 235 GrAppliedClip* out) { | 236 GrAppliedClip* out) { |
| 236 if (!clip.clipStack() || clip.clipStack()->isWideOpen()) { | 237 if (!clip.clipStack() || clip.clipStack()->isWideOpen()) { |
| 237 return true; | 238 return true; |
| 238 } | 239 } |
| 239 | 240 |
| 241 SkRect devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height
()); |
| 242 if (origDevBounds && !devBounds.intersect(*origDevBounds)) { |
| 243 return false; |
| 244 } |
| 245 |
| 246 const SkScalar clipX = SkIntToScalar(clip.origin().x()), |
| 247 clipY = SkIntToScalar(clip.origin().y()); |
| 248 |
| 240 GrReducedClip::ElementList elements; | 249 GrReducedClip::ElementList elements; |
| 241 int32_t genID = 0; | 250 int32_t genID = 0; |
| 242 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; | |
| 243 SkIRect clipSpaceIBounds; | 251 SkIRect clipSpaceIBounds; |
| 244 bool requiresAA = false; | 252 bool requiresAA = false; |
| 245 | 253 |
| 246 SkIRect clipSpaceReduceQueryBounds; | 254 InitialState initialState = GrReducedClip::ReduceClipStack(*clip.clipStack()
, |
| 247 SkRect devBounds; | 255 devBounds.makeOff
set(clipX, clipY), |
| 248 if (origDevBounds) { | 256 &elements, |
| 249 if (!devBounds.intersect(SkRect::MakeIWH(drawContext->width(), drawConte
xt->height()), | 257 &genID, |
| 250 *origDevBounds)) { | 258 &clipSpaceIBounds
, |
| 251 return false; | 259 &requiresAA); |
| 252 } | |
| 253 devBounds.roundOut(&clipSpaceReduceQueryBounds); | |
| 254 clipSpaceReduceQueryBounds.offset(clip.origin()); | |
| 255 } else { | |
| 256 devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height())
; | |
| 257 clipSpaceReduceQueryBounds.setXYWH(0, 0, drawContext->width(), drawConte
xt->height()); | |
| 258 clipSpaceReduceQueryBounds.offset(clip.origin()); | |
| 259 } | |
| 260 GrReducedClip::ReduceClipStack(*clip.clipStack(), | |
| 261 clipSpaceReduceQueryBounds, | |
| 262 &elements, | |
| 263 &genID, | |
| 264 &initialState, | |
| 265 &clipSpaceIBounds, | |
| 266 &requiresAA); | |
| 267 if (elements.isEmpty()) { | 260 if (elements.isEmpty()) { |
| 268 if (GrReducedClip::kAllOut_InitialState == initialState) { | 261 if (GrReducedClip::kAllOut_InitialState == initialState) { |
| 269 return false; | 262 return false; |
| 270 } else { | 263 } else { |
| 271 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 264 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 272 scissorSpaceIBounds.offset(-clip.origin()); | 265 scissorSpaceIBounds.offset(-clip.origin()); |
| 273 if (!GrClip::CanIgnoreScissor(scissorSpaceIBounds, devBounds)) { | 266 if (!GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) { |
| 274 out->makeScissored(scissorSpaceIBounds); | 267 out->makeScissored(scissorSpaceIBounds); |
| 275 } | 268 } |
| 276 return true; | 269 return true; |
| 277 } | 270 } |
| 278 } | 271 } |
| 279 | 272 |
| 280 // An element count of 4 was chosen because of the common pattern in Blink o
f: | 273 // An element count of 4 was chosen because of the common pattern in Blink o
f: |
| 281 // isect RR | 274 // isect RR |
| 282 // diff RR | 275 // diff RR |
| 283 // isect convex_poly | 276 // isect convex_poly |
| 284 // isect convex_poly | 277 // isect convex_poly |
| 285 // when drawing rounded div borders. This could probably be tuned based on a | 278 // when drawing rounded div borders. This could probably be tuned based on a |
| 286 // configuration's relative costs of switching RTs to generate a mask vs | 279 // configuration's relative costs of switching RTs to generate a mask vs |
| 287 // longer shaders. | 280 // longer shaders. |
| 288 if (elements.count() <= kMaxAnalyticElements) { | 281 if (elements.count() <= kMaxAnalyticElements) { |
| 289 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), | |
| 290 SkIntToScalar(-clip.origin().fY) }; | |
| 291 // When there are multiple samples we want to do per-sample clipping, no
t compute a | 282 // When there are multiple samples we want to do per-sample clipping, no
t compute a |
| 292 // fractional pixel coverage. | 283 // fractional pixel coverage. |
| 293 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); | 284 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); |
| 294 if (disallowAnalyticAA && !drawContext->numColorSamples()) { | 285 if (disallowAnalyticAA && !drawContext->numColorSamples()) { |
| 295 // With a single color sample, any coverage info is lost from color
once it hits the | 286 // With a single color sample, any coverage info is lost from color
once it hits the |
| 296 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe | 287 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe |
| 297 // is multisampled. | 288 // is multisampled. |
| 298 disallowAnalyticAA = useHWAA || hasUserStencilSettings; | 289 disallowAnalyticAA = useHWAA || hasUserStencilSettings; |
| 299 } | 290 } |
| 300 sk_sp<GrFragmentProcessor> clipFP; | 291 sk_sp<GrFragmentProcessor> clipFP; |
| 301 if (requiresAA && | 292 if (requiresAA && |
| 302 get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTOf
fset, devBounds, | 293 get_analytic_clip_processor(elements, disallowAnalyticAA, {-clipX, -
clipY}, devBounds, |
| 303 &clipFP)) { | 294 &clipFP)) { |
| 304 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 295 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 305 scissorSpaceIBounds.offset(-clip.origin()); | 296 scissorSpaceIBounds.offset(-clip.origin()); |
| 306 if (GrClip::CanIgnoreScissor(scissorSpaceIBounds, devBounds)) { | 297 if (GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) { |
| 307 out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBo
unds)); | 298 out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBo
unds)); |
| 308 } else { | 299 } else { |
| 309 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds
); | 300 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds
); |
| 310 } | 301 } |
| 311 return true; | 302 return true; |
| 312 } | 303 } |
| 313 } | 304 } |
| 314 | 305 |
| 315 // If the stencil buffer is multisampled we can use it to do everything. | 306 // If the stencil buffer is multisampled we can use it to do everything. |
| 316 if (!drawContext->isStencilBufferMultisampled() && requiresAA) { | 307 if (!drawContext->isStencilBufferMultisampled() && requiresAA) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 initialState, | 354 initialState, |
| 364 elements, | 355 elements, |
| 365 clipSpaceIBounds, | 356 clipSpaceIBounds, |
| 366 clipSpaceToStencilSpaceOffset); | 357 clipSpaceToStencilSpaceOffset); |
| 367 | 358 |
| 368 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 359 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
| 369 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 360 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
| 370 // use both stencil and scissor test to the bounds for the final draw. | 361 // use both stencil and scissor test to the bounds for the final draw. |
| 371 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 362 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 372 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 363 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
| 373 if (GrClip::CanIgnoreScissor(scissorSpaceIBounds, devBounds)) { | 364 if (GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) { |
| 374 out->makeStencil(true, devBounds); | 365 out->makeStencil(true, devBounds); |
| 375 } else { | 366 } else { |
| 376 out->makeScissoredStencil(scissorSpaceIBounds); | 367 out->makeScissoredStencil(scissorSpaceIBounds); |
| 377 } | 368 } |
| 378 return true; | 369 return true; |
| 379 } | 370 } |
| 380 | 371 |
| 381 static bool stencil_element(GrDrawContext* dc, | 372 static bool stencil_element(GrDrawContext* dc, |
| 382 const GrFixedClip& clip, | 373 const GrFixedClip& clip, |
| 383 const GrUserStencilSettings* ss, | 374 const GrUserStencilSettings* ss, |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 810 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); | 801 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); |
| 811 if (!result) { | 802 if (!result) { |
| 812 return nullptr; | 803 return nullptr; |
| 813 } | 804 } |
| 814 result->resourcePriv().setUniqueKey(key); | 805 result->resourcePriv().setUniqueKey(key); |
| 815 | 806 |
| 816 helper.toTexture(result.get()); | 807 helper.toTexture(result.get()); |
| 817 | 808 |
| 818 return result; | 809 return result; |
| 819 } | 810 } |
| OLD | NEW |