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