| 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 13 matching lines...) Expand all Loading... |
| 24 #include "effects/GrConvexPolyEffect.h" | 24 #include "effects/GrConvexPolyEffect.h" |
| 25 #include "effects/GrPorterDuffXferProcessor.h" | 25 #include "effects/GrPorterDuffXferProcessor.h" |
| 26 #include "effects/GrRRectEffect.h" | 26 #include "effects/GrRRectEffect.h" |
| 27 #include "effects/GrTextureDomain.h" | 27 #include "effects/GrTextureDomain.h" |
| 28 | 28 |
| 29 typedef SkClipStack::Element Element; | 29 typedef SkClipStack::Element Element; |
| 30 | 30 |
| 31 //////////////////////////////////////////////////////////////////////////////// | 31 //////////////////////////////////////////////////////////////////////////////// |
| 32 // set up the draw state to enable the aa clipping mask. Besides setting up the | 32 // set up the draw state to enable the aa clipping mask. Besides setting up the |
| 33 // stage matrix this also alters the vertex layout | 33 // stage matrix this also alters the vertex layout |
| 34 static const GrFragmentProcessor* create_fp_for_mask(GrTexture* result, const Sk
IRect &devBound) { | 34 static sk_sp<const GrFragmentProcessor> create_fp_for_mask(GrTexture* result, |
| 35 const SkIRect &devBou
nd) { |
| 35 SkMatrix mat; | 36 SkMatrix mat; |
| 36 // We use device coords to compute the texture coordinates. We set our matri
x to be a | 37 // We use device coords to compute the texture coordinates. We set our matri
x to be a |
| 37 // translation to the devBound, and then a scaling matrix to normalized coor
ds. | 38 // translation to the devBound, and then a scaling matrix to normalized coor
ds. |
| 38 mat.setIDiv(result->width(), result->height()); | 39 mat.setIDiv(result->width(), result->height()); |
| 39 mat.preTranslate(SkIntToScalar(-devBound.fLeft), | 40 mat.preTranslate(SkIntToScalar(-devBound.fLeft), |
| 40 SkIntToScalar(-devBound.fTop)); | 41 SkIntToScalar(-devBound.fTop)); |
| 41 | 42 |
| 42 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); | 43 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); |
| 43 return GrTextureDomainEffect::Create(result, | 44 return sk_sp<const GrFragmentProcessor>(GrTextureDomainEffect::Create( |
| 45 result, |
| 44 mat, | 46 mat, |
| 45 GrTextureDomain::MakeTexelDomain(result
, domainTexels), | 47 GrTextureDomain::MakeTexelDomain(result
, domainTexels), |
| 46 GrTextureDomain::kDecal_Mode, | 48 GrTextureDomain::kDecal_Mode, |
| 47 GrTextureParams::kNone_FilterMode, | 49 GrTextureParams::kNone_FilterMode, |
| 48 kDevice_GrCoordSet); | 50 kDevice_GrCoordSet)); |
| 49 } | 51 } |
| 50 | 52 |
| 51 static void draw_non_aa_rect(GrDrawTarget* drawTarget, | 53 static void draw_non_aa_rect(GrDrawTarget* drawTarget, |
| 52 const GrPipelineBuilder& pipelineBuilder, | 54 const GrPipelineBuilder& pipelineBuilder, |
| 53 const GrClip& clip, | 55 const GrClip& clip, |
| 54 GrColor color, | 56 GrColor color, |
| 55 const SkMatrix& viewMatrix, | 57 const SkMatrix& viewMatrix, |
| 56 const SkRect& rect) { | 58 const SkRect& rect) { |
| 57 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v
iewMatrix, rect, | 59 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v
iewMatrix, rect, |
| 58 nullptr,
nullptr)); | 60 nullptr,
nullptr)); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 return true; | 181 return true; |
| 180 } | 182 } |
| 181 } | 183 } |
| 182 return false; | 184 return false; |
| 183 } | 185 } |
| 184 | 186 |
| 185 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, | 187 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, |
| 186 bool abortIfAA, | 188 bool abortIfAA, |
| 187 SkVector& clipToRTOffset, | 189 SkVector& clipToRTOffset, |
| 188 const SkRect* drawBounds, | 190 const SkRect* drawBounds, |
| 189 const GrFragmentProcessor** res
ultFP) { | 191 sk_sp<const GrFragmentProcessor
>* resultFP) { |
| 190 SkRect boundsInClipSpace; | 192 SkRect boundsInClipSpace; |
| 191 if (drawBounds) { | 193 if (drawBounds) { |
| 192 boundsInClipSpace = *drawBounds; | 194 boundsInClipSpace = *drawBounds; |
| 193 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); | 195 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); |
| 194 } | 196 } |
| 195 SkASSERT(elements.count() <= kMaxAnalyticElements); | 197 SkASSERT(elements.count() <= kMaxAnalyticElements); |
| 196 const GrFragmentProcessor* fps[kMaxAnalyticElements]; | 198 const GrFragmentProcessor* fps[kMaxAnalyticElements]; |
| 197 for (int i = 0; i < kMaxAnalyticElements; ++i) { | 199 for (int i = 0; i < kMaxAnalyticElements; ++i) { |
| 198 fps[i] = nullptr; | 200 fps[i] = nullptr; |
| 199 } | 201 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 failed = true; | 266 failed = true; |
| 265 break; | 267 break; |
| 266 } | 268 } |
| 267 fpCnt++; | 269 fpCnt++; |
| 268 } | 270 } |
| 269 iter.next(); | 271 iter.next(); |
| 270 } | 272 } |
| 271 | 273 |
| 272 *resultFP = nullptr; | 274 *resultFP = nullptr; |
| 273 if (!failed && fpCnt) { | 275 if (!failed && fpCnt) { |
| 274 *resultFP = GrFragmentProcessor::RunInSeries(fps, fpCnt); | 276 resultFP->reset(GrFragmentProcessor::RunInSeries(fps, fpCnt)); |
| 275 } | 277 } |
| 276 for (int i = 0; i < fpCnt; ++i) { | 278 for (int i = 0; i < fpCnt; ++i) { |
| 277 fps[i]->unref(); | 279 fps[i]->unref(); |
| 278 } | 280 } |
| 279 return !failed; | 281 return !failed; |
| 280 } | 282 } |
| 281 | 283 |
| 282 //////////////////////////////////////////////////////////////////////////////// | 284 //////////////////////////////////////////////////////////////////////////////// |
| 283 // sort out what kind of clip mask needs to be created: alpha, stencil, | 285 // sort out what kind of clip mask needs to be created: alpha, stencil, |
| 284 // scissor, or entirely software | 286 // scissor, or entirely software |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 // When there are multiple samples we want to do per-sample clipping, no
t compute a | 347 // When there are multiple samples we want to do per-sample clipping, no
t compute a |
| 346 // fractional pixel coverage. | 348 // fractional pixel coverage. |
| 347 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); | 349 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); |
| 348 if (disallowAnalyticAA && !rt->numColorSamples()) { | 350 if (disallowAnalyticAA && !rt->numColorSamples()) { |
| 349 // With a single color sample, any coverage info is lost from color
once it hits the | 351 // With a single color sample, any coverage info is lost from color
once it hits the |
| 350 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe | 352 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe |
| 351 // is multisampled. | 353 // is multisampled. |
| 352 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || | 354 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || |
| 353 pipelineBuilder.hasUserStencilSettings(); | 355 pipelineBuilder.hasUserStencilSettings(); |
| 354 } | 356 } |
| 355 const GrFragmentProcessor* clipFP = nullptr; | 357 sk_sp<const GrFragmentProcessor> clipFP; |
| 356 if (elements.isEmpty() || | 358 if (elements.isEmpty() || |
| 357 (requiresAA && | 359 (requiresAA && |
| 358 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo
RTOffset, devBounds, | 360 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo
RTOffset, devBounds, |
| 359 &clipFP))) { | 361 &clipFP))) { |
| 360 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 362 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 361 scissorSpaceIBounds.offset(-clip.origin()); | 363 scissorSpaceIBounds.offset(-clip.origin()); |
| 362 if (nullptr == devBounds || | 364 if (nullptr == devBounds || |
| 363 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { | 365 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { |
| 364 out->fScissorState.set(scissorSpaceIBounds); | 366 out->makeScissoredFPBased(clipFP, scissorSpaceIBounds); |
| 367 return true; |
| 365 } | 368 } |
| 366 out->fClipCoverageFP.reset(clipFP); | 369 out->makeFPBased(clipFP); |
| 367 return true; | 370 return true; |
| 368 } | 371 } |
| 369 } | 372 } |
| 370 | 373 |
| 371 // If the stencil buffer is multisampled we can use it to do everything. | 374 // If the stencil buffer is multisampled we can use it to do everything. |
| 372 if (!rt->isStencilBufferMultisampled() && requiresAA) { | 375 if (!rt->isStencilBufferMultisampled() && requiresAA) { |
| 373 sk_sp<GrTexture> result; | 376 sk_sp<GrTexture> result; |
| 374 | 377 |
| 375 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 378 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
| 376 SkVector clipToMaskOffset = { | 379 SkVector clipToMaskOffset = { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 396 clipSpaceIBounds); | 399 clipSpaceIBounds); |
| 397 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug | 400 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug |
| 398 SkASSERT(result); | 401 SkASSERT(result); |
| 399 } | 402 } |
| 400 | 403 |
| 401 if (result) { | 404 if (result) { |
| 402 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 405 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
| 403 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 406 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
| 404 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 407 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
| 405 rtSpaceMaskBounds.offset(-clip.origin()); | 408 rtSpaceMaskBounds.offset(-clip.origin()); |
| 406 out->fClipCoverageFP.reset(create_fp_for_mask(result.get(), rtSpaceM
askBounds)); | 409 out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds)
); |
| 407 return true; | 410 return true; |
| 408 } | 411 } |
| 409 // if alpha clip mask creation fails fall through to the non-AA code pat
hs | 412 // if alpha clip mask creation fails fall through to the non-AA code pat
hs |
| 410 } | 413 } |
| 411 | 414 |
| 412 // use the stencil clip if we can't represent the clip as a rectangle. | 415 // use the stencil clip if we can't represent the clip as a rectangle. |
| 413 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); | 416 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); |
| 414 this->createStencilClipMask(rt, | 417 this->createStencilClipMask(rt, |
| 415 genID, | 418 genID, |
| 416 initialState, | 419 initialState, |
| 417 elements, | 420 elements, |
| 418 clipSpaceIBounds, | 421 clipSpaceIBounds, |
| 419 clipSpaceToStencilSpaceOffset); | 422 clipSpaceToStencilSpaceOffset); |
| 420 | 423 |
| 421 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 424 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
| 422 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 425 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
| 423 // use both stencil and scissor test to the bounds for the final draw. | 426 // use both stencil and scissor test to the bounds for the final draw. |
| 424 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 427 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 425 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 428 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
| 426 out->fScissorState.set(scissorSpaceIBounds); | 429 out->makeScissoredStencil(true, scissorSpaceIBounds); |
| 427 out->fHasStencilClip = true; | |
| 428 return true; | 430 return true; |
| 429 } | 431 } |
| 430 | 432 |
| 431 static bool stencil_element(GrDrawContext* dc, | 433 static bool stencil_element(GrDrawContext* dc, |
| 432 const GrFixedClip& clip, | 434 const GrFixedClip& clip, |
| 433 const GrUserStencilSettings* ss, | 435 const GrUserStencilSettings* ss, |
| 434 const SkMatrix& viewMatrix, | 436 const SkMatrix& viewMatrix, |
| 435 const SkClipStack::Element* element) { | 437 const SkClipStack::Element* element) { |
| 436 | 438 |
| 437 // TODO: Draw rrects directly here. | 439 // TODO: Draw rrects directly here. |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 858 sk_sp<GrTexture> result(context->resourceProvider()->createApproxTexture(des
c, 0)); | 860 sk_sp<GrTexture> result(context->resourceProvider()->createApproxTexture(des
c, 0)); |
| 859 if (!result) { | 861 if (!result) { |
| 860 return nullptr; | 862 return nullptr; |
| 861 } | 863 } |
| 862 result->resourcePriv().setUniqueKey(key); | 864 result->resourcePriv().setUniqueKey(key); |
| 863 | 865 |
| 864 helper.toTexture(result.get()); | 866 helper.toTexture(result.get()); |
| 865 | 867 |
| 866 return result; | 868 return result; |
| 867 } | 869 } |
| OLD | NEW |