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 |