| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "GrClipMaskManager.h" | 9 #include "GrClipMaskManager.h" |
| 10 #include "GrAAConvexPathRenderer.h" | 10 #include "GrAAConvexPathRenderer.h" |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 } | 106 } |
| 107 | 107 |
| 108 //////////////////////////////////////////////////////////////////////////////// | 108 //////////////////////////////////////////////////////////////////////////////// |
| 109 // sort out what kind of clip mask needs to be created: alpha, stencil, | 109 // sort out what kind of clip mask needs to be created: alpha, stencil, |
| 110 // scissor, or entirely software | 110 // scissor, or entirely software |
| 111 bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, | 111 bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
| 112 GrDrawState::AutoRestoreEffects* are) { | 112 GrDrawState::AutoRestoreEffects* are) { |
| 113 fCurrClipMaskType = kNone_ClipMaskType; | 113 fCurrClipMaskType = kNone_ClipMaskType; |
| 114 | 114 |
| 115 ElementList elements(16); | 115 ElementList elements(16); |
| 116 int32_t genID; | |
| 117 InitialState initialState; | 116 InitialState initialState; |
| 118 SkIRect clipSpaceIBounds; | 117 SkIRect clipSpaceIBounds; |
| 119 bool requiresAA; | 118 bool requiresAA; |
| 120 bool isRect = false; | 119 bool isRect = false; |
| 121 | 120 |
| 122 GrDrawState* drawState = fGpu->drawState(); | 121 GrDrawState* drawState = fGpu->drawState(); |
| 123 | 122 |
| 124 const GrRenderTarget* rt = drawState->getRenderTarget(); | 123 const GrRenderTarget* rt = drawState->getRenderTarget(); |
| 125 // GrDrawTarget should have filtered this for us | 124 // GrDrawTarget should have filtered this for us |
| 126 SkASSERT(NULL != rt); | 125 SkASSERT(NULL != rt); |
| 127 | 126 |
| 128 bool ignoreClip = !drawState->isClipState() || clipDataIn->fClipStack->isWid
eOpen(); | 127 bool ignoreClip = !drawState->isClipState() || clipDataIn->fClipStack->isWid
eOpen(); |
| 129 | 128 |
| 130 if (!ignoreClip) { | 129 if (!ignoreClip) { |
| 131 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 130 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
| 132 clipSpaceRTIBounds.offset(clipDataIn->fOrigin); | 131 clipSpaceRTIBounds.offset(clipDataIn->fOrigin); |
| 133 ReduceClipStack(*clipDataIn->fClipStack, | 132 ReduceClipStack(*clipDataIn->fClipStack, |
| 134 clipSpaceRTIBounds, | 133 clipSpaceRTIBounds, |
| 135 &elements, | 134 &elements, |
| 136 &genID, | |
| 137 &initialState, | 135 &initialState, |
| 138 &clipSpaceIBounds, | 136 &clipSpaceIBounds, |
| 139 &requiresAA); | 137 &requiresAA); |
| 140 if (elements.isEmpty()) { | 138 if (elements.isEmpty()) { |
| 141 if (kAllIn_InitialState == initialState) { | 139 if (kAllIn_InitialState == initialState) { |
| 142 ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds; | 140 ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds; |
| 143 isRect = true; | 141 isRect = true; |
| 144 } else { | 142 } else { |
| 145 return false; | 143 return false; |
| 146 } | 144 } |
| 147 } | 145 } |
| 148 } | 146 } |
| 149 | 147 |
| 150 if (ignoreClip) { | 148 if (ignoreClip) { |
| 151 fGpu->disableScissor(); | 149 fGpu->disableScissor(); |
| 152 this->setGpuStencil(); | 150 this->setGpuStencil(); |
| 153 return true; | 151 return true; |
| 154 } | 152 } |
| 155 | 153 |
| 156 #if GR_AA_CLIP | 154 #if GR_AA_CLIP |
| 157 // TODO: catch isRect && requiresAA and use clip planes if available rather
than a mask. | 155 // TODO: catch isRect && requiresAA and use clip planes if available rather
than a mask. |
| 158 | 156 |
| 159 // If MSAA is enabled we can do everything in the stencil buffer. | 157 // If MSAA is enabled we can do everything in the stencil buffer. |
| 160 if (0 == rt->numSamples() && requiresAA) { | 158 if (0 == rt->numSamples() && requiresAA) { |
| 159 int32_t genID = clipDataIn->fClipStack->getTopmostGenID(); |
| 161 GrTexture* result = NULL; | 160 GrTexture* result = NULL; |
| 162 | 161 |
| 163 if (this->useSWOnlyPath(elements)) { | 162 if (this->useSWOnlyPath(elements)) { |
| 164 // The clip geometry is complex enough that it will be more efficien
t to create it | 163 // The clip geometry is complex enough that it will be more efficien
t to create it |
| 165 // entirely in software | 164 // entirely in software |
| 166 result = this->createSoftwareClipMask(genID, | 165 result = this->createSoftwareClipMask(genID, |
| 167 initialState, | 166 initialState, |
| 168 elements, | 167 elements, |
| 169 clipSpaceIBounds); | 168 clipSpaceIBounds); |
| 170 } else { | 169 } else { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 201 if (isRect) { | 200 if (isRect) { |
| 202 SkIRect clipRect = clipSpaceIBounds; | 201 SkIRect clipRect = clipSpaceIBounds; |
| 203 clipRect.offset(-clipDataIn->fOrigin); | 202 clipRect.offset(-clipDataIn->fOrigin); |
| 204 fGpu->enableScissor(clipRect); | 203 fGpu->enableScissor(clipRect); |
| 205 this->setGpuStencil(); | 204 this->setGpuStencil(); |
| 206 return true; | 205 return true; |
| 207 } | 206 } |
| 208 | 207 |
| 209 // use the stencil clip if we can't represent the clip as a rectangle. | 208 // use the stencil clip if we can't represent the clip as a rectangle. |
| 210 SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin; | 209 SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin; |
| 211 this->createStencilClipMask(genID, | 210 this->createStencilClipMask(initialState, |
| 212 initialState, | |
| 213 elements, | 211 elements, |
| 214 clipSpaceIBounds, | 212 clipSpaceIBounds, |
| 215 clipSpaceToStencilSpaceOffset); | 213 clipSpaceToStencilSpaceOffset); |
| 216 | 214 |
| 217 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 215 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
| 218 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 216 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
| 219 // use both stencil and scissor test to the bounds for the final draw. | 217 // use both stencil and scissor test to the bounds for the final draw. |
| 220 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 218 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 221 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 219 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
| 222 fGpu->enableScissor(scissorSpaceIBounds); | 220 fGpu->enableScissor(scissorSpaceIBounds); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 desc.fHeight = height; | 383 desc.fHeight = height; |
| 386 desc.fConfig = kAlpha_8_GrPixelConfig; | 384 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 387 | 385 |
| 388 temp->set(this->getContext(), desc); | 386 temp->set(this->getContext(), desc); |
| 389 } | 387 } |
| 390 | 388 |
| 391 //////////////////////////////////////////////////////////////////////////////// | 389 //////////////////////////////////////////////////////////////////////////////// |
| 392 // Handles caching & allocation (if needed) of a clip alpha-mask texture for bot
h the sw-upload | 390 // Handles caching & allocation (if needed) of a clip alpha-mask texture for bot
h the sw-upload |
| 393 // or gpu-rendered cases. Returns true if there is no more work to be done (i.e.
, we got a cache | 391 // or gpu-rendered cases. Returns true if there is no more work to be done (i.e.
, we got a cache |
| 394 // hit) | 392 // hit) |
| 395 bool GrClipMaskManager::getMaskTexture(int32_t elementsGenID, | 393 bool GrClipMaskManager::getMaskTexture(int32_t clipStackGenID, |
| 396 const SkIRect& clipSpaceIBounds, | 394 const SkIRect& clipSpaceIBounds, |
| 397 GrTexture** result, | 395 GrTexture** result, |
| 398 bool willUpload) { | 396 bool willUpload) { |
| 399 bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds); | 397 bool cached = fAACache.canReuse(clipStackGenID, clipSpaceIBounds); |
| 400 if (!cached) { | 398 if (!cached) { |
| 401 | 399 |
| 402 // There isn't a suitable entry in the cache so we create a new texture
to store the mask. | 400 // There isn't a suitable entry in the cache so we create a new texture
to store the mask. |
| 403 // Since we are setting up the cache we know the last lookup was a miss.
Free up the | 401 // Since we are setting up the cache we know the last lookup was a miss.
Free up the |
| 404 // currently cached mask so it can be reused. | 402 // currently cached mask so it can be reused. |
| 405 fAACache.reset(); | 403 fAACache.reset(); |
| 406 | 404 |
| 407 GrTextureDesc desc; | 405 GrTextureDesc desc; |
| 408 desc.fFlags = willUpload ? kNone_GrTextureFlags : kRenderTarget_GrTextur
eFlagBit; | 406 desc.fFlags = willUpload ? kNone_GrTextureFlags : kRenderTarget_GrTextur
eFlagBit; |
| 409 desc.fWidth = clipSpaceIBounds.width(); | 407 desc.fWidth = clipSpaceIBounds.width(); |
| 410 desc.fHeight = clipSpaceIBounds.height(); | 408 desc.fHeight = clipSpaceIBounds.height(); |
| 411 desc.fConfig = kRGBA_8888_GrPixelConfig; | 409 desc.fConfig = kRGBA_8888_GrPixelConfig; |
| 412 if (willUpload || this->getContext()->isConfigRenderable(kAlpha_8_GrPixe
lConfig, false)) { | 410 if (willUpload || this->getContext()->isConfigRenderable(kAlpha_8_GrPixe
lConfig, false)) { |
| 413 // We would always like A8 but it isn't supported on all platforms | 411 // We would always like A8 but it isn't supported on all platforms |
| 414 desc.fConfig = kAlpha_8_GrPixelConfig; | 412 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 415 } | 413 } |
| 416 | 414 |
| 417 fAACache.acquireMask(elementsGenID, desc, clipSpaceIBounds); | 415 fAACache.acquireMask(clipStackGenID, desc, clipSpaceIBounds); |
| 418 } | 416 } |
| 419 | 417 |
| 420 *result = fAACache.getLastMask(); | 418 *result = fAACache.getLastMask(); |
| 421 return cached; | 419 return cached; |
| 422 } | 420 } |
| 423 | 421 |
| 424 //////////////////////////////////////////////////////////////////////////////// | 422 //////////////////////////////////////////////////////////////////////////////// |
| 425 // Create a 8-bit clip mask in alpha | 423 // Create a 8-bit clip mask in alpha |
| 426 GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, | 424 GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t clipStackGenID, |
| 427 InitialState initialState, | 425 InitialState initialState, |
| 428 const ElementList& elements, | 426 const ElementList& elements, |
| 429 const SkIRect& clipSpaceIBound
s) { | 427 const SkIRect& clipSpaceIBound
s) { |
| 430 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 428 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
| 431 | 429 |
| 432 GrTexture* result; | 430 GrTexture* result; |
| 433 if (this->getMaskTexture(elementsGenID, clipSpaceIBounds, &result, false)) { | 431 if (this->getMaskTexture(clipStackGenID, clipSpaceIBounds, &result, false))
{ |
| 434 fCurrClipMaskType = kAlpha_ClipMaskType; | 432 fCurrClipMaskType = kAlpha_ClipMaskType; |
| 435 return result; | 433 return result; |
| 436 } | 434 } |
| 437 | 435 |
| 438 if (NULL == result) { | 436 if (NULL == result) { |
| 439 fAACache.reset(); | 437 fAACache.reset(); |
| 440 return NULL; | 438 return NULL; |
| 441 } | 439 } |
| 442 | 440 |
| 443 // The top-left of the mask corresponds to the top-left corner of the bounds
. | 441 // The top-left of the mask corresponds to the top-left corner of the bounds
. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 } | 562 } |
| 565 } | 563 } |
| 566 | 564 |
| 567 fCurrClipMaskType = kAlpha_ClipMaskType; | 565 fCurrClipMaskType = kAlpha_ClipMaskType; |
| 568 return result; | 566 return result; |
| 569 } | 567 } |
| 570 | 568 |
| 571 //////////////////////////////////////////////////////////////////////////////// | 569 //////////////////////////////////////////////////////////////////////////////// |
| 572 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 570 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
| 573 // (as opposed to canvas) coordinates | 571 // (as opposed to canvas) coordinates |
| 574 bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, | 572 bool GrClipMaskManager::createStencilClipMask(InitialState initialState, |
| 575 InitialState initialState, | |
| 576 const ElementList& elements, | 573 const ElementList& elements, |
| 577 const SkIRect& clipSpaceIBounds, | 574 const SkIRect& clipSpaceIBounds, |
| 578 const SkIPoint& clipSpaceToStencil
Offset) { | 575 const SkIPoint& clipSpaceToStencil
Offset) { |
| 579 | 576 |
| 580 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 577 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
| 581 | 578 |
| 582 GrDrawState* drawState = fGpu->drawState(); | 579 GrDrawState* drawState = fGpu->drawState(); |
| 583 SkASSERT(drawState->isClipState()); | 580 SkASSERT(drawState->isClipState()); |
| 584 | 581 |
| 585 GrRenderTarget* rt = drawState->getRenderTarget(); | 582 GrRenderTarget* rt = drawState->getRenderTarget(); |
| 586 SkASSERT(NULL != rt); | 583 SkASSERT(NULL != rt); |
| 587 | 584 |
| 588 // TODO: dynamically attach a SB when needed. | 585 // TODO: dynamically attach a SB when needed. |
| 589 GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); | 586 GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); |
| 590 if (NULL == stencilBuffer) { | 587 if (NULL == stencilBuffer) { |
| 591 return false; | 588 return false; |
| 592 } | 589 } |
| 590 int32_t genID = elements.tail()->getGenID(); |
| 593 | 591 |
| 594 if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpace
ToStencilOffset)) { | 592 if (stencilBuffer->mustRenderClip(genID, clipSpaceIBounds, clipSpaceToStenci
lOffset)) { |
| 595 | 593 |
| 596 stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToS
tencilOffset); | 594 stencilBuffer->setLastClip(genID, clipSpaceIBounds, clipSpaceToStencilOf
fset); |
| 597 | 595 |
| 598 // Set the matrix so that rendered clip elements are transformed from cl
ip to stencil space. | 596 // Set the matrix so that rendered clip elements are transformed from cl
ip to stencil space. |
| 599 SkVector translate = { | 597 SkVector translate = { |
| 600 SkIntToScalar(clipSpaceToStencilOffset.fX), | 598 SkIntToScalar(clipSpaceToStencilOffset.fX), |
| 601 SkIntToScalar(clipSpaceToStencilOffset.fY) | 599 SkIntToScalar(clipSpaceToStencilOffset.fY) |
| 602 }; | 600 }; |
| 603 SkMatrix matrix; | 601 SkMatrix matrix; |
| 604 matrix.setTranslate(translate); | 602 matrix.setTranslate(translate); |
| 605 GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_
ASRInit, &matrix); | 603 GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_
ASRInit, &matrix); |
| 606 drawState = fGpu->drawState(); | 604 drawState = fGpu->drawState(); |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 } else { | 914 } else { |
| 917 finished = true; | 915 finished = true; |
| 918 } | 916 } |
| 919 } | 917 } |
| 920 if (!twoSided) { | 918 if (!twoSided) { |
| 921 settings->copyFrontSettingsToBack(); | 919 settings->copyFrontSettingsToBack(); |
| 922 } | 920 } |
| 923 } | 921 } |
| 924 | 922 |
| 925 //////////////////////////////////////////////////////////////////////////////// | 923 //////////////////////////////////////////////////////////////////////////////// |
| 926 GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, | 924 GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t clipStackGenID, |
| 927 GrReducedClip::InitialState
initialState, | 925 GrReducedClip::InitialState
initialState, |
| 928 const GrReducedClip::Elemen
tList& elements, | 926 const GrReducedClip::Elemen
tList& elements, |
| 929 const SkIRect& clipSpaceIBo
unds) { | 927 const SkIRect& clipSpaceIBo
unds) { |
| 930 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 928 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
| 931 | 929 |
| 932 GrTexture* result; | 930 GrTexture* result; |
| 933 if (this->getMaskTexture(elementsGenID, clipSpaceIBounds, &result, true)) { | 931 if (this->getMaskTexture(clipStackGenID, clipSpaceIBounds, &result, true)) { |
| 934 return result; | 932 return result; |
| 935 } | 933 } |
| 936 | 934 |
| 937 if (NULL == result) { | 935 if (NULL == result) { |
| 938 fAACache.reset(); | 936 fAACache.reset(); |
| 939 return NULL; | 937 return NULL; |
| 940 } | 938 } |
| 941 | 939 |
| 942 // The mask texture may be larger than necessary. We round out the clip spac
e bounds and pin | 940 // The mask texture may be larger than necessary. We round out the clip spac
e bounds and pin |
| 943 // the top left corner of the resulting rect to the top left of the texture. | 941 // the top left corner of the resulting rect to the top left of the texture. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 | 1033 |
| 1036 // TODO: dynamically attach a stencil buffer | 1034 // TODO: dynamically attach a stencil buffer |
| 1037 int stencilBits = 0; | 1035 int stencilBits = 0; |
| 1038 GrStencilBuffer* stencilBuffer = | 1036 GrStencilBuffer* stencilBuffer = |
| 1039 drawState.getRenderTarget()->getStencilBuffer(); | 1037 drawState.getRenderTarget()->getStencilBuffer(); |
| 1040 if (NULL != stencilBuffer) { | 1038 if (NULL != stencilBuffer) { |
| 1041 stencilBits = stencilBuffer->bits(); | 1039 stencilBits = stencilBuffer->bits(); |
| 1042 this->adjustStencilParams(settings, clipMode, stencilBits); | 1040 this->adjustStencilParams(settings, clipMode, stencilBits); |
| 1043 } | 1041 } |
| 1044 } | 1042 } |
| OLD | NEW |