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