Chromium Code Reviews| 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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 103 return true; | 103 return true; |
| 104 } | 104 } |
| 105 } | 105 } |
| 106 } | 106 } |
| 107 return false; | 107 return false; |
| 108 } | 108 } |
| 109 | 109 |
| 110 bool GrClipMaskManager::installClipEffects(const ElementList& elements, | 110 bool GrClipMaskManager::installClipEffects(const ElementList& elements, |
| 111 GrDrawState::AutoRestoreEffects* are, | 111 GrDrawState::AutoRestoreEffects* are, |
| 112 const SkVector& clipToRTOffset, | 112 const SkVector& clipToRTOffset, |
| 113 const SkRect* drawBounds) { | 113 const SkRect* drawBounds, |
| 114 SkIRect* scissorRect) { | |
| 114 | 115 |
|
robertphillips
2014/07/02 14:44:34
SkASSERT(NULL != scissorRect && scissorRect->isEmp
bsalomon
2014/07/02 16:36:46
Added the NULL assertion, I'm not sure this functi
robertphillips
2014/07/02 16:48:28
Fair enough.
| |
| 115 GrDrawState* drawState = fGpu->drawState(); | 116 GrDrawState* drawState = fGpu->drawState(); |
| 116 SkRect boundsInClipSpace; | 117 SkRect boundsInClipSpace; |
| 117 if (NULL != drawBounds) { | 118 if (NULL != drawBounds) { |
| 118 boundsInClipSpace = *drawBounds; | 119 boundsInClipSpace = *drawBounds; |
| 119 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); | 120 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); |
| 120 } | 121 } |
| 121 | 122 |
| 122 are->set(drawState); | 123 are->set(drawState); |
| 123 GrRenderTarget* rt = drawState->getRenderTarget(); | 124 GrRenderTarget* rt = drawState->getRenderTarget(); |
| 124 ElementList::Iter iter(elements); | 125 // We iterate from the top of the stack to the bottom. We do this because we select the first |
| 126 // BW rectangle as the scissor. Clients performing hierarchical rendering te nd to use smaller | |
| 127 // clips towards the top of the clip stack. Smaller scissor rects can help t iled architectures | |
| 128 // skip processing tiles for draws. | |
| 129 ElementList::Iter iter(elements, ElementList::Iter::kTail_IterStart); | |
| 125 | 130 |
| 126 bool setARE = false; | 131 bool setARE = false; |
| 127 bool failed = false; | 132 bool failed = false; |
| 128 | 133 |
| 129 while (NULL != iter.get()) { | 134 while (NULL != iter.get()) { |
| 130 SkRegion::Op op = iter.get()->getOp(); | 135 SkRegion::Op op = iter.get()->getOp(); |
| 131 bool invert; | 136 bool invert; |
| 132 bool skip = false; | 137 bool skip = false; |
| 133 switch (op) { | 138 switch (op) { |
| 134 case SkRegion::kReplace_Op: | 139 case SkRegion::kReplace_Op: |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 150 break; | 155 break; |
| 151 } | 156 } |
| 152 if (failed) { | 157 if (failed) { |
| 153 break; | 158 break; |
| 154 } | 159 } |
| 155 | 160 |
| 156 if (!skip) { | 161 if (!skip) { |
| 157 GrEffectEdgeType edgeType; | 162 GrEffectEdgeType edgeType; |
| 158 if (GR_AA_CLIP && iter.get()->isAA()) { | 163 if (GR_AA_CLIP && iter.get()->isAA()) { |
| 159 if (rt->isMultisampled()) { | 164 if (rt->isMultisampled()) { |
| 160 // Coverage based AA clips don't place nicely with MSAA. | 165 // Coverage based AA clips don't play nicely with MSAA. |
| 161 failed = true; | 166 failed = true; |
| 162 break; | 167 break; |
| 163 } | 168 } |
| 164 edgeType = invert ? kInverseFillAA_GrEffectEdgeType : kFillAA_Gr EffectEdgeType; | 169 edgeType = invert ? kInverseFillAA_GrEffectEdgeType : kFillAA_Gr EffectEdgeType; |
| 165 } else { | 170 } else { |
| 166 edgeType = invert ? kInverseFillBW_GrEffectEdgeType : kFillBW_Gr EffectEdgeType; | 171 edgeType = invert ? kInverseFillBW_GrEffectEdgeType : kFillBW_Gr EffectEdgeType; |
| 167 } | 172 } |
|
robertphillips
2014/07/02 14:44:34
// We don't want to exit if we convert a BW rect c
bsalomon
2014/07/02 16:36:47
Done.
| |
| 173 bool failIfNoEffect = true; | |
| 168 SkAutoTUnref<GrEffectRef> effect; | 174 SkAutoTUnref<GrEffectRef> effect; |
| 169 switch (iter.get()->getType()) { | 175 switch (iter.get()->getType()) { |
| 170 case SkClipStack::Element::kPath_Type: | 176 case SkClipStack::Element::kPath_Type: |
| 171 effect.reset(GrConvexPolyEffect::Create(edgeType, iter.get() ->getPath(), | 177 effect.reset(GrConvexPolyEffect::Create(edgeType, iter.get() ->getPath(), |
| 172 &clipToRTOffset)); | 178 &clipToRTOffset)); |
| 173 break; | 179 break; |
| 174 case SkClipStack::Element::kRRect_Type: { | 180 case SkClipStack::Element::kRRect_Type: { |
| 175 SkRRect rrect = iter.get()->getRRect(); | 181 SkRRect rrect = iter.get()->getRRect(); |
| 176 rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY); | 182 rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
| 177 effect.reset(GrRRectEffect::Create(edgeType, rrect)); | 183 effect.reset(GrRRectEffect::Create(edgeType, rrect)); |
| 178 break; | 184 break; |
| 179 } | 185 } |
| 180 case SkClipStack::Element::kRect_Type: { | 186 case SkClipStack::Element::kRect_Type: { |
| 181 SkRect rect = iter.get()->getRect(); | 187 SkRect rect = iter.get()->getRect(); |
| 182 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); | 188 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
|
robertphillips
2014/07/02 14:44:34
Kind of hand wavy here but what about something li
bsalomon
2014/07/02 16:36:47
Expanding how? The round out? I think that's what
| |
| 183 effect.reset(GrConvexPolyEffect::Create(edgeType, rect)); | 189 if (kFillBW_GrEffectEdgeType == edgeType && scissorRect->isE mpty()) { |
| 190 rect.roundOut(scissorRect); | |
| 191 failIfNoEffect = false; | |
| 192 } else { | |
| 193 effect.reset(GrConvexPolyEffect::Create(edgeType, rect)) ; | |
| 194 } | |
| 184 break; | 195 break; |
| 185 } | 196 } |
| 186 default: | 197 default: |
| 187 break; | 198 break; |
| 188 } | 199 } |
| 189 if (effect) { | 200 if (effect) { |
| 190 if (!setARE) { | 201 if (!setARE) { |
| 191 are->set(fGpu->drawState()); | 202 are->set(fGpu->drawState()); |
| 192 setARE = true; | 203 setARE = true; |
| 193 } | 204 } |
| 194 fGpu->drawState()->addCoverageEffect(effect); | 205 fGpu->drawState()->addCoverageEffect(effect); |
| 195 } else { | 206 } else if (failIfNoEffect) { |
| 196 failed = true; | 207 failed = true; |
| 197 break; | 208 break; |
| 198 } | 209 } |
| 199 } | 210 } |
| 200 iter.next(); | 211 iter.prev(); |
| 201 } | 212 } |
| 202 | 213 |
| 203 if (failed) { | 214 if (failed) { |
| 204 are->set(NULL); | 215 are->set(NULL); |
| 205 } | 216 } |
| 206 | 217 |
| 207 return !failed; | 218 return !failed; |
| 208 } | 219 } |
| 209 | 220 |
| 210 //////////////////////////////////////////////////////////////////////////////// | 221 //////////////////////////////////////////////////////////////////////////////// |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 | 267 |
| 257 // An element count of 4 was chosen because of the common pattern in Blink o f: | 268 // An element count of 4 was chosen because of the common pattern in Blink o f: |
| 258 // isect RR | 269 // isect RR |
| 259 // diff RR | 270 // diff RR |
| 260 // isect convex_poly | 271 // isect convex_poly |
| 261 // isect convex_poly | 272 // isect convex_poly |
| 262 // when drawing rounded div borders. This could probably be tuned based on a | 273 // when drawing rounded div borders. This could probably be tuned based on a |
| 263 // configuration's relative costs of switching RTs to generate a mask vs | 274 // configuration's relative costs of switching RTs to generate a mask vs |
| 264 // longer shaders. | 275 // longer shaders. |
| 265 if (elements.count() <= 4) { | 276 if (elements.count() <= 4) { |
| 277 SkIRect scissorRect; | |
| 278 scissorRect.setEmpty(); | |
| 266 SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX), | 279 SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX), |
| 267 SkIntToScalar(-clipDataIn->fOrigin.fY) }; | 280 SkIntToScalar(-clipDataIn->fOrigin.fY) }; |
| 268 if (elements.isEmpty() || | 281 if (elements.isEmpty() || |
| 269 (requiresAA && this->installClipEffects(elements, are, clipToRTOffse t, devBounds))) { | 282 this->installClipEffects(elements, are, clipToRTOffset, devBounds, & scissorRect)) { |
| 270 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 283 if (scissorRect.isEmpty()) { |
| 271 scissorSpaceIBounds.offset(-clipDataIn->fOrigin); | 284 // We may still want to use a scissor, especially on tiled archi tectures. |
| 272 if (NULL == devBounds || | 285 scissorRect = clipSpaceIBounds; |
| 273 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { | 286 scissorRect.offset(-clipDataIn->fOrigin); |
| 274 fGpu->enableScissor(scissorSpaceIBounds); | 287 if (NULL == devBounds || |
|
robertphillips
2014/07/02 14:44:34
Add magical SkIRect contains Rect method ?
bsalomon
2014/07/02 16:36:47
This current code is actually overkill because con
| |
| 288 !SkRect::Make(scissorRect).contains(*devBounds)) { | |
| 289 fGpu->enableScissor(scissorRect); | |
| 290 } else { | |
|
robertphillips
2014/07/02 14:44:34
Why not use devBounds intersected with scissorRect
bsalomon
2014/07/02 16:36:47
Scissor changes prevent batching. If we don't see
robertphillips
2014/07/02 16:48:28
That would make a good comment.
bsalomon
2014/07/02 17:28:46
Done, and added a comment about effects always shr
| |
| 291 fGpu->disableScissor(); | |
| 292 } | |
| 275 } else { | 293 } else { |
|
robertphillips
2014/07/02 14:44:34
Add SkIRect::intersectWH or, failing that, use SkI
bsalomon
2014/07/02 16:36:47
The intersect() methods on SkIRect all do empty ch
| |
| 276 fGpu->disableScissor(); | 294 scissorRect.fLeft = SkTMax(0, scissorRect.fLeft); |
| 295 scissorRect.fTop = SkTMax(0, scissorRect.fTop); | |
| 296 scissorRect.fRight = SkTMin(rt->width(), scissorRect.fRight); | |
| 297 scissorRect.fBottom = SkTMin(rt->height(), scissorRect.fBottom); | |
| 298 fGpu->enableScissor(scissorRect); | |
| 277 } | 299 } |
| 278 this->setGpuStencil(); | 300 this->setGpuStencil(); |
| 279 return true; | 301 return true; |
| 280 } | 302 } |
| 281 } | 303 } |
| 282 | 304 |
| 283 #if GR_AA_CLIP | 305 #if GR_AA_CLIP |
| 284 // If MSAA is enabled we can do everything in the stencil buffer. | 306 // If MSAA is enabled we can do everything in the stencil buffer. |
| 285 if (0 == rt->numSamples() && requiresAA) { | 307 if (0 == rt->numSamples() && requiresAA) { |
| 286 GrTexture* result = NULL; | 308 GrTexture* result = NULL; |
| (...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1139 | 1161 |
| 1140 // TODO: dynamically attach a stencil buffer | 1162 // TODO: dynamically attach a stencil buffer |
| 1141 int stencilBits = 0; | 1163 int stencilBits = 0; |
| 1142 GrStencilBuffer* stencilBuffer = | 1164 GrStencilBuffer* stencilBuffer = |
| 1143 drawState.getRenderTarget()->getStencilBuffer(); | 1165 drawState.getRenderTarget()->getStencilBuffer(); |
| 1144 if (NULL != stencilBuffer) { | 1166 if (NULL != stencilBuffer) { |
| 1145 stencilBits = stencilBuffer->bits(); | 1167 stencilBits = stencilBuffer->bits(); |
| 1146 this->adjustStencilParams(settings, clipMode, stencilBits); | 1168 this->adjustStencilParams(settings, clipMode, stencilBits); |
| 1147 } | 1169 } |
| 1148 } | 1170 } |
| OLD | NEW |