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