1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrDrawState.h"
9#include "GrPaint.h"
10
11bool GrDrawState::setIdentityViewMatrix()  {
12    if (fColorStages.count() || fCoverageStages.count()) {
13        SkMatrix invVM;
14        if (!fCommon.fViewMatrix.invert(&invVM)) {
15            // sad trombone sound
16            return false;
17        }
18        for (int s = 0; s < fColorStages.count(); ++s) {
19            fColorStages[s].localCoordChange(invVM);
20        }
21        for (int s = 0; s < fCoverageStages.count(); ++s) {
22            fCoverageStages[s].localCoordChange(invVM);
23        }
24    }
25    fCommon.fViewMatrix.reset();
26    return true;
27}
28
29void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
30    SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
31
32    fColorStages.reset();
33    fCoverageStages.reset();
34
35    for (int i = 0; i < paint.numColorStages(); ++i) {
36        fColorStages.push_back(paint.getColorStage(i));
37    }
38
39    for (int i = 0; i < paint.numCoverageStages(); ++i) {
40        fCoverageStages.push_back(paint.getCoverageStage(i));
41    }
42
43    this->setRenderTarget(rt);
44
45    fCommon.fViewMatrix = vm;
46
47    // These have no equivalent in GrPaint, set them to defaults
48    fCommon.fBlendConstant = 0x0;
49    fCommon.fDrawFace = kBoth_DrawFace;
50    fCommon.fStencilSettings.setDisabled();
51    this->resetStateFlags();
52
53    // Enable the clip bit
54    this->enableState(GrDrawState::kClip_StateBit);
55
56    this->setColor(paint.getColor());
57    this->setState(GrDrawState::kDither_StateBit, paint.isDither());
58    this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
59
60    this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
61    this->setCoverage(paint.getCoverage());
62}
63
64////////////////////////////////////////////////////////////////////////////////
65
66static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
67    // this works as long as we're 4 byte-aligned
68#ifdef SK_DEBUG
69    uint32_t overlapCheck = 0;
70#endif
71    SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
72    size_t size = 0;
73    for (int index = 0; index < count; ++index) {
74        size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
75        size += attribSize;
76#ifdef SK_DEBUG
77        size_t dwordCount = attribSize >> 2;
78        uint32_t mask = (1 << dwordCount)-1;
79        size_t offsetShift = attribs[index].fOffset >> 2;
80        SkASSERT(!(overlapCheck & (mask << offsetShift)));
81        overlapCheck |= (mask << offsetShift);
82#endif
83    }
84    return size;
85}
86
87size_t GrDrawState::getVertexSize() const {
88    return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
89}
90
91////////////////////////////////////////////////////////////////////////////////
92
93void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
94    SkASSERT(count <= kMaxVertexAttribCnt);
95
96    fCommon.fVAPtr = attribs;
97    fCommon.fVACount = count;
98
99    // Set all the indices to -1
100    memset(fCommon.fFixedFunctionVertexAttribIndices,
101           0xff,
102           sizeof(fCommon.fFixedFunctionVertexAttribIndices));
103#ifdef SK_DEBUG
104    uint32_t overlapCheck = 0;
105#endif
106    for (int i = 0; i < count; ++i) {
107        if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
108            // The fixed function attribs can only be specified once
109            SkASSERT(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
110            SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
111                     GrVertexAttribTypeVectorCount(attribs[i].fType));
112            fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
113        }
114#ifdef SK_DEBUG
115        size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
116        uint32_t mask = (1 << dwordCount)-1;
117        size_t offsetShift = attribs[i].fOffset >> 2;
118        SkASSERT(!(overlapCheck & (mask << offsetShift)));
119        overlapCheck |= (mask << offsetShift);
120#endif
121    }
122    // Positions must be specified.
123    SkASSERT(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
124}
125
126////////////////////////////////////////////////////////////////////////////////
127
128void GrDrawState::setDefaultVertexAttribs() {
129    static const GrVertexAttrib kPositionAttrib =
130        {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
131
132    fCommon.fVAPtr = &kPositionAttrib;
133    fCommon.fVACount = 1;
134
135    // set all the fixed function indices to -1 except position.
136    memset(fCommon.fFixedFunctionVertexAttribIndices,
137           0xff,
138           sizeof(fCommon.fFixedFunctionVertexAttribIndices));
139    fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
140}
141
142////////////////////////////////////////////////////////////////////////////////
143
144bool GrDrawState::validateVertexAttribs() const {
145    // check consistency of effects and attributes
146    GrSLType slTypes[kMaxVertexAttribCnt];
147    for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
148        slTypes[i] = static_cast<GrSLType>(-1);
149    }
150    int totalStages = fColorStages.count() + fCoverageStages.count();
151    for (int s = 0; s < totalStages; ++s) {
152        int covIdx = s - fColorStages.count();
153        const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
154        const GrEffectRef* effect = stage.getEffect();
155        SkASSERT(NULL != effect);
156        // make sure that any attribute indices have the correct binding type, that the attrib
157        // type and effect's shader lang type are compatible, and that attributes shared by
158        // multiple effects use the same shader lang type.
159        const int* attributeIndices = stage.getVertexAttribIndices();
160        int numAttributes = stage.getVertexAttribIndexCount();
161        for (int i = 0; i < numAttributes; ++i) {
162            int attribIndex = attributeIndices[i];
163            if (attribIndex >= fCommon.fVACount ||
164                kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
165                return false;
166            }
167
168            GrSLType effectSLType = (*effect)->vertexAttribType(i);
169            GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
170            int slVecCount = GrSLTypeVectorCount(effectSLType);
171            int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
172            if (slVecCount != attribVecCount ||
173                (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
174                    slTypes[attribIndex] != effectSLType)) {
175                return false;
176            }
177            slTypes[attribIndex] = effectSLType;
178        }
179    }
180
181    return true;
182}
183
184bool GrDrawState::willEffectReadDstColor() const {
185    if (!this->isColorWriteDisabled()) {
186        for (int s = 0; s < fColorStages.count(); ++s) {
187            if ((*fColorStages[s].getEffect())->willReadDstColor()) {
188                return true;
189            }
190        }
191    }
192    for (int s = 0; s < fCoverageStages.count(); ++s) {
193        if ((*fCoverageStages[s].getEffect())->willReadDstColor()) {
194            return true;
195        }
196    }
197    return false;
198}
199
200////////////////////////////////////////////////////////////////////////////////
201
202bool GrDrawState::srcAlphaWillBeOne() const {
203    uint32_t validComponentFlags;
204    GrColor color;
205    // Check if per-vertex or constant color may have partial alpha
206    if (this->hasColorVertexAttribute()) {
207        validComponentFlags = 0;
208        color = 0; // not strictly necessary but we get false alarms from tools about uninit.
209    } else {
210        validComponentFlags = kRGBA_GrColorComponentFlags;
211        color = this->getColor();
212    }
213
214    // Run through the color stages
215    for (int s = 0; s < fColorStages.count(); ++s) {
216        const GrEffectRef* effect = fColorStages[s].getEffect();
217        (*effect)->getConstantColorComponents(&color, &validComponentFlags);
218    }
219
220    // Check whether coverage is treated as color. If so we run through the coverage computation.
221    if (this->isCoverageDrawing()) {
222        GrColor coverageColor = this->getCoverageColor();
223        GrColor oldColor = color;
224        color = 0;
225        for (int c = 0; c < 4; ++c) {
226            if (validComponentFlags & (1 << c)) {
227                U8CPU a = (oldColor >> (c * 8)) & 0xff;
228                U8CPU b = (coverageColor >> (c * 8)) & 0xff;
229                color |= (SkMulDiv255Round(a, b) << (c * 8));
230            }
231        }
232        for (int s = 0; s < fCoverageStages.count(); ++s) {
233            const GrEffectRef* effect = fCoverageStages[s].getEffect();
234            (*effect)->getConstantColorComponents(&color, &validComponentFlags);
235        }
236    }
237    return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
238}
239
240bool GrDrawState::hasSolidCoverage() const {
241    // If we're drawing coverage directly then coverage is effectively treated as color.
242    if (this->isCoverageDrawing()) {
243        return true;
244    }
245
246    GrColor coverage;
247    uint32_t validComponentFlags;
248    // Initialize to an unknown starting coverage if per-vertex coverage is specified.
249    if (this->hasCoverageVertexAttribute()) {
250        validComponentFlags = 0;
251    } else {
252        coverage = fCommon.fCoverage;
253        validComponentFlags = kRGBA_GrColorComponentFlags;
254    }
255
256    // Run through the coverage stages and see if the coverage will be all ones at the end.
257    for (int s = 0; s < fCoverageStages.count(); ++s) {
258        const GrEffectRef* effect = fCoverageStages[s].getEffect();
259        (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
260    }
261    return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
262}
263
264////////////////////////////////////////////////////////////////////////////////
265
266// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
267// others will blend incorrectly.
268bool GrDrawState::canTweakAlphaForCoverage() const {
269    /*
270     The fractional coverage is f.
271     The src and dst coeffs are Cs and Cd.
272     The dst and src colors are S and D.
273     We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
274     we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
275     term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
276     find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
277     Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
278     color by definition.
279     */
280    return kOne_GrBlendCoeff == fCommon.fDstBlend ||
281           kISA_GrBlendCoeff == fCommon.fDstBlend ||
282           kISC_GrBlendCoeff == fCommon.fDstBlend ||
283           this->isCoverageDrawing();
284}
285
286GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
287                                                     GrBlendCoeff* srcCoeff,
288                                                     GrBlendCoeff* dstCoeff) const {
289
290    GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
291    if (NULL == srcCoeff) {
292        srcCoeff = &bogusSrcCoeff;
293    }
294    *srcCoeff = this->getSrcBlendCoeff();
295
296    if (NULL == dstCoeff) {
297        dstCoeff = &bogusDstCoeff;
298    }
299    *dstCoeff = this->getDstBlendCoeff();
300
301    if (this->isColorWriteDisabled()) {
302        *srcCoeff = kZero_GrBlendCoeff;
303        *dstCoeff = kOne_GrBlendCoeff;
304    }
305
306    bool srcAIsOne = this->srcAlphaWillBeOne();
307    bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
308                         (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
309    bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
310                         (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
311
312    bool covIsZero = !this->isCoverageDrawing() &&
313                     !this->hasCoverageVertexAttribute() &&
314                     0 == this->getCoverageColor();
315    // When coeffs are (0,1) there is no reason to draw at all, unless
316    // stenciling is enabled. Having color writes disabled is effectively
317    // (0,1). The same applies when coverage is known to be 0.
318    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
319        if (this->getStencil().doesWrite()) {
320            return kDisableBlend_BlendOptFlag |
321                   kEmitCoverage_BlendOptFlag;
322        } else {
323            return kSkipDraw_BlendOptFlag;
324        }
325    }
326
327    // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
328    bool hasCoverage = forceCoverage ||
329                       0xffffffff != this->getCoverageColor() ||
330                       this->hasCoverageVertexAttribute() ||
331                       fCoverageStages.count() > 0;
332
333    // if we don't have coverage we can check whether the dst
334    // has to read at all. If not, we'll disable blending.
335    if (!hasCoverage) {
336        if (dstCoeffIsZero) {
337            if (kOne_GrBlendCoeff == *srcCoeff) {
338                // if there is no coverage and coeffs are (1,0) then we
339                // won't need to read the dst at all, it gets replaced by src
340                return kDisableBlend_BlendOptFlag;
341            } else if (kZero_GrBlendCoeff == *srcCoeff) {
342                // if the op is "clear" then we don't need to emit a color
343                // or blend, just write transparent black into the dst.
344                *srcCoeff = kOne_GrBlendCoeff;
345                *dstCoeff = kZero_GrBlendCoeff;
346                return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
347            }
348        }
349    } else if (this->isCoverageDrawing()) {
350        // we have coverage but we aren't distinguishing it from alpha by request.
351        return kCoverageAsAlpha_BlendOptFlag;
352    } else {
353        // check whether coverage can be safely rolled into alpha
354        // of if we can skip color computation and just emit coverage
355        if (this->canTweakAlphaForCoverage()) {
356            return kCoverageAsAlpha_BlendOptFlag;
357        }
358        if (dstCoeffIsZero) {
359            if (kZero_GrBlendCoeff == *srcCoeff) {
360                // the source color is not included in the blend
361                // the dst coeff is effectively zero so blend works out to:
362                // (c)(0)D + (1-c)D = (1-c)D.
363                *dstCoeff = kISA_GrBlendCoeff;
364                return  kEmitCoverage_BlendOptFlag;
365            } else if (srcAIsOne) {
366                // the dst coeff is effectively zero so blend works out to:
367                // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
368                // If Sa is 1 then we can replace Sa with c
369                // and set dst coeff to 1-Sa.
370                *dstCoeff = kISA_GrBlendCoeff;
371                return  kCoverageAsAlpha_BlendOptFlag;
372            }
373        } else if (dstCoeffIsOne) {
374            // the dst coeff is effectively one so blend works out to:
375            // cS + (c)(1)D + (1-c)D = cS + D.
376            *dstCoeff = kOne_GrBlendCoeff;
377            return  kCoverageAsAlpha_BlendOptFlag;
378        }
379    }
380    if (kOne_GrBlendCoeff == *srcCoeff &&
381        kZero_GrBlendCoeff == *dstCoeff &&
382        this->willEffectReadDstColor()) {
383        // In this case the shader will fully resolve the color, coverage, and dst and we don't
384        // need blending.
385        return kDisableBlend_BlendOptFlag;
386    }
387    return kNone_BlendOpt;
388}
389
390////////////////////////////////////////////////////////////////////////////////
391
392void GrDrawState::AutoViewMatrixRestore::restore() {
393    if (NULL != fDrawState) {
394        SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
395        fDrawState->fCommon.fViewMatrix = fViewMatrix;
396        SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
397        int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
398        SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
399
400        int i = 0;
401        for (int s = 0; s < fNumColorStages; ++s, ++i) {
402            fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
403        }
404        for (int s = 0; s < numCoverageStages; ++s, ++i) {
405            fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
406        }
407        fDrawState = NULL;
408    }
409}
410
411void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
412                                             const SkMatrix& preconcatMatrix) {
413    this->restore();
414
415    SkASSERT(NULL == fDrawState);
416    if (NULL == drawState || preconcatMatrix.isIdentity()) {
417        return;
418    }
419    fDrawState = drawState;
420
421    fViewMatrix = drawState->getViewMatrix();
422    drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
423
424    this->doEffectCoordChanges(preconcatMatrix);
425    SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
426}
427
428bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
429    this->restore();
430
431    if (NULL == drawState) {
432        return false;
433    }
434
435    if (drawState->getViewMatrix().isIdentity()) {
436        return true;
437    }
438
439    fViewMatrix = drawState->getViewMatrix();
440    if (0 == drawState->numTotalStages()) {
441        drawState->fCommon.fViewMatrix.reset();
442        fDrawState = drawState;
443        fNumColorStages = 0;
444        fSavedCoordChanges.reset(0);
445        SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
446        return true;
447    } else {
448        SkMatrix inv;
449        if (!fViewMatrix.invert(&inv)) {
450            return false;
451        }
452        drawState->fCommon.fViewMatrix.reset();
453        fDrawState = drawState;
454        this->doEffectCoordChanges(inv);
455        SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
456        return true;
457    }
458}
459
460void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
461    fSavedCoordChanges.reset(fDrawState->numTotalStages());
462    int i = 0;
463
464    fNumColorStages = fDrawState->numColorStages();
465    for (int s = 0; s < fNumColorStages; ++s, ++i) {
466        fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
467        fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
468    }
469
470    int numCoverageStages = fDrawState->numCoverageStages();
471    for (int s = 0; s < numCoverageStages; ++s, ++i) {
472        fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
473        fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
474    }
475}
476