Chromium Code Reviews| 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" |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 drawContext, translate, element, nullptr, needsS tencil)) { | 139 drawContext, translate, element, nullptr, needsS tencil)) { |
| 140 return true; | 140 return true; |
| 141 } | 141 } |
| 142 } | 142 } |
| 143 return false; | 143 return false; |
| 144 } | 144 } |
| 145 | 145 |
| 146 static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen ts, | 146 static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen ts, |
| 147 bool abortIfAA, | 147 bool abortIfAA, |
| 148 SkVector& clipToRTOffset, | 148 SkVector& clipToRTOffset, |
| 149 const SkRect* drawBounds, | 149 const SkRect& drawBounds, |
| 150 sk_sp<GrFragmentProcessor>* resultFP) { | 150 sk_sp<GrFragmentProcessor>* resultFP) { |
| 151 SkRect boundsInClipSpace; | 151 SkRect boundsInClipSpace; |
| 152 if (drawBounds) { | 152 boundsInClipSpace = drawBounds.makeOffset(-clipToRTOffset.fX, -clipToRTOffse t.fY); |
| 153 boundsInClipSpace = *drawBounds; | |
| 154 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); | |
| 155 } | |
| 156 SkASSERT(elements.count() <= kMaxAnalyticElements); | 153 SkASSERT(elements.count() <= kMaxAnalyticElements); |
| 157 SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps; | 154 SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps; |
| 158 GrReducedClip::ElementList::Iter iter(elements); | 155 GrReducedClip::ElementList::Iter iter(elements); |
| 159 while (iter.get()) { | 156 while (iter.get()) { |
| 160 SkRegion::Op op = iter.get()->getOp(); | 157 SkRegion::Op op = iter.get()->getOp(); |
| 161 bool invert; | 158 bool invert; |
| 162 bool skip = false; | 159 bool skip = false; |
| 163 switch (op) { | 160 switch (op) { |
| 164 case SkRegion::kReplace_Op: | 161 case SkRegion::kReplace_Op: |
| 165 SkASSERT(iter.get() == elements.head()); | 162 SkASSERT(iter.get() == elements.head()); |
| 166 // Fallthrough, handled same as intersect. | 163 // Fallthrough, handled same as intersect. |
| 167 case SkRegion::kIntersect_Op: | 164 case SkRegion::kIntersect_Op: |
| 168 invert = false; | 165 invert = false; |
| 169 if (drawBounds && iter.get()->contains(boundsInClipSpace)) { | 166 if (iter.get()->contains(boundsInClipSpace)) { |
| 170 skip = true; | 167 skip = true; |
| 171 } | 168 } |
| 172 break; | 169 break; |
| 173 case SkRegion::kDifference_Op: | 170 case SkRegion::kDifference_Op: |
| 174 invert = true; | 171 invert = true; |
| 175 // We don't currently have a cheap test for whether a rect is fu lly outside an | 172 // We don't currently have a cheap test for whether a rect is fu lly outside an |
| 176 // element's primitive, so don't attempt to set skip. | 173 // element's primitive, so don't attempt to set skip. |
| 177 break; | 174 break; |
| 178 default: | 175 default: |
| 179 return false; | 176 return false; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 return true; | 222 return true; |
| 226 } | 223 } |
| 227 | 224 |
| 228 //////////////////////////////////////////////////////////////////////////////// | 225 //////////////////////////////////////////////////////////////////////////////// |
| 229 // sort out what kind of clip mask needs to be created: alpha, stencil, | 226 // sort out what kind of clip mask needs to be created: alpha, stencil, |
| 230 // scissor, or entirely software | 227 // scissor, or entirely software |
| 231 bool GrClipMaskManager::SetupClipping(GrContext* context, | 228 bool GrClipMaskManager::SetupClipping(GrContext* context, |
| 232 const GrPipelineBuilder& pipelineBuilder, | 229 const GrPipelineBuilder& pipelineBuilder, |
| 233 GrDrawContext* drawContext, | 230 GrDrawContext* drawContext, |
| 234 const GrClipStackClip& clip, | 231 const GrClipStackClip& clip, |
| 235 const SkRect* devBounds, | 232 const SkRect* origDevBounds, |
| 236 GrAppliedClip* out) { | 233 GrAppliedClip* out) { |
| 237 if (!clip.clipStack() || clip.clipStack()->isWideOpen()) { | 234 if (!clip.clipStack() || clip.clipStack()->isWideOpen()) { |
| 238 return true; | 235 return true; |
| 239 } | 236 } |
| 240 | 237 |
| 241 GrReducedClip::ElementList elements; | 238 GrReducedClip::ElementList elements; |
| 242 int32_t genID = 0; | 239 int32_t genID = 0; |
| 243 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat e; | 240 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat e; |
| 244 SkIRect clipSpaceIBounds; | 241 SkIRect clipSpaceIBounds; |
| 245 bool requiresAA = false; | 242 bool requiresAA = false; |
| 246 | 243 |
| 247 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(drawContext->width(), drawConte xt->height()); | |
| 248 clipSpaceRTIBounds.offset(clip.origin()); | |
| 249 | |
| 250 SkIRect clipSpaceReduceQueryBounds; | 244 SkIRect clipSpaceReduceQueryBounds; |
| 251 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 | 245 SkRect devBounds; |
| 252 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { | 246 if (origDevBounds) { |
|
robertphillips
2016/07/08 14:21:58
Are there any issues with this reject and hairline
bsalomon
2016/07/08 14:25:56
Because of 'empty' rects? No, because GrDT bloats
| |
| 253 SkIRect devIBounds = devBounds->roundOut(); | 247 if (!devBounds.intersect(SkRect::MakeIWH(drawContext->width(), drawConte xt->height()), |
| 254 devIBounds.offset(clip.origin()); | 248 *origDevBounds)) { |
| 255 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, devIBounds )) { | |
| 256 return false; | 249 return false; |
| 257 } | 250 } |
| 251 devBounds.roundOut(&clipSpaceReduceQueryBounds); | |
| 252 clipSpaceReduceQueryBounds.offset(clip.origin()); | |
| 258 } else { | 253 } else { |
| 259 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; | 254 devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height()) ; |
| 255 clipSpaceReduceQueryBounds.setXYWH(0, 0, drawContext->width(), drawConte xt->height()); | |
| 256 clipSpaceReduceQueryBounds.offset(clip.origin()); | |
| 260 } | 257 } |
| 261 GrReducedClip::ReduceClipStack(*clip.clipStack(), | 258 GrReducedClip::ReduceClipStack(*clip.clipStack(), |
| 262 clipSpaceReduceQueryBounds, | 259 clipSpaceReduceQueryBounds, |
| 263 &elements, | 260 &elements, |
| 264 &genID, | 261 &genID, |
| 265 &initialState, | 262 &initialState, |
| 266 &clipSpaceIBounds, | 263 &clipSpaceIBounds, |
| 267 &requiresAA); | 264 &requiresAA); |
| 268 if (elements.isEmpty()) { | 265 if (elements.isEmpty()) { |
| 269 if (GrReducedClip::kAllIn_InitialState == initialState) { | 266 if (GrReducedClip::kAllOut_InitialState == initialState) { |
| 270 if (clipSpaceIBounds == clipSpaceRTIBounds) { | 267 return false; |
| 271 return true; | 268 } else { |
| 269 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | |
| 270 scissorSpaceIBounds.offset(-clip.origin()); | |
| 271 if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) { | |
| 272 out->makeScissored(scissorSpaceIBounds); | |
| 272 } | 273 } |
| 273 } else { | 274 return true; |
| 274 return false; | |
| 275 } | 275 } |
| 276 } | 276 } |
| 277 | 277 |
| 278 // 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: |
| 279 // isect RR | 279 // isect RR |
| 280 // diff RR | 280 // diff RR |
| 281 // isect convex_poly | 281 // isect convex_poly |
| 282 // isect convex_poly | 282 // isect convex_poly |
| 283 // 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 |
| 284 // 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 |
| 285 // longer shaders. | 285 // longer shaders. |
| 286 if (elements.count() <= kMaxAnalyticElements) { | 286 if (elements.count() <= kMaxAnalyticElements) { |
| 287 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), | 287 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), |
| 288 SkIntToScalar(-clip.origin().fY) }; | 288 SkIntToScalar(-clip.origin().fY) }; |
| 289 // When there are multiple samples we want to do per-sample clipping, no t compute a | 289 // When there are multiple samples we want to do per-sample clipping, no t compute a |
| 290 // fractional pixel coverage. | 290 // fractional pixel coverage. |
| 291 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); | 291 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); |
| 292 if (disallowAnalyticAA && !drawContext->numColorSamples()) { | 292 if (disallowAnalyticAA && !drawContext->numColorSamples()) { |
| 293 // With a single color sample, any coverage info is lost from color once it hits the | 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 | 294 // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe |
| 295 // is multisampled. | 295 // is multisampled. |
| 296 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || | 296 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || |
| 297 pipelineBuilder.hasUserStencilSettings(); | 297 pipelineBuilder.hasUserStencilSettings(); |
| 298 } | 298 } |
| 299 sk_sp<GrFragmentProcessor> clipFP; | 299 sk_sp<GrFragmentProcessor> clipFP; |
| 300 if (elements.isEmpty() || | 300 if (requiresAA && |
| 301 (requiresAA && | 301 get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTOf fset, devBounds, |
| 302 get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTO ffset, devBounds, | 302 &clipFP)) { |
| 303 &clipFP))) { | |
| 304 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 303 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 305 scissorSpaceIBounds.offset(-clip.origin()); | 304 scissorSpaceIBounds.offset(-clip.origin()); |
| 306 if (!devBounds || !SkRect::Make(scissorSpaceIBounds).contains(*devBo unds)) { | 305 if (!SkRect::Make(scissorSpaceIBounds).contains(devBounds)) { |
| 307 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds ); | 306 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds ); |
| 308 return true; | 307 return true; |
| 309 } | 308 } |
| 310 out->makeFPBased(std::move(clipFP)); | 309 out->makeFPBased(std::move(clipFP)); |
| 311 return true; | 310 return true; |
| 312 } | 311 } |
| 313 } | 312 } |
| 314 | 313 |
| 315 // If the stencil buffer is multisampled we can use it to do everything. | 314 // If the stencil buffer is multisampled we can use it to do everything. |
| 316 if (!drawContext->isStencilBufferMultisampled() && requiresAA) { | 315 if (!drawContext->isStencilBufferMultisampled() && requiresAA) { |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 798 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); | 797 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); |
| 799 if (!result) { | 798 if (!result) { |
| 800 return nullptr; | 799 return nullptr; |
| 801 } | 800 } |
| 802 result->resourcePriv().setUniqueKey(key); | 801 result->resourcePriv().setUniqueKey(key); |
| 803 | 802 |
| 804 helper.toTexture(result.get()); | 803 helper.toTexture(result.get()); |
| 805 | 804 |
| 806 return result; | 805 return result; |
| 807 } | 806 } |
| OLD | NEW |