GrDrawTarget.cpp revision f13f58804659175925042a291304d483a4fd9278
1
2/*
3 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10
11#include "GrDrawTarget.h"
12#include "GrGpuVertex.h"
13#include "GrIndexBuffer.h"
14#include "GrRenderTarget.h"
15#include "GrTexture.h"
16#include "GrVertexBuffer.h"
17
18namespace {
19
20/**
21 * This function generates some masks that we like to have known at compile
22 * time. When the number of stages or tex coords is bumped or the way bits
23 * are defined in GrDrawTarget.h changes this function should be rerun to
24 * generate the new masks. (We attempted to force the compiler to generate the
25 * masks using recursive templates but always wound up with static initializers
26 * under gcc, even if they were just a series of immediate->memory moves.)
27 *
28 */
29void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
30                     GrVertexLayout* stageMasks,
31                     GrVertexLayout* texCoordMasks) {
32    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
33        stageTexCoordMasks[s] = 0;
34        for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
35            stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
36        }
37        stageMasks[s] = stageTexCoordMasks[s];
38    }
39    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
40        texCoordMasks[t] = 0;
41        for (int s = 0; s < GrDrawState::kNumStages; ++s) {
42            texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
43        }
44    }
45}
46
47/**
48 * Run this function to generate the code that declares the global masks.
49 */
50void gen_globals() {
51    GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
52    GrVertexLayout stageMasks[GrDrawState::kNumStages];
53    GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
54    gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
55
56    GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
57    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
58        GrPrintf("    0x%x,\n", stageTexCoordMasks[s]);
59    }
60    GrPrintf("};\n");
61    GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
62    GrPrintf("const GrVertexLayout gStageMasks[] = {\n");
63    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
64        GrPrintf("    0x%x,\n", stageMasks[s]);
65    }
66    GrPrintf("};\n");
67    GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));\n\n");
68    GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
69    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
70        GrPrintf("    0x%x,\n", texCoordMasks[t]);
71    }
72    GrPrintf("};\n");
73    GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
74}
75
76/* These values were generated by the above function */
77const GrVertexLayout gStageTexCoordMasks[] = {
78    0x1111,
79    0x2222,
80    0x4444,
81    0x8888,
82};
83GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
84
85const GrVertexLayout gStageMasks[] = {
86    0x1111,
87    0x2222,
88    0x4444,
89    0x8888,
90};
91GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));
92
93const GrVertexLayout gTexCoordMasks[] = {
94    0xf,
95    0xf0,
96    0xf00,
97    0xf000,
98};
99GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
100
101
102
103bool check_layout(GrVertexLayout layout) {
104    // can only have 1 or 0 bits set for each stage.
105    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
106        int stageBits = layout & gStageMasks[s];
107        if (stageBits && !GrIsPow2(stageBits)) {
108            return false;
109        }
110    }
111    return true;
112}
113
114int num_tex_coords(GrVertexLayout layout) {
115    int cnt = 0;
116    // figure out how many tex coordinates are present
117    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
118        if (gTexCoordMasks[t] & layout) {
119            ++cnt;
120        }
121    }
122    return cnt;
123}
124
125} //unnamed namespace
126
127size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
128    GrAssert(check_layout(vertexLayout));
129
130    size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
131                        sizeof(GrGpuTextVertex) :
132                        sizeof(GrPoint);
133
134    size_t size = vecSize; // position
135    size += num_tex_coords(vertexLayout) * vecSize;
136    if (vertexLayout & kColor_VertexLayoutBit) {
137        size += sizeof(GrColor);
138    }
139    if (vertexLayout & kCoverage_VertexLayoutBit) {
140        size += sizeof(GrColor);
141    }
142    if (vertexLayout & kEdge_VertexLayoutBit) {
143        size += 4 * sizeof(GrScalar);
144    }
145    return size;
146}
147
148////////////////////////////////////////////////////////////////////////////////
149
150/**
151 * Functions for computing offsets of various components from the layout
152 * bitfield.
153 *
154 * Order of vertex components:
155 * Position
156 * Tex Coord 0
157 * ...
158 * Tex Coord GrDrawState::kMaxTexCoords-1
159 * Color
160 * Coverage
161 */
162
163int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
164    GrAssert(check_layout(vertexLayout));
165
166    if (!StageUsesTexCoords(vertexLayout, stage)) {
167        return 0;
168    }
169    int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
170    if (tcIdx >= 0) {
171
172        int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
173                                    sizeof(GrGpuTextVertex) :
174                                    sizeof(GrPoint);
175        int offset = vecSize; // position
176        // figure out how many tex coordinates are present and precede this one.
177        for (int t = 0; t < tcIdx; ++t) {
178            if (gTexCoordMasks[t] & vertexLayout) {
179                offset += vecSize;
180            }
181        }
182        return offset;
183    }
184
185    return -1;
186}
187
188int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
189    GrAssert(check_layout(vertexLayout));
190
191    if (vertexLayout & kColor_VertexLayoutBit) {
192        int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
193                                    sizeof(GrGpuTextVertex) :
194                                    sizeof(GrPoint);
195        return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
196    }
197    return -1;
198}
199
200int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
201    GrAssert(check_layout(vertexLayout));
202
203    if (vertexLayout & kCoverage_VertexLayoutBit) {
204        int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
205                                    sizeof(GrGpuTextVertex) :
206                                    sizeof(GrPoint);
207
208        int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
209        if (vertexLayout & kColor_VertexLayoutBit) {
210            offset += sizeof(GrColor);
211        }
212        return offset;
213    }
214    return -1;
215}
216
217int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
218    GrAssert(check_layout(vertexLayout));
219
220    // edge pts are after the pos, tex coords, and color
221    if (vertexLayout & kEdge_VertexLayoutBit) {
222        int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
223                                    sizeof(GrGpuTextVertex) :
224                                    sizeof(GrPoint);
225        int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
226        if (vertexLayout & kColor_VertexLayoutBit) {
227            offset += sizeof(GrColor);
228        }
229        if (vertexLayout & kCoverage_VertexLayoutBit) {
230            offset += sizeof(GrColor);
231        }
232        return offset;
233    }
234    return -1;
235}
236
237int GrDrawTarget::VertexSizeAndOffsetsByIdx(
238        GrVertexLayout vertexLayout,
239        int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
240        int* colorOffset,
241        int* coverageOffset,
242        int* edgeOffset) {
243    GrAssert(check_layout(vertexLayout));
244
245    int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
246                                                    sizeof(GrGpuTextVertex) :
247                                                    sizeof(GrPoint);
248    int size = vecSize; // position
249
250    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
251        if (gTexCoordMasks[t] & vertexLayout) {
252            if (NULL != texCoordOffsetsByIdx) {
253                texCoordOffsetsByIdx[t] = size;
254            }
255            size += vecSize;
256        } else {
257            if (NULL != texCoordOffsetsByIdx) {
258                texCoordOffsetsByIdx[t] = -1;
259            }
260        }
261    }
262    if (kColor_VertexLayoutBit & vertexLayout) {
263        if (NULL != colorOffset) {
264            *colorOffset = size;
265        }
266        size += sizeof(GrColor);
267    } else {
268        if (NULL != colorOffset) {
269            *colorOffset = -1;
270        }
271    }
272    if (kCoverage_VertexLayoutBit & vertexLayout) {
273        if (NULL != coverageOffset) {
274            *coverageOffset = size;
275        }
276        size += sizeof(GrColor);
277    } else {
278        if (NULL != coverageOffset) {
279            *coverageOffset = -1;
280        }
281    }
282    if (kEdge_VertexLayoutBit & vertexLayout) {
283        if (NULL != edgeOffset) {
284            *edgeOffset = size;
285        }
286        size += 4 * sizeof(GrScalar);
287    } else {
288        if (NULL != edgeOffset) {
289            *edgeOffset = -1;
290        }
291    }
292    return size;
293}
294
295int GrDrawTarget::VertexSizeAndOffsetsByStage(
296        GrVertexLayout vertexLayout,
297        int texCoordOffsetsByStage[GrDrawState::kNumStages],
298        int* colorOffset,
299        int* coverageOffset,
300        int* edgeOffset) {
301    GrAssert(check_layout(vertexLayout));
302
303    int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
304    int size = VertexSizeAndOffsetsByIdx(vertexLayout,
305                                         (NULL == texCoordOffsetsByStage) ?
306                                               NULL :
307                                               texCoordOffsetsByIdx,
308                                         colorOffset,
309                                         coverageOffset,
310                                         edgeOffset);
311    if (NULL != texCoordOffsetsByStage) {
312        for (int s = 0; s < GrDrawState::kNumStages; ++s) {
313            int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
314            texCoordOffsetsByStage[s] =
315                tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
316        }
317    }
318    return size;
319}
320
321////////////////////////////////////////////////////////////////////////////////
322
323bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
324                                         GrVertexLayout vertexLayout) {
325    GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
326    GrAssert(check_layout(vertexLayout));
327    return !!(gTexCoordMasks[coordIndex] & vertexLayout);
328}
329
330int GrDrawTarget::VertexTexCoordsForStage(int stage,
331                                          GrVertexLayout vertexLayout) {
332    GrAssert(stage < GrDrawState::kNumStages);
333    GrAssert(check_layout(vertexLayout));
334    int bit = vertexLayout & gStageTexCoordMasks[stage];
335    if (bit) {
336        // figure out which set of texture coordates is used
337        // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
338        // and start at bit 0.
339        GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
340        return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
341    }
342    return -1;
343}
344
345////////////////////////////////////////////////////////////////////////////////
346
347void GrDrawTarget::VertexLayoutUnitTest() {
348    // Ensure that our globals mask arrays are correct
349    GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
350    GrVertexLayout stageMasks[GrDrawState::kNumStages];
351    GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
352    gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
353    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
354        GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
355        GrAssert(stageMasks[s] == gStageMasks[s]);
356    }
357    for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
358        GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
359    }
360
361    // not necessarily exhaustive
362    static bool run;
363    if (!run) {
364        run = true;
365        for (int s = 0; s < GrDrawState::kNumStages; ++s) {
366
367            GrVertexLayout stageMask = 0;
368            for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
369                stageMask |= StageTexCoordVertexLayoutBit(s,t);
370            }
371            GrAssert(1 == GrDrawState::kMaxTexCoords ||
372                     !check_layout(stageMask));
373            GrAssert(gStageTexCoordMasks[s] == stageMask);
374            GrAssert(!check_layout(stageMask));
375        }
376        for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
377            GrVertexLayout tcMask = 0;
378            GrAssert(!VertexUsesTexCoordIdx(t, 0));
379            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
380                tcMask |= StageTexCoordVertexLayoutBit(s,t);
381                GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
382                GrAssert(VertexUsesTexCoordIdx(t, tcMask));
383                GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
384                GrAssert(t == VertexTexCoordsForStage(s, tcMask));
385                for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
386                    GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
387
388                #if GR_DEBUG
389                    GrVertexLayout posAsTex = tcMask;
390                #endif
391                    GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
392                    GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
393                    GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
394                    GrAssert(-1 == VertexEdgeOffset(posAsTex));
395                }
396                GrAssert(-1 == VertexEdgeOffset(tcMask));
397                GrAssert(-1 == VertexColorOffset(tcMask));
398                GrAssert(-1 == VertexCoverageOffset(tcMask));
399            #if GR_DEBUG
400                GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
401            #endif
402                GrAssert(-1 == VertexCoverageOffset(withColor));
403                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
404                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
405            #if GR_DEBUG
406                GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
407            #endif
408                GrAssert(-1 == VertexColorOffset(withEdge));
409                GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
410                GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
411            #if GR_DEBUG
412                GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
413            #endif
414                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
415                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
416                GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
417            #if GR_DEBUG
418                GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
419            #endif
420                GrAssert(-1 == VertexColorOffset(withCoverage));
421                GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
422                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
423            #if GR_DEBUG
424                GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
425                                                      kColor_VertexLayoutBit;
426            #endif
427                GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
428                GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
429                GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
430            }
431            GrAssert(gTexCoordMasks[t] == tcMask);
432            GrAssert(check_layout(tcMask));
433
434            int stageOffsets[GrDrawState::kNumStages];
435            int colorOffset;
436            int edgeOffset;
437            int coverageOffset;
438            int size;
439            size = VertexSizeAndOffsetsByStage(tcMask,
440                                               stageOffsets, &colorOffset,
441                                               &coverageOffset, &edgeOffset);
442            GrAssert(2*sizeof(GrPoint) == size);
443            GrAssert(-1 == colorOffset);
444            GrAssert(-1 == coverageOffset);
445            GrAssert(-1 == edgeOffset);
446            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
447                GrAssert(sizeof(GrPoint) == stageOffsets[s]);
448                GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
449            }
450        }
451    }
452}
453
454////////////////////////////////////////////////////////////////////////////////
455
456#define DEBUG_INVAL_BUFFER 0xdeadcafe
457#define DEBUG_INVAL_START_IDX -1
458
459GrDrawTarget::GrDrawTarget() {
460#if GR_DEBUG
461    VertexLayoutUnitTest();
462#endif
463    fDrawState = &fDefaultDrawState;
464    // We assume that fDrawState always owns a ref to the object it points at.
465    fDefaultDrawState.ref();
466    GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
467#if GR_DEBUG
468    geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
469    geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
470    geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
471    geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
472#endif
473    geoSrc.fVertexSrc = kNone_GeometrySrcType;
474    geoSrc.fIndexSrc  = kNone_GeometrySrcType;
475}
476
477GrDrawTarget::~GrDrawTarget() {
478    GrAssert(1 == fGeoSrcStateStack.count());
479    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
480    GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
481    GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
482    fDrawState->unref();
483}
484
485void GrDrawTarget::releaseGeometry() {
486    int popCnt = fGeoSrcStateStack.count() - 1;
487    while (popCnt) {
488        this->popGeometrySource();
489        --popCnt;
490    }
491    this->resetVertexSource();
492    this->resetIndexSource();
493}
494
495void GrDrawTarget::setClip(const GrClip& clip) {
496    clipWillBeSet(clip);
497    fClip = clip;
498}
499
500const GrClip& GrDrawTarget::getClip() const {
501    return fClip;
502}
503
504void GrDrawTarget::setDrawState(GrDrawState*  drawState) {
505    GrAssert(NULL != fDrawState);
506    if (NULL == drawState) {
507        drawState = &fDefaultDrawState;
508    }
509    if (fDrawState != drawState) {
510        fDrawState->unref();
511        drawState->ref();
512        fDrawState = drawState;
513    }
514}
515
516bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
517                                      int vertexCount,
518                                      void** vertices) {
519    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
520    bool acquired = false;
521    if (vertexCount > 0) {
522        GrAssert(NULL != vertices);
523        this->releasePreviousVertexSource();
524        geoSrc.fVertexSrc = kNone_GeometrySrcType;
525
526        acquired = this->onReserveVertexSpace(vertexLayout,
527                                              vertexCount,
528                                              vertices);
529    }
530    if (acquired) {
531        geoSrc.fVertexSrc = kReserved_GeometrySrcType;
532        geoSrc.fVertexCount = vertexCount;
533        geoSrc.fVertexLayout = vertexLayout;
534    } else if (NULL != vertices) {
535        *vertices = NULL;
536    }
537    return acquired;
538}
539
540bool GrDrawTarget::reserveIndexSpace(int indexCount,
541                                     void** indices) {
542    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
543    bool acquired = false;
544    if (indexCount > 0) {
545        GrAssert(NULL != indices);
546        this->releasePreviousIndexSource();
547        geoSrc.fIndexSrc = kNone_GeometrySrcType;
548
549        acquired = this->onReserveIndexSpace(indexCount, indices);
550    }
551    if (acquired) {
552        geoSrc.fIndexSrc = kReserved_GeometrySrcType;
553        geoSrc.fIndexCount = indexCount;
554    } else if (NULL != indices) {
555        *indices = NULL;
556    }
557    return acquired;
558
559}
560
561bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stage) {
562    return layout & gStageTexCoordMasks[stage];
563}
564
565bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
566                                              int vertexCount,
567                                              int indexCount,
568                                              void** vertices,
569                                              void** indices) {
570    this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
571    if (vertexCount) {
572        if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
573            if (indexCount) {
574                this->resetIndexSource();
575            }
576            return false;
577        }
578    }
579    if (indexCount) {
580        if (!this->reserveIndexSpace(indexCount, indices)) {
581            if (vertexCount) {
582                this->resetVertexSource();
583            }
584            return false;
585        }
586    }
587    return true;
588}
589
590bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
591                                 int32_t* vertexCount,
592                                 int32_t* indexCount) const {
593    if (NULL != vertexCount) {
594        *vertexCount = -1;
595    }
596    if (NULL != indexCount) {
597        *indexCount = -1;
598    }
599    return false;
600}
601
602void GrDrawTarget::releasePreviousVertexSource() {
603    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
604    switch (geoSrc.fVertexSrc) {
605        case kNone_GeometrySrcType:
606            break;
607        case kArray_GeometrySrcType:
608            this->releaseVertexArray();
609            break;
610        case kReserved_GeometrySrcType:
611            this->releaseReservedVertexSpace();
612            break;
613        case kBuffer_GeometrySrcType:
614            geoSrc.fVertexBuffer->unref();
615#if GR_DEBUG
616            geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
617#endif
618            break;
619        default:
620            GrCrash("Unknown Vertex Source Type.");
621            break;
622    }
623}
624
625void GrDrawTarget::releasePreviousIndexSource() {
626    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
627    switch (geoSrc.fIndexSrc) {
628        case kNone_GeometrySrcType:   // these two don't require
629            break;
630        case kArray_GeometrySrcType:
631            this->releaseIndexArray();
632            break;
633        case kReserved_GeometrySrcType:
634            this->releaseReservedIndexSpace();
635            break;
636        case kBuffer_GeometrySrcType:
637            geoSrc.fIndexBuffer->unref();
638#if GR_DEBUG
639            geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
640#endif
641            break;
642        default:
643            GrCrash("Unknown Index Source Type.");
644            break;
645    }
646}
647
648void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
649                                          const void* vertexArray,
650                                          int vertexCount) {
651    this->releasePreviousVertexSource();
652    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
653    geoSrc.fVertexSrc = kArray_GeometrySrcType;
654    geoSrc.fVertexLayout = vertexLayout;
655    geoSrc.fVertexCount = vertexCount;
656    this->onSetVertexSourceToArray(vertexArray, vertexCount);
657}
658
659void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
660                                         int indexCount) {
661    this->releasePreviousIndexSource();
662    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
663    geoSrc.fIndexSrc = kArray_GeometrySrcType;
664    geoSrc.fIndexCount = indexCount;
665    this->onSetIndexSourceToArray(indexArray, indexCount);
666}
667
668void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
669                                           const GrVertexBuffer* buffer) {
670    this->releasePreviousVertexSource();
671    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
672    geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
673    geoSrc.fVertexBuffer = buffer;
674    buffer->ref();
675    geoSrc.fVertexLayout = vertexLayout;
676}
677
678void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
679    this->releasePreviousIndexSource();
680    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
681    geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
682    geoSrc.fIndexBuffer  = buffer;
683    buffer->ref();
684}
685
686void GrDrawTarget::resetVertexSource() {
687    this->releasePreviousVertexSource();
688    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
689    geoSrc.fVertexSrc = kNone_GeometrySrcType;
690}
691
692void GrDrawTarget::resetIndexSource() {
693    this->releasePreviousIndexSource();
694    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
695    geoSrc.fIndexSrc = kNone_GeometrySrcType;
696}
697
698void GrDrawTarget::pushGeometrySource() {
699    this->geometrySourceWillPush();
700    GeometrySrcState& newState = fGeoSrcStateStack.push_back();
701    newState.fIndexSrc = kNone_GeometrySrcType;
702    newState.fVertexSrc = kNone_GeometrySrcType;
703#if GR_DEBUG
704    newState.fVertexCount  = ~0;
705    newState.fVertexBuffer = (GrVertexBuffer*)~0;
706    newState.fIndexCount   = ~0;
707    newState.fIndexBuffer = (GrIndexBuffer*)~0;
708#endif
709}
710
711void GrDrawTarget::popGeometrySource() {
712    // if popping last element then pops are unbalanced with pushes
713    GrAssert(fGeoSrcStateStack.count() > 1);
714
715    this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
716    this->releasePreviousVertexSource();
717    this->releasePreviousIndexSource();
718    fGeoSrcStateStack.pop_back();
719}
720
721////////////////////////////////////////////////////////////////////////////////
722
723bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
724                             int startIndex, int vertexCount,
725                             int indexCount) const {
726#if GR_DEBUG
727    const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
728    int maxVertex = startVertex + vertexCount;
729    int maxValidVertex;
730    switch (geoSrc.fVertexSrc) {
731        case kNone_GeometrySrcType:
732            GrCrash("Attempting to draw without vertex src.");
733        case kReserved_GeometrySrcType: // fallthrough
734        case kArray_GeometrySrcType:
735            maxValidVertex = geoSrc.fVertexCount;
736            break;
737        case kBuffer_GeometrySrcType:
738            maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
739                             VertexSize(geoSrc.fVertexLayout);
740            break;
741    }
742    if (maxVertex > maxValidVertex) {
743        GrCrash("Drawing outside valid vertex range.");
744    }
745    if (indexCount > 0) {
746        int maxIndex = startIndex + indexCount;
747        int maxValidIndex;
748        switch (geoSrc.fIndexSrc) {
749            case kNone_GeometrySrcType:
750                GrCrash("Attempting to draw indexed geom without index src.");
751            case kReserved_GeometrySrcType: // fallthrough
752            case kArray_GeometrySrcType:
753                maxValidIndex = geoSrc.fIndexCount;
754                break;
755            case kBuffer_GeometrySrcType:
756                maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
757                break;
758        }
759        if (maxIndex > maxValidIndex) {
760            GrCrash("Index reads outside valid index range.");
761        }
762    }
763
764    GrAssert(NULL != this->getDrawState().getRenderTarget());
765    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
766        if (this->getDrawState().getTexture(i)) {
767            GrAssert(this->getDrawState().getTexture(i)->asRenderTarget() !=
768                     this->getDrawState().getRenderTarget());
769        }
770    }
771#endif
772    const GrDrawState& drawState = this->getDrawState();
773    if (NULL == drawState.getRenderTarget()) {
774        return false;
775    }
776    if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
777        if (kOne_GrBlendCoeff != drawState.getSrcBlendCoeff() ||
778            kZero_GrBlendCoeff != drawState.getDstBlendCoeff()) {
779            return false;
780        }
781    }
782    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
783        // We don't support using unpremultiplied textures with filters (other
784        // than nearest). Alpha-premulling is not distributive WRT to filtering.
785        // We'd have to filter each texel before filtering. We could do this for
786        // our custom filters but we would also have to disable bilerp and do
787        // a custom bilerp in the shader. Until Skia itself supports unpremul
788        // configs there is no pressure to implement this.
789        if (this->isStageEnabled(s) &&
790            GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
791            GrSamplerState::kNearest_Filter !=
792            drawState.getSampler(s).getFilter()) {
793            return false;
794        }
795    }
796    return true;
797}
798
799void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
800                               int startIndex, int vertexCount,
801                               int indexCount) {
802    if (indexCount > 0 &&
803        this->checkDraw(type, startVertex, startIndex,
804                        vertexCount, indexCount)) {
805        this->onDrawIndexed(type, startVertex, startIndex,
806                            vertexCount, indexCount);
807    }
808}
809
810void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
811                                  int startVertex,
812                                  int vertexCount) {
813    if (vertexCount > 0 &&
814        this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
815        this->onDrawNonIndexed(type, startVertex, vertexCount);
816    }
817}
818
819void GrDrawTarget::stencilPath(const GrPath& path, GrPathFill fill) {
820    // TODO: extract portions of checkDraw that are relevant to path stenciling.
821    GrAssert(fCaps.fPathStencilingSupport);
822    GrAssert(kHairLine_GrPathFill != fill);
823    GrAssert(!GrIsFillInverted(fill));
824    this->onStencilPath(path, fill);
825}
826
827////////////////////////////////////////////////////////////////////////////////
828
829// Some blend modes allow folding a partial coverage value into the color's
830// alpha channel, while others will blend incorrectly.
831bool GrDrawTarget::canTweakAlphaForCoverage() const {
832    /**
833     * The fractional coverage is f
834     * The src and dst coeffs are Cs and Cd
835     * The dst and src colors are S and D
836     * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
837     * By tweaking the source color's alpha we're replacing S with S'=fS. It's
838     * obvious that that first term will always be ok. The second term can be
839     * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
840     * for Cd we find that only 1, ISA, and ISC produce the correct depth
841     * coeffecient in terms of S' and D.
842     */
843    GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
844    return kOne_GrBlendCoeff == dstCoeff ||
845           kISA_GrBlendCoeff == dstCoeff ||
846           kISC_GrBlendCoeff == dstCoeff;
847}
848
849bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
850    const GrDrawState& drawState = this->getDrawState();
851
852    // Check if per-vertex or constant color may have partial alpha
853    if ((layout & kColor_VertexLayoutBit) ||
854        0xff != GrColorUnpackA(drawState.getColor())) {
855        return false;
856    }
857    // Check if color filter could introduce an alpha
858    // (TODO: Consider being more aggressive with regards to detecting 0xff
859    // final alpha from color filter).
860    if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
861        return false;
862    }
863    // Check if a color stage could create a partial alpha
864    for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
865        if (this->isStageEnabled(s)) {
866            GrAssert(NULL != drawState.getTexture(s));
867            GrPixelConfig config = drawState.getTexture(s)->config();
868            if (!GrPixelConfigIsOpaque(config)) {
869                return false;
870            }
871        }
872    }
873    return true;
874}
875
876namespace {
877GrVertexLayout default_blend_opts_vertex_layout() {
878    GrVertexLayout layout = 0;
879    return layout;
880}
881}
882
883GrDrawTarget::BlendOptFlags
884GrDrawTarget::getBlendOpts(bool forceCoverage,
885                           GrBlendCoeff* srcCoeff,
886                           GrBlendCoeff* dstCoeff) const {
887
888    GrVertexLayout layout;
889    if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
890        layout = default_blend_opts_vertex_layout();
891    } else {
892        layout = this->getVertexLayout();
893    }
894
895    const GrDrawState& drawState = this->getDrawState();
896
897    GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
898    if (NULL == srcCoeff) {
899        srcCoeff = &bogusSrcCoeff;
900    }
901    *srcCoeff = drawState.getSrcBlendCoeff();
902
903    if (NULL == dstCoeff) {
904        dstCoeff = &bogusDstCoeff;
905    }
906    *dstCoeff = drawState.getDstBlendCoeff();
907
908    // We don't ever expect source coeffecients to reference the source
909    GrAssert(kSA_GrBlendCoeff != *srcCoeff &&
910             kISA_GrBlendCoeff != *srcCoeff &&
911             kSC_GrBlendCoeff != *srcCoeff &&
912             kISC_GrBlendCoeff != *srcCoeff);
913    // same for dst
914    GrAssert(kDA_GrBlendCoeff != *dstCoeff &&
915             kIDA_GrBlendCoeff != *dstCoeff &&
916             kDC_GrBlendCoeff != *dstCoeff &&
917             kIDC_GrBlendCoeff != *dstCoeff);
918
919    if (drawState.isColorWriteDisabled()) {
920        *srcCoeff = kZero_GrBlendCoeff;
921        *dstCoeff = kOne_GrBlendCoeff;
922    }
923
924    bool srcAIsOne = this->srcAlphaWillBeOne(layout);
925    bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
926                         (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
927    bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
928                         (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
929
930
931    // When coeffs are (0,1) there is no reason to draw at all, unless
932    // stenciling is enabled. Having color writes disabled is effectively
933    // (0,1). The same applies when coverage is known to be 0.
934    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) ||
935        (!(layout & kCoverage_VertexLayoutBit) &&
936         0 == drawState.getCoverage())) {
937        if (drawState.getStencil().doesWrite()) {
938            return kDisableBlend_BlendOptFlag |
939                   kEmitTransBlack_BlendOptFlag;
940        } else {
941            return kSkipDraw_BlendOptFlag;
942        }
943    }
944
945    // check for coverage due to constant coverage, per-vertex coverage,
946    // edge aa or coverage texture stage
947    bool hasCoverage = forceCoverage ||
948                       0xffffffff != drawState.getCoverage() ||
949                       (layout & kCoverage_VertexLayoutBit) ||
950                       (layout & kEdge_VertexLayoutBit);
951    for (int s = drawState.getFirstCoverageStage();
952         !hasCoverage && s < GrDrawState::kNumStages;
953         ++s) {
954        if (this->isStageEnabled(s)) {
955            hasCoverage = true;
956        }
957    }
958
959    // if we don't have coverage we can check whether the dst
960    // has to read at all. If not, we'll disable blending.
961    if (!hasCoverage) {
962        if (dstCoeffIsZero) {
963            if (kOne_GrBlendCoeff == *srcCoeff) {
964                // if there is no coverage and coeffs are (1,0) then we
965                // won't need to read the dst at all, it gets replaced by src
966                return kDisableBlend_BlendOptFlag;
967            } else if (kZero_GrBlendCoeff == *srcCoeff) {
968                // if the op is "clear" then we don't need to emit a color
969                // or blend, just write transparent black into the dst.
970                *srcCoeff = kOne_GrBlendCoeff;
971                *dstCoeff = kZero_GrBlendCoeff;
972                return kDisableBlend_BlendOptFlag |
973                       kEmitTransBlack_BlendOptFlag;
974            }
975        }
976    } else {
977        // check whether coverage can be safely rolled into alpha
978        // of if we can skip color computation and just emit coverage
979        if (this->canTweakAlphaForCoverage()) {
980            return kCoverageAsAlpha_BlendOptFlag;
981        }
982        if (dstCoeffIsZero) {
983            if (kZero_GrBlendCoeff == *srcCoeff) {
984                // the source color is not included in the blend
985                // the dst coeff is effectively zero so blend works out to:
986                // (c)(0)D + (1-c)D = (1-c)D.
987                *dstCoeff = kISA_GrBlendCoeff;
988                return  kEmitCoverage_BlendOptFlag;
989            } else if (srcAIsOne) {
990                // the dst coeff is effectively zero so blend works out to:
991                // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
992                // If Sa is 1 then we can replace Sa with c
993                // and set dst coeff to 1-Sa.
994                *dstCoeff = kISA_GrBlendCoeff;
995                return  kCoverageAsAlpha_BlendOptFlag;
996            }
997        } else if (dstCoeffIsOne) {
998            // the dst coeff is effectively one so blend works out to:
999            // cS + (c)(1)D + (1-c)D = cS + D.
1000            *dstCoeff = kOne_GrBlendCoeff;
1001            return  kCoverageAsAlpha_BlendOptFlag;
1002        }
1003    }
1004    return kNone_BlendOpt;
1005}
1006
1007bool GrDrawTarget::willUseHWAALines() const {
1008    // there is a conflict between using smooth lines and our use of
1009    // premultiplied alpha. Smooth lines tweak the incoming alpha value
1010    // but not in a premul-alpha way. So we only use them when our alpha
1011    // is 0xff and tweaking the color for partial coverage is OK
1012    if (!fCaps.fHWAALineSupport ||
1013        !this->getDrawState().isHWAntialiasState()) {
1014        return false;
1015    }
1016    BlendOptFlags opts = this->getBlendOpts();
1017    return (kDisableBlend_BlendOptFlag & opts) &&
1018           (kCoverageAsAlpha_BlendOptFlag & opts);
1019}
1020
1021bool GrDrawTarget::canApplyCoverage() const {
1022    // we can correctly apply coverage if a) we have dual source blending
1023    // or b) one of our blend optimizations applies.
1024    return this->getCaps().fDualSourceBlendingSupport ||
1025           kNone_BlendOpt != this->getBlendOpts(true);
1026}
1027
1028////////////////////////////////////////////////////////////////////////////////
1029
1030void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1031                                        int instanceCount,
1032                                        int verticesPerInstance,
1033                                        int indicesPerInstance) {
1034    if (!verticesPerInstance || !indicesPerInstance) {
1035        return;
1036    }
1037
1038    int instancesPerDraw = this->indexCountInCurrentSource() /
1039                           indicesPerInstance;
1040    if (!instancesPerDraw) {
1041        return;
1042    }
1043
1044    instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1045    int startVertex = 0;
1046    while (instanceCount) {
1047        this->drawIndexed(type,
1048                          startVertex,
1049                          0,
1050                          verticesPerInstance * instancesPerDraw,
1051                          indicesPerInstance * instancesPerDraw);
1052        startVertex += verticesPerInstance;
1053        instanceCount -= instancesPerDraw;
1054    }
1055}
1056
1057////////////////////////////////////////////////////////////////////////////////
1058
1059void GrDrawTarget::drawRect(const GrRect& rect,
1060                            const GrMatrix* matrix,
1061                            StageMask stageMask,
1062                            const GrRect* srcRects[],
1063                            const GrMatrix* srcMatrices[]) {
1064    GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
1065
1066    AutoReleaseGeometry geo(this, layout, 4, 0);
1067    if (!geo.succeeded()) {
1068        GrPrintf("Failed to get space for vertices!\n");
1069        return;
1070    }
1071
1072    SetRectVertices(rect, matrix, srcRects,
1073                    srcMatrices, layout, geo.vertices());
1074
1075    drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
1076}
1077
1078GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
1079                                                 const GrRect* srcRects[]) {
1080    GrVertexLayout layout = 0;
1081
1082    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
1083        int numTC = 0;
1084        if (stageMask & (1 << i)) {
1085            if (NULL != srcRects && NULL != srcRects[i]) {
1086                layout |= StageTexCoordVertexLayoutBit(i, numTC);
1087                ++numTC;
1088            }
1089        }
1090    }
1091    return layout;
1092}
1093
1094void GrDrawTarget::SetRectVertices(const GrRect& rect,
1095                                   const GrMatrix* matrix,
1096                                   const GrRect* srcRects[],
1097                                   const GrMatrix* srcMatrices[],
1098                                   GrVertexLayout layout,
1099                                   void* vertices) {
1100#if GR_DEBUG
1101    // check that the layout and srcRects agree
1102    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
1103        if (VertexTexCoordsForStage(i, layout) >= 0) {
1104            GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1105        } else {
1106            GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1107        }
1108    }
1109#endif
1110
1111    int stageOffsets[GrDrawState::kNumStages];
1112    int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1113                                            NULL, NULL, NULL);
1114
1115    GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
1116                                            rect.fRight, rect.fBottom,
1117                                            vsize);
1118    if (NULL != matrix) {
1119        matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1120    }
1121
1122    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
1123        if (stageOffsets[i] > 0) {
1124            GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
1125                                                stageOffsets[i]);
1126            coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
1127                               srcRects[i]->fRight, srcRects[i]->fBottom,
1128                               vsize);
1129            if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1130                srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1131            }
1132        }
1133    }
1134}
1135
1136////////////////////////////////////////////////////////////////////////////////
1137
1138GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1139    fDrawTarget = NULL;
1140}
1141
1142GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1143                                                 ASRInit init) {
1144    fDrawTarget = NULL;
1145    this->set(target, init);
1146}
1147
1148GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
1149    if (NULL != fDrawTarget) {
1150        fDrawTarget->setDrawState(fSavedState);
1151        fSavedState->unref();
1152    }
1153}
1154
1155void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1156    GrAssert(NULL == fDrawTarget);
1157    fDrawTarget = target;
1158    fSavedState = target->drawState();
1159    GrAssert(fSavedState);
1160    fSavedState->ref();
1161    if (kReset_ASRInit == init) {
1162        // calls the default cons
1163        fTempState.init();
1164    } else {
1165        GrAssert(kPreserve_ASRInit == init);
1166        // calls the copy cons
1167        fTempState.set(*fSavedState);
1168    }
1169    target->setDrawState(fTempState.get());
1170}
1171
1172////////////////////////////////////////////////////////////////////////////////
1173
1174GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
1175                                            GrDrawTarget* target,
1176                                            GrDrawState::StageMask stageMask) {
1177    GrAssert(NULL != target);
1178    GrDrawState* drawState = target->drawState();
1179
1180    fDrawTarget = target;
1181    fViewMatrix = drawState->getViewMatrix();
1182    fStageMask = stageMask;
1183    if (fStageMask) {
1184        GrMatrix invVM;
1185        if (fViewMatrix.invert(&invVM)) {
1186            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
1187                if (fStageMask & (1 << s)) {
1188                    fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
1189                }
1190            }
1191            drawState->preConcatSamplerMatrices(fStageMask, invVM);
1192        } else {
1193            // sad trombone sound
1194            fStageMask = 0;
1195        }
1196    }
1197    drawState->viewMatrix()->reset();
1198}
1199
1200GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
1201    GrDrawState* drawState = fDrawTarget->drawState();
1202    drawState->setViewMatrix(fViewMatrix);
1203    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
1204        if (fStageMask & (1 << s)) {
1205            *drawState->sampler(s)->matrix() = fSamplerMatrices[s];
1206        }
1207    }
1208}
1209
1210////////////////////////////////////////////////////////////////////////////////
1211
1212GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1213                                         GrDrawTarget*  target,
1214                                         GrVertexLayout vertexLayout,
1215                                         int vertexCount,
1216                                         int indexCount) {
1217    fTarget = NULL;
1218    this->set(target, vertexLayout, vertexCount, indexCount);
1219}
1220
1221GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1222    fTarget = NULL;
1223}
1224
1225GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1226    this->reset();
1227}
1228
1229bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
1230                                            GrVertexLayout vertexLayout,
1231                                            int vertexCount,
1232                                            int indexCount) {
1233    this->reset();
1234    fTarget = target;
1235    bool success = true;
1236    if (NULL != fTarget) {
1237        fTarget = target;
1238        success = target->reserveVertexAndIndexSpace(vertexLayout,
1239                                                     vertexCount,
1240                                                     indexCount,
1241                                                     &fVertices,
1242                                                     &fIndices);
1243        if (!success) {
1244            fTarget = NULL;
1245            this->reset();
1246        }
1247    }
1248    GrAssert(success == (NULL != fTarget));
1249    return success;
1250}
1251
1252void GrDrawTarget::AutoReleaseGeometry::reset() {
1253    if (NULL != fTarget) {
1254        if (NULL != fVertices) {
1255            fTarget->resetVertexSource();
1256        }
1257        if (NULL != fIndices) {
1258            fTarget->resetIndexSource();
1259        }
1260        fTarget = NULL;
1261    }
1262    fVertices = NULL;
1263    fIndices = NULL;
1264}
1265
1266void GrDrawTarget::Caps::print() const {
1267    static const char* gNY[] = {"NO", "YES"};
1268    GrPrintf("8 Bit Palette Support       : %s\n", gNY[f8BitPaletteSupport]);
1269    GrPrintf("NPOT Texture Tile Support   : %s\n", gNY[fNPOTTextureTileSupport]);
1270    GrPrintf("Two Sided Stencil Support   : %s\n", gNY[fTwoSidedStencilSupport]);
1271    GrPrintf("Stencil Wrap Ops  Support   : %s\n", gNY[fStencilWrapOpsSupport]);
1272    GrPrintf("HW AA Lines Support         : %s\n", gNY[fHWAALineSupport]);
1273    GrPrintf("Shader Derivative Support   : %s\n", gNY[fShaderDerivativeSupport]);
1274    GrPrintf("Geometry Shader Support     : %s\n", gNY[fGeometryShaderSupport]);
1275    GrPrintf("FSAA Support                : %s\n", gNY[fFSAASupport]);
1276    GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1277    GrPrintf("Buffer Lock Support         : %s\n", gNY[fBufferLockSupport]);
1278    GrPrintf("Max Texture Size            : %d\n", fMaxTextureSize);
1279    GrPrintf("Max Render Target Size      : %d\n", fMaxRenderTargetSize);
1280}
1281
1282
1283