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