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 "GrAAConvexPathRenderer.h" | 9 #include "GrAAConvexPathRenderer.h" |
10 #include "GrAAHairLinePathRenderer.h" | 10 #include "GrAAHairLinePathRenderer.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "effects/GrTextureDomain.h" | 25 #include "effects/GrTextureDomain.h" |
26 | 26 |
27 typedef SkClipStack::Element Element; | 27 typedef SkClipStack::Element Element; |
28 | 28 |
29 //////////////////////////////////////////////////////////////////////////////// | 29 //////////////////////////////////////////////////////////////////////////////// |
30 namespace { | 30 namespace { |
31 // set up the draw state to enable the aa clipping mask. Besides setting up the | 31 // set up the draw state to enable the aa clipping mask. Besides setting up the |
32 // stage matrix this also alters the vertex layout | 32 // stage matrix this also alters the vertex layout |
33 void setup_drawstate_aaclip(const GrPipelineBuilder& pipelineBuilder, | 33 void setup_drawstate_aaclip(const GrPipelineBuilder& pipelineBuilder, |
34 GrTexture* result, | 34 GrTexture* result, |
35 GrPipelineBuilder::AutoRestoreFragmentProcessors* ar
fp, | 35 GrPipelineBuilder::AutoRestoreFragmentProcessorState
* arfps, |
36 GrPipelineBuilder::AutoRestoreProcessorDataManager*
arpdm, | |
37 const SkIRect &devBound) { | 36 const SkIRect &devBound) { |
38 SkASSERT(arfp && arpdm); | 37 SkASSERT(arfps); |
39 arfp->set(&pipelineBuilder); | 38 arfps->set(&pipelineBuilder); |
40 arpdm->set(&pipelineBuilder); | |
41 | 39 |
42 SkMatrix mat; | 40 SkMatrix mat; |
43 // We use device coords to compute the texture coordinates. We set our matri
x to be a | 41 // We use device coords to compute the texture coordinates. We set our matri
x to be a |
44 // translation to the devBound, and then a scaling matrix to normalized coor
ds. | 42 // translation to the devBound, and then a scaling matrix to normalized coor
ds. |
45 mat.setIDiv(result->width(), result->height()); | 43 mat.setIDiv(result->width(), result->height()); |
46 mat.preTranslate(SkIntToScalar(-devBound.fLeft), | 44 mat.preTranslate(SkIntToScalar(-devBound.fLeft), |
47 SkIntToScalar(-devBound.fTop)); | 45 SkIntToScalar(-devBound.fTop)); |
48 | 46 |
49 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); | 47 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); |
50 // This could be a long-lived effect that is cached with the alpha-mask. | 48 // This could be a long-lived effect that is cached with the alpha-mask. |
51 arfp->addCoverageProcessor( | 49 arfps->addCoverageProcessor( |
52 GrTextureDomainEffect::Create(arpdm->getProcessorDataManager(), | 50 GrTextureDomainEffect::Create(arfps->getProcessorDataManager(), |
53 result, | 51 result, |
54 mat, | 52 mat, |
55 GrTextureDomain::MakeTexelDomain(result, d
omainTexels), | 53 GrTextureDomain::MakeTexelDomain(result, d
omainTexels), |
56 GrTextureDomain::kDecal_Mode, | 54 GrTextureDomain::kDecal_Mode, |
57 GrTextureParams::kNone_FilterMode, | 55 GrTextureParams::kNone_FilterMode, |
58 kDevice_GrCoordSet))->unref(); | 56 kDevice_GrCoordSet))->unref(); |
59 } | 57 } |
60 | 58 |
61 bool path_needs_SW_renderer(GrContext* context, | 59 bool path_needs_SW_renderer(GrContext* context, |
62 const GrDrawTarget* gpu, | 60 const GrDrawTarget* gpu, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 element->asPath(&path); | 114 element->asPath(&path); |
117 if (path_needs_SW_renderer(this->getContext(), fClipTarget, pipeline
Builder, translate, | 115 if (path_needs_SW_renderer(this->getContext(), fClipTarget, pipeline
Builder, translate, |
118 path, stroke, element->isAA())) { | 116 path, stroke, element->isAA())) { |
119 return true; | 117 return true; |
120 } | 118 } |
121 } | 119 } |
122 } | 120 } |
123 return false; | 121 return false; |
124 } | 122 } |
125 | 123 |
126 bool GrClipMaskManager::installClipEffects(const GrPipelineBuilder& pipelineBuil
der, | 124 bool GrClipMaskManager::installClipEffects( |
127 GrPipelineBuilder::AutoRestoreFragmen
tProcessors* arfp, | 125 const GrPipelineBuilder& pipelineBuilder, |
128 const GrReducedClip::ElementList& ele
ments, | 126 GrPipelineBuilder::AutoRestoreFragmentProcessorState* arfps, |
129 const SkVector& clipToRTOffset, | 127 const GrReducedClip::ElementList& elements, |
130 const SkRect* drawBounds) { | 128 const SkVector& clipToRTOffset, |
| 129 const SkRect* drawBounds) { |
131 SkRect boundsInClipSpace; | 130 SkRect boundsInClipSpace; |
132 if (drawBounds) { | 131 if (drawBounds) { |
133 boundsInClipSpace = *drawBounds; | 132 boundsInClipSpace = *drawBounds; |
134 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); | 133 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); |
135 } | 134 } |
136 | 135 |
137 arfp->set(&pipelineBuilder); | 136 arfps->set(&pipelineBuilder); |
138 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 137 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
139 GrReducedClip::ElementList::Iter iter(elements); | 138 GrReducedClip::ElementList::Iter iter(elements); |
140 bool failed = false; | 139 bool failed = false; |
141 while (iter.get()) { | 140 while (iter.get()) { |
142 SkRegion::Op op = iter.get()->getOp(); | 141 SkRegion::Op op = iter.get()->getOp(); |
143 bool invert; | 142 bool invert; |
144 bool skip = false; | 143 bool skip = false; |
145 switch (op) { | 144 switch (op) { |
146 case SkRegion::kReplace_Op: | 145 case SkRegion::kReplace_Op: |
147 SkASSERT(iter.get() == elements.head()); | 146 SkASSERT(iter.get() == elements.head()); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 case SkClipStack::Element::kRect_Type: { | 193 case SkClipStack::Element::kRect_Type: { |
195 SkRect rect = iter.get()->getRect(); | 194 SkRect rect = iter.get()->getRect(); |
196 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); | 195 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
197 fp.reset(GrConvexPolyEffect::Create(edgeType, rect)); | 196 fp.reset(GrConvexPolyEffect::Create(edgeType, rect)); |
198 break; | 197 break; |
199 } | 198 } |
200 default: | 199 default: |
201 break; | 200 break; |
202 } | 201 } |
203 if (fp) { | 202 if (fp) { |
204 arfp->addCoverageProcessor(fp); | 203 arfps->addCoverageProcessor(fp); |
205 } else { | 204 } else { |
206 failed = true; | 205 failed = true; |
207 break; | 206 break; |
208 } | 207 } |
209 } | 208 } |
210 iter.next(); | 209 iter.next(); |
211 } | 210 } |
212 | 211 |
213 if (failed) { | 212 if (failed) { |
214 arfp->set(NULL); | 213 arfps->set(NULL); |
215 } | 214 } |
216 return !failed; | 215 return !failed; |
217 } | 216 } |
218 | 217 |
219 //////////////////////////////////////////////////////////////////////////////// | 218 //////////////////////////////////////////////////////////////////////////////// |
220 // sort out what kind of clip mask needs to be created: alpha, stencil, | 219 // sort out what kind of clip mask needs to be created: alpha, stencil, |
221 // scissor, or entirely software | 220 // scissor, or entirely software |
222 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, | 221 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, |
223 GrPipelineBuilder::AutoRestoreFragmentProc
essors* arfp, | 222 GrPipelineBuilder::AutoRestoreFragmentProc
essorState* arfps, |
224 GrPipelineBuilder::AutoRestoreStencil* ars
, | 223 GrPipelineBuilder::AutoRestoreStencil* ars
, |
225 GrPipelineBuilder::AutoRestoreProcessorDat
aManager* arpdm, | |
226 GrScissorState* scissorState, | 224 GrScissorState* scissorState, |
227 const SkRect* devBounds) { | 225 const SkRect* devBounds) { |
228 fCurrClipMaskType = kNone_ClipMaskType; | 226 fCurrClipMaskType = kNone_ClipMaskType; |
229 if (kRespectClip_StencilClipMode == fClipMode) { | 227 if (kRespectClip_StencilClipMode == fClipMode) { |
230 fClipMode = kIgnoreClip_StencilClipMode; | 228 fClipMode = kIgnoreClip_StencilClipMode; |
231 } | 229 } |
232 | 230 |
233 GrReducedClip::ElementList elements(16); | 231 GrReducedClip::ElementList elements(16); |
234 int32_t genID = 0; | 232 int32_t genID = 0; |
235 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; | 233 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 // diff RR | 287 // diff RR |
290 // isect convex_poly | 288 // isect convex_poly |
291 // isect convex_poly | 289 // isect convex_poly |
292 // when drawing rounded div borders. This could probably be tuned based on a | 290 // when drawing rounded div borders. This could probably be tuned based on a |
293 // configuration's relative costs of switching RTs to generate a mask vs | 291 // configuration's relative costs of switching RTs to generate a mask vs |
294 // longer shaders. | 292 // longer shaders. |
295 if (elements.count() <= 4) { | 293 if (elements.count() <= 4) { |
296 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), | 294 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), |
297 SkIntToScalar(-clip.origin().fY) }; | 295 SkIntToScalar(-clip.origin().fY) }; |
298 if (elements.isEmpty() || | 296 if (elements.isEmpty() || |
299 (requiresAA && this->installClipEffects(pipelineBuilder, arfp, eleme
nts, clipToRTOffset, | 297 (requiresAA && this->installClipEffects(pipelineBuilder, arfps, elem
ents, clipToRTOffset, |
300 devBounds))) { | 298 devBounds))) { |
301 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 299 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
302 scissorSpaceIBounds.offset(-clip.origin()); | 300 scissorSpaceIBounds.offset(-clip.origin()); |
303 if (NULL == devBounds || | 301 if (NULL == devBounds || |
304 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { | 302 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { |
305 scissorState->set(scissorSpaceIBounds); | 303 scissorState->set(scissorSpaceIBounds); |
306 } | 304 } |
307 this->setPipelineBuilderStencil(pipelineBuilder, ars); | 305 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
308 return true; | 306 return true; |
309 } | 307 } |
(...skipping 19 matching lines...) Expand all Loading... |
329 clipSpaceIBounds); | 327 clipSpaceIBounds); |
330 } else { | 328 } else { |
331 result = this->createAlphaClipMask(genID, | 329 result = this->createAlphaClipMask(genID, |
332 initialState, | 330 initialState, |
333 elements, | 331 elements, |
334 clipToMaskOffset, | 332 clipToMaskOffset, |
335 clipSpaceIBounds); | 333 clipSpaceIBounds); |
336 } | 334 } |
337 | 335 |
338 if (result) { | 336 if (result) { |
339 arfp->set(&pipelineBuilder); | 337 arfps->set(&pipelineBuilder); |
340 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 338 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
341 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 339 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
342 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 340 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
343 rtSpaceMaskBounds.offset(-clip.origin()); | 341 rtSpaceMaskBounds.offset(-clip.origin()); |
344 setup_drawstate_aaclip(pipelineBuilder, result, arfp, arpdm, rtSpace
MaskBounds); | 342 setup_drawstate_aaclip(pipelineBuilder, result, arfps, rtSpaceMaskBo
unds); |
345 this->setPipelineBuilderStencil(pipelineBuilder, ars); | 343 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
346 return true; | 344 return true; |
347 } | 345 } |
348 // if alpha clip mask creation fails fall through to the non-AA code pat
hs | 346 // if alpha clip mask creation fails fall through to the non-AA code pat
hs |
349 } | 347 } |
350 | 348 |
351 // Either a hard (stencil buffer) clip was explicitly requested or an anti-a
liased clip couldn't | 349 // Either a hard (stencil buffer) clip was explicitly requested or an anti-a
liased clip couldn't |
352 // be created. In either case, free up the texture in the anti-aliased mask
cache. | 350 // be created. In either case, free up the texture in the anti-aliased mask
cache. |
353 // TODO: this may require more investigation. Ganesh performs a lot of utili
ty draws (e.g., | 351 // TODO: this may require more investigation. Ganesh performs a lot of utili
ty draws (e.g., |
354 // clears, InOrderDrawBuffer playbacks) that hit the stencil buffer path. Th
ese may be | 352 // clears, InOrderDrawBuffer playbacks) that hit the stencil buffer path. Th
ese may be |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1123 fAACache.purgeResources(); | 1121 fAACache.purgeResources(); |
1124 } | 1122 } |
1125 | 1123 |
1126 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, | 1124 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, |
1127 GrStencilSettings* settings) { | 1125 GrStencilSettings* settings) { |
1128 if (stencilAttachment) { | 1126 if (stencilAttachment) { |
1129 int stencilBits = stencilAttachment->bits(); | 1127 int stencilBits = stencilAttachment->bits(); |
1130 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1128 this->adjustStencilParams(settings, fClipMode, stencilBits); |
1131 } | 1129 } |
1132 } | 1130 } |
OLD | NEW |