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