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 |