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" |
| 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 |