| 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 SkPath path; | 100 SkPath path; |
| 101 element->asPath(&path); | 101 element->asPath(&path); |
| 102 if (path_needs_SW_renderer(this->getContext(), fGpu, path, stroke, e
lement->isAA())) { | 102 if (path_needs_SW_renderer(this->getContext(), fGpu, path, stroke, e
lement->isAA())) { |
| 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, |
| 111 GrDrawState::AutoRestoreEffects* are, |
| 112 const SkVector& clipToRTOffset, |
| 113 const SkRect* drawBounds) { |
| 114 |
| 115 GrDrawState* drawState = fGpu->drawState(); |
| 116 SkRect boundsInClipSpace; |
| 117 if (NULL != drawBounds) { |
| 118 boundsInClipSpace = *drawBounds; |
| 119 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); |
| 120 } |
| 121 |
| 122 are->set(drawState); |
| 123 GrRenderTarget* rt = drawState->getRenderTarget(); |
| 124 ElementList::Iter iter(elements); |
| 125 |
| 126 bool setARE = false; |
| 127 bool failed = false; |
| 128 |
| 129 while (NULL != iter.get()) { |
| 130 SkRegion::Op op = iter.get()->getOp(); |
| 131 bool invert; |
| 132 bool skip = false; |
| 133 switch (op) { |
| 134 case SkRegion::kReplace_Op: |
| 135 SkASSERT(iter.get() == elements.head()); |
| 136 // Fallthrough, handled same as intersect. |
| 137 case SkRegion::kIntersect_Op: |
| 138 invert = false; |
| 139 if (NULL != drawBounds && iter.get()->contains(boundsInClipSpace
)) { |
| 140 skip = true; |
| 141 } |
| 142 break; |
| 143 case SkRegion::kDifference_Op: |
| 144 invert = true; |
| 145 // We don't currently have a cheap test for whether a rect is fu
lly outside an |
| 146 // element's primitive, so don't attempt to set skip. |
| 147 break; |
| 148 default: |
| 149 failed = true; |
| 150 break; |
| 151 } |
| 152 if (failed) { |
| 153 break; |
| 154 } |
| 155 |
| 156 if (!skip) { |
| 157 GrEffectEdgeType edgeType; |
| 158 if (GR_AA_CLIP && iter.get()->isAA()) { |
| 159 if (rt->isMultisampled()) { |
| 160 // Coverage based AA clips don't place nicely with MSAA. |
| 161 failed = true; |
| 162 break; |
| 163 } |
| 164 edgeType = invert ? kInverseFillAA_GrEffectEdgeType : kFillAA_Gr
EffectEdgeType; |
| 165 } else { |
| 166 edgeType = invert ? kInverseFillBW_GrEffectEdgeType : kFillBW_Gr
EffectEdgeType; |
| 167 } |
| 168 SkAutoTUnref<GrEffectRef> effect; |
| 169 switch (iter.get()->getType()) { |
| 170 case SkClipStack::Element::kPath_Type: |
| 171 effect.reset(GrConvexPolyEffect::Create(edgeType, iter.get()
->getPath(), |
| 172 &clipToRTOffset)); |
| 173 break; |
| 174 case SkClipStack::Element::kRRect_Type: { |
| 175 SkRRect rrect = iter.get()->getRRect(); |
| 176 rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
| 177 effect.reset(GrRRectEffect::Create(edgeType, rrect)); |
| 178 break; |
| 179 } |
| 180 case SkClipStack::Element::kRect_Type: { |
| 181 SkRect rect = iter.get()->getRect(); |
| 182 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
| 183 effect.reset(GrConvexPolyEffect::Create(edgeType, rect)); |
| 184 break; |
| 185 } |
| 186 default: |
| 187 break; |
| 188 } |
| 189 if (effect) { |
| 190 if (!setARE) { |
| 191 are->set(fGpu->drawState()); |
| 192 setARE = true; |
| 193 } |
| 194 fGpu->drawState()->addCoverageEffect(effect); |
| 195 } else { |
| 196 failed = true; |
| 197 break; |
| 198 } |
| 199 } |
| 200 iter.next(); |
| 201 } |
| 202 |
| 203 if (failed) { |
| 204 are->set(NULL); |
| 205 } |
| 206 |
| 207 return !failed; |
| 208 } |
| 209 |
| 110 //////////////////////////////////////////////////////////////////////////////// | 210 //////////////////////////////////////////////////////////////////////////////// |
| 111 // sort out what kind of clip mask needs to be created: alpha, stencil, | 211 // sort out what kind of clip mask needs to be created: alpha, stencil, |
| 112 // scissor, or entirely software | 212 // scissor, or entirely software |
| 113 bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, | 213 bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
| 114 GrDrawState::AutoRestoreEffects* are, | 214 GrDrawState::AutoRestoreEffects* are, |
| 115 const SkRect* devBounds) { | 215 const SkRect* devBounds) { |
| 116 fCurrClipMaskType = kNone_ClipMaskType; | 216 fCurrClipMaskType = kNone_ClipMaskType; |
| 117 | 217 |
| 118 ElementList elements(16); | 218 ElementList elements(16); |
| 119 int32_t genID; | 219 int32_t genID; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 149 } | 249 } |
| 150 } | 250 } |
| 151 } | 251 } |
| 152 | 252 |
| 153 if (ignoreClip) { | 253 if (ignoreClip) { |
| 154 fGpu->disableScissor(); | 254 fGpu->disableScissor(); |
| 155 this->setGpuStencil(); | 255 this->setGpuStencil(); |
| 156 return true; | 256 return true; |
| 157 } | 257 } |
| 158 | 258 |
| 159 // If there is only one clip element we check whether the draw's bounds are
contained | 259 // An element count of 4 was chosen because of the common pattern in Blink o
f: |
| 160 // fully within the clip. If not, we install an effect that handles the clip
for some | 260 // isect RR |
| 161 // cases. | 261 // diff RR |
| 162 if (1 == elements.count() && SkRegion::kReplace_Op == elements.tail()->getOp
()) { | 262 // isect convex_poly |
| 163 if (NULL != devBounds) { | 263 // isect convex_poly |
| 164 SkRect boundsInClipSpace = *devBounds; | 264 // when drawing rounded div borders. This could probably be tuned based on a |
| 165 boundsInClipSpace.offset(SkIntToScalar(clipDataIn->fOrigin.fX), | 265 // configuration's relative costs of switching RTs to generate a mask vs |
| 166 SkIntToScalar(clipDataIn->fOrigin.fY)); | 266 // longer shaders. |
| 167 if (elements.tail()->contains(boundsInClipSpace)) { | 267 if (elements.count() <= 4) { |
| 168 fGpu->disableScissor(); | 268 SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX), |
| 169 this->setGpuStencil(); | |
| 170 return true; | |
| 171 } | |
| 172 } | |
| 173 Element::Type type = elements.tail()->getType(); | |
| 174 bool isAA = GR_AA_CLIP && elements.tail()->isAA(); | |
| 175 SkAutoTUnref<GrEffectRef> effect; | |
| 176 if (SkClipStack::Element::kPath_Type == type) { | |
| 177 const SkPath& path = elements.tail()->getPath(); | |
| 178 if (rt->isMultisampled()) { | |
| 179 // A coverage effect for AA clipping won't play nicely with MSAA
. | |
| 180 if (!isAA) { | |
| 181 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), | |
| 182 SkIntToScalar(-clipDataIn->fOrigin.fY) }
; | |
| 183 effect.reset(GrConvexPolyEffect::Create(kFillBW_GrEffectEdge
Type, | |
| 184 path, &offset)); | |
| 185 } | |
| 186 } else { | |
| 187 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), | |
| 188 SkIntToScalar(-clipDataIn->fOrigin.fY) }; | 269 SkIntToScalar(-clipDataIn->fOrigin.fY) }; |
| 189 GrEffectEdgeType type = isAA ? kFillAA_GrEffectEdgeType : kFillB
W_GrEffectEdgeType; | 270 if (elements.isEmpty() || |
| 190 effect.reset(GrConvexPolyEffect::Create(type, path, &offset)); | 271 this->installClipEffects(elements, are, clipToRTOffset, devBounds))
{ |
| 191 } | |
| 192 } else if (isAA && SkClipStack::Element::kRRect_Type == type && !rt->isM
ultisampled()) { | |
| 193 const SkRRect& rrect = elements.tail()->getRRect(); | |
| 194 effect.reset(GrRRectEffect::Create(kFillAA_GrEffectEdgeType, rrect))
; | |
| 195 } else if (isAA && SkClipStack::Element::kRect_Type == type && !rt->isMu
ltisampled()) { | |
| 196 // We only handle AA/non-MSAA rects here. Coverage effect AA isn't M
SAA friendly and | |
| 197 // non-AA rect clips are handled by the scissor. | |
| 198 SkRect rect = elements.tail()->getRect(); | |
| 199 SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX), | |
| 200 SkIntToScalar(-clipDataIn->fOrigin.fY) }; | |
| 201 rect.offset(offset); | |
| 202 effect.reset(GrConvexPolyEffect::Create(kFillAA_GrEffectEdgeType, re
ct)); | |
| 203 // This should never fail. | |
| 204 SkASSERT(effect); | |
| 205 } | |
| 206 if (effect) { | |
| 207 are->set(fGpu->drawState()); | |
| 208 fGpu->drawState()->addCoverageEffect(effect); | |
| 209 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 272 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 210 scissorSpaceIBounds.offset(-clipDataIn->fOrigin); | 273 scissorSpaceIBounds.offset(-clipDataIn->fOrigin); |
| 211 fGpu->enableScissor(scissorSpaceIBounds); | 274 if (NULL == devBounds || |
| 275 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { |
| 276 fGpu->enableScissor(scissorSpaceIBounds); |
| 277 } else { |
| 278 fGpu->disableScissor(); |
| 279 } |
| 212 this->setGpuStencil(); | 280 this->setGpuStencil(); |
| 213 return true; | 281 return true; |
| 214 } | 282 } |
| 215 } | 283 } |
| 216 | 284 |
| 217 #if GR_AA_CLIP | 285 #if GR_AA_CLIP |
| 218 // If MSAA is enabled we can do everything in the stencil buffer. | 286 // If MSAA is enabled we can do everything in the stencil buffer. |
| 219 if (0 == rt->numSamples() && requiresAA) { | 287 if (0 == rt->numSamples() && requiresAA) { |
| 220 GrTexture* result = NULL; | 288 GrTexture* result = NULL; |
| 221 | 289 |
| (...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 | 1144 |
| 1077 // TODO: dynamically attach a stencil buffer | 1145 // TODO: dynamically attach a stencil buffer |
| 1078 int stencilBits = 0; | 1146 int stencilBits = 0; |
| 1079 GrStencilBuffer* stencilBuffer = | 1147 GrStencilBuffer* stencilBuffer = |
| 1080 drawState.getRenderTarget()->getStencilBuffer(); | 1148 drawState.getRenderTarget()->getStencilBuffer(); |
| 1081 if (NULL != stencilBuffer) { | 1149 if (NULL != stencilBuffer) { |
| 1082 stencilBits = stencilBuffer->bits(); | 1150 stencilBits = stencilBuffer->bits(); |
| 1083 this->adjustStencilParams(settings, clipMode, stencilBits); | 1151 this->adjustStencilParams(settings, clipMode, stencilBits); |
| 1084 } | 1152 } |
| 1085 } | 1153 } |
| OLD | NEW |