Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrDrawTarget.cpp
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 "GrContext.h"
13 #include "GrDrawTargetCaps.h"
14 #include "GrPath.h"
15 #include "GrRenderTarget.h"
16 #include "GrTexture.h"
17 #include "GrVertexBuffer.h"
18
19 #include "SkStrokeRec.h"
20
21 ////////////////////////////////////////////////////////////////////////////////
22
23 GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
24     fPrimitiveType  = di.fPrimitiveType;
25     fStartVertex    = di.fStartVertex;
26     fStartIndex     = di.fStartIndex;
27     fVertexCount    = di.fVertexCount;
28     fIndexCount     = di.fIndexCount;
29
30     fInstanceCount          = di.fInstanceCount;
31     fVerticesPerInstance    = di.fVerticesPerInstance;
32     fIndicesPerInstance     = di.fIndicesPerInstance;
33
34     if (NULL != di.fDevBounds) {
35         SkASSERT(di.fDevBounds == &di.fDevBoundsStorage);
36         fDevBoundsStorage = di.fDevBoundsStorage;
37         fDevBounds = &fDevBoundsStorage;
38     } else {
39         fDevBounds = NULL;
40     }
41
42     fDstCopy = di.fDstCopy;
43
44     return *this;
45 }
46
47 #ifdef SK_DEBUG
48 bool GrDrawTarget::DrawInfo::isInstanced() const {
49     if (fInstanceCount > 0) {
50         SkASSERT(0 == fIndexCount % fIndicesPerInstance);
51         SkASSERT(0 == fVertexCount % fVerticesPerInstance);
52         SkASSERT(fIndexCount / fIndicesPerInstance == fInstanceCount);
53         SkASSERT(fVertexCount / fVerticesPerInstance == fInstanceCount);
54         // there is no way to specify a non-zero start index to drawIndexedInstances().
55         SkASSERT(0 == fStartIndex);
56         return true;
57     } else {
58         SkASSERT(!fVerticesPerInstance);
59         SkASSERT(!fIndicesPerInstance);
60         return false;
61     }
62 }
63 #endif
64
65 void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
66     SkASSERT(this->isInstanced());
67     SkASSERT(instanceOffset + fInstanceCount >= 0);
68     fInstanceCount += instanceOffset;
69     fVertexCount = fVerticesPerInstance * fInstanceCount;
70     fIndexCount = fIndicesPerInstance * fInstanceCount;
71 }
72
73 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
74     fStartVertex += vertexOffset;
75     SkASSERT(fStartVertex >= 0);
76 }
77
78 void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
79     SkASSERT(this->isIndexed());
80     fStartIndex += indexOffset;
81     SkASSERT(fStartIndex >= 0);
82 }
83
84 ////////////////////////////////////////////////////////////////////////////////
85
86 #define DEBUG_INVAL_BUFFER 0xdeadcafe
87 #define DEBUG_INVAL_START_IDX -1
88
89 GrDrawTarget::GrDrawTarget(GrContext* context)
90     : fClip(NULL)
91     , fContext(context) {
92     SkASSERT(NULL != context);
93
94     fDrawState = &fDefaultDrawState;
95     // We assume that fDrawState always owns a ref to the object it points at.
96     fDefaultDrawState.ref();
97     GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
98 #ifdef SK_DEBUG
99     geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
100     geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
101     geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
102     geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
103 #endif
104     geoSrc.fVertexSrc = kNone_GeometrySrcType;
105     geoSrc.fIndexSrc  = kNone_GeometrySrcType;
106 }
107
108 GrDrawTarget::~GrDrawTarget() {
109     SkASSERT(1 == fGeoSrcStateStack.count());
110     SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
111     SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc);
112     SkASSERT(kNone_GeometrySrcType == geoSrc.fVertexSrc);
113     fDrawState->unref();
114 }
115
116 void GrDrawTarget::releaseGeometry() {
117     int popCnt = fGeoSrcStateStack.count() - 1;
118     while (popCnt) {
119         this->popGeometrySource();
120         --popCnt;
121     }
122     this->resetVertexSource();
123     this->resetIndexSource();
124 }
125
126 void GrDrawTarget::setClip(const GrClipData* clip) {
127     clipWillBeSet(clip);
128     fClip = clip;
129 }
130
131 const GrClipData* GrDrawTarget::getClip() const {
132     return fClip;
133 }
134
135 void GrDrawTarget::setDrawState(GrDrawState*  drawState) {
136     SkASSERT(NULL != fDrawState);
137     if (NULL == drawState) {
138         drawState = &fDefaultDrawState;
139     }
140     if (fDrawState != drawState) {
141         fDrawState->unref();
142         drawState->ref();
143         fDrawState = drawState;
144     }
145 }
146
147 bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
148                                       int vertexCount,
149                                       void** vertices) {
150     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
151     bool acquired = false;
152     if (vertexCount > 0) {
153         SkASSERT(NULL != vertices);
154         this->releasePreviousVertexSource();
155         geoSrc.fVertexSrc = kNone_GeometrySrcType;
156
157         acquired = this->onReserveVertexSpace(vertexSize,
158                                               vertexCount,
159                                               vertices);
160     }
161     if (acquired) {
162         geoSrc.fVertexSrc = kReserved_GeometrySrcType;
163         geoSrc.fVertexCount = vertexCount;
164         geoSrc.fVertexSize = vertexSize;
165     } else if (NULL != vertices) {
166         *vertices = NULL;
167     }
168     return acquired;
169 }
170
171 bool GrDrawTarget::reserveIndexSpace(int indexCount,
172                                      void** indices) {
173     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
174     bool acquired = false;
175     if (indexCount > 0) {
176         SkASSERT(NULL != indices);
177         this->releasePreviousIndexSource();
178         geoSrc.fIndexSrc = kNone_GeometrySrcType;
179
180         acquired = this->onReserveIndexSpace(indexCount, indices);
181     }
182     if (acquired) {
183         geoSrc.fIndexSrc = kReserved_GeometrySrcType;
184         geoSrc.fIndexCount = indexCount;
185     } else if (NULL != indices) {
186         *indices = NULL;
187     }
188     return acquired;
189
190 }
191
192 bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
193                                               int indexCount,
194                                               void** vertices,
195                                               void** indices) {
196     size_t vertexSize = this->drawState()->getVertexSize();
197     this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
198     if (vertexCount) {
199         if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) {
200             if (indexCount) {
201                 this->resetIndexSource();
202             }
203             return false;
204         }
205     }
206     if (indexCount) {
207         if (!this->reserveIndexSpace(indexCount, indices)) {
208             if (vertexCount) {
209                 this->resetVertexSource();
210             }
211             return false;
212         }
213     }
214     return true;
215 }
216
217 bool GrDrawTarget::geometryHints(int32_t* vertexCount,
218                                  int32_t* indexCount) const {
219     if (NULL != vertexCount) {
220         *vertexCount = -1;
221     }
222     if (NULL != indexCount) {
223         *indexCount = -1;
224     }
225     return false;
226 }
227
228 void GrDrawTarget::releasePreviousVertexSource() {
229     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
230     switch (geoSrc.fVertexSrc) {
231         case kNone_GeometrySrcType:
232             break;
233         case kArray_GeometrySrcType:
234             this->releaseVertexArray();
235             break;
236         case kReserved_GeometrySrcType:
237             this->releaseReservedVertexSpace();
238             break;
239         case kBuffer_GeometrySrcType:
240             geoSrc.fVertexBuffer->unref();
241 #ifdef SK_DEBUG
242             geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
243 #endif
244             break;
245         default:
246             GrCrash("Unknown Vertex Source Type.");
247             break;
248     }
249 }
250
251 void GrDrawTarget::releasePreviousIndexSource() {
252     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
253     switch (geoSrc.fIndexSrc) {
254         case kNone_GeometrySrcType:   // these two don't require
255             break;
256         case kArray_GeometrySrcType:
257             this->releaseIndexArray();
258             break;
259         case kReserved_GeometrySrcType:
260             this->releaseReservedIndexSpace();
261             break;
262         case kBuffer_GeometrySrcType:
263             geoSrc.fIndexBuffer->unref();
264 #ifdef SK_DEBUG
265             geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
266 #endif
267             break;
268         default:
269             GrCrash("Unknown Index Source Type.");
270             break;
271     }
272 }
273
274 void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
275                                           int vertexCount) {
276     this->releasePreviousVertexSource();
277     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
278     geoSrc.fVertexSrc = kArray_GeometrySrcType;
279     geoSrc.fVertexSize = this->drawState()->getVertexSize();
280     geoSrc.fVertexCount = vertexCount;
281     this->onSetVertexSourceToArray(vertexArray, vertexCount);
282 }
283
284 void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
285                                          int indexCount) {
286     this->releasePreviousIndexSource();
287     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
288     geoSrc.fIndexSrc = kArray_GeometrySrcType;
289     geoSrc.fIndexCount = indexCount;
290     this->onSetIndexSourceToArray(indexArray, indexCount);
291 }
292
293 void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
294     this->releasePreviousVertexSource();
295     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
296     geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
297     geoSrc.fVertexBuffer = buffer;
298     buffer->ref();
299     geoSrc.fVertexSize = this->drawState()->getVertexSize();
300 }
301
302 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
303     this->releasePreviousIndexSource();
304     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
305     geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
306     geoSrc.fIndexBuffer  = buffer;
307     buffer->ref();
308 }
309
310 void GrDrawTarget::resetVertexSource() {
311     this->releasePreviousVertexSource();
312     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
313     geoSrc.fVertexSrc = kNone_GeometrySrcType;
314 }
315
316 void GrDrawTarget::resetIndexSource() {
317     this->releasePreviousIndexSource();
318     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
319     geoSrc.fIndexSrc = kNone_GeometrySrcType;
320 }
321
322 void GrDrawTarget::pushGeometrySource() {
323     this->geometrySourceWillPush();
324     GeometrySrcState& newState = fGeoSrcStateStack.push_back();
325     newState.fIndexSrc = kNone_GeometrySrcType;
326     newState.fVertexSrc = kNone_GeometrySrcType;
327 #ifdef SK_DEBUG
328     newState.fVertexCount  = ~0;
329     newState.fVertexBuffer = (GrVertexBuffer*)~0;
330     newState.fIndexCount   = ~0;
331     newState.fIndexBuffer = (GrIndexBuffer*)~0;
332 #endif
333 }
334
335 void GrDrawTarget::popGeometrySource() {
336     // if popping last element then pops are unbalanced with pushes
337     SkASSERT(fGeoSrcStateStack.count() > 1);
338
339     this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
340     this->releasePreviousVertexSource();
341     this->releasePreviousIndexSource();
342     fGeoSrcStateStack.pop_back();
343 }
344
345 ////////////////////////////////////////////////////////////////////////////////
346
347 bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
348                              int startIndex, int vertexCount,
349                              int indexCount) const {
350     const GrDrawState& drawState = this->getDrawState();
351 #ifdef SK_DEBUG
352     const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
353     int maxVertex = startVertex + vertexCount;
354     int maxValidVertex;
355     switch (geoSrc.fVertexSrc) {
356         case kNone_GeometrySrcType:
357             GrCrash("Attempting to draw without vertex src.");
358         case kReserved_GeometrySrcType: // fallthrough
359         case kArray_GeometrySrcType:
360             maxValidVertex = geoSrc.fVertexCount;
361             break;
362         case kBuffer_GeometrySrcType:
363             maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize);
364             break;
365     }
366     if (maxVertex > maxValidVertex) {
367         GrCrash("Drawing outside valid vertex range.");
368     }
369     if (indexCount > 0) {
370         int maxIndex = startIndex + indexCount;
371         int maxValidIndex;
372         switch (geoSrc.fIndexSrc) {
373             case kNone_GeometrySrcType:
374                 GrCrash("Attempting to draw indexed geom without index src.");
375             case kReserved_GeometrySrcType: // fallthrough
376             case kArray_GeometrySrcType:
377                 maxValidIndex = geoSrc.fIndexCount;
378                 break;
379             case kBuffer_GeometrySrcType:
380                 maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t));
381                 break;
382         }
383         if (maxIndex > maxValidIndex) {
384             GrCrash("Index reads outside valid index range.");
385         }
386     }
387
388     SkASSERT(NULL != drawState.getRenderTarget());
389
390     for (int s = 0; s < drawState.numColorStages(); ++s) {
391         const GrEffectRef& effect = *drawState.getColorStage(s).getEffect();
392         int numTextures = effect->numTextures();
393         for (int t = 0; t < numTextures; ++t) {
394             GrTexture* texture = effect->texture(t);
395             SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
396         }
397     }
398     for (int s = 0; s < drawState.numCoverageStages(); ++s) {
399         const GrEffectRef& effect = *drawState.getCoverageStage(s).getEffect();
400         int numTextures = effect->numTextures();
401         for (int t = 0; t < numTextures; ++t) {
402             GrTexture* texture = effect->texture(t);
403             SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
404         }
405     }
406
407     SkASSERT(drawState.validateVertexAttribs());
408 #endif
409     if (NULL == drawState.getRenderTarget()) {
410         return false;
411     }
412     return true;
413 }
414
415 bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) {
416     if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) {
417         return true;
418     }
419     GrRenderTarget* rt = this->drawState()->getRenderTarget();
420     SkIRect copyRect;
421     const GrClipData* clip = this->getClip();
422     clip->getConservativeBounds(rt, &copyRect);
423
424     if (NULL != drawBounds) {
425         SkIRect drawIBounds;
426         drawBounds->roundOut(&drawIBounds);
427         if (!copyRect.intersect(drawIBounds)) {
428 #ifdef SK_DEBUG
429             GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n");
430 #endif
431             return false;
432         }
433     } else {
434 #ifdef SK_DEBUG
435         //GrPrintf("No dev bounds when dst copy is made.\n");
436 #endif
437     }
438
439     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
440     // have per-sample dst values by making the copy multisampled.
441     GrTextureDesc desc;
442     this->initCopySurfaceDstDesc(rt, &desc);
443     desc.fWidth = copyRect.width();
444     desc.fHeight = copyRect.height();
445
446     GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch);
447
448     if (NULL == ast.texture()) {
449         GrPrintf("Failed to create temporary copy of destination texture.\n");
450         return false;
451     }
452     SkIPoint dstPoint = {0, 0};
453     if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) {
454         dstCopy->setTexture(ast.texture());
455         dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
456         return true;
457     } else {
458         return false;
459     }
460 }
461
462 void GrDrawTarget::drawIndexed(GrPrimitiveType type,
463                                int startVertex,
464                                int startIndex,
465                                int vertexCount,
466                                int indexCount,
467                                const SkRect* devBounds) {
468     if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
469         DrawInfo info;
470         info.fPrimitiveType = type;
471         info.fStartVertex   = startVertex;
472         info.fStartIndex    = startIndex;
473         info.fVertexCount   = vertexCount;
474         info.fIndexCount    = indexCount;
475
476         info.fInstanceCount         = 0;
477         info.fVerticesPerInstance   = 0;
478         info.fIndicesPerInstance    = 0;
479
480         if (NULL != devBounds) {
481             info.setDevBounds(*devBounds);
482         }
483         // TODO: We should continue with incorrect blending.
484         if (!this->setupDstReadIfNecessary(&info)) {
485             return;
486         }
487         this->onDraw(info);
488     }
489 }
490
491 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
492                                   int startVertex,
493                                   int vertexCount,
494                                   const SkRect* devBounds) {
495     if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
496         DrawInfo info;
497         info.fPrimitiveType = type;
498         info.fStartVertex   = startVertex;
499         info.fStartIndex    = 0;
500         info.fVertexCount   = vertexCount;
501         info.fIndexCount    = 0;
502
503         info.fInstanceCount         = 0;
504         info.fVerticesPerInstance   = 0;
505         info.fIndicesPerInstance    = 0;
506
507         if (NULL != devBounds) {
508             info.setDevBounds(*devBounds);
509         }
510         // TODO: We should continue with incorrect blending.
511         if (!this->setupDstReadIfNecessary(&info)) {
512             return;
513         }
514         this->onDraw(info);
515     }
516 }
517
518 void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) {
519     // TODO: extract portions of checkDraw that are relevant to path stenciling.
520     SkASSERT(NULL != path);
521     SkASSERT(this->caps()->pathRenderingSupport());
522     SkASSERT(!SkPath::IsInverseFillType(fill));
523     this->onStencilPath(path, fill);
524 }
525
526 void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
527     // TODO: extract portions of checkDraw that are relevant to path rendering.
528     SkASSERT(NULL != path);
529     SkASSERT(this->caps()->pathRenderingSupport());
530     const GrDrawState* drawState = &getDrawState();
531
532     SkRect devBounds;
533     if (SkPath::IsInverseFillType(fill)) {
534         devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()),
535                                    SkIntToScalar(drawState->getRenderTarget()->height()));
536     } else {
537         devBounds = path->getBounds();
538     }
539     SkMatrix viewM = drawState->getViewMatrix();
540     viewM.mapRect(&devBounds);
541
542     GrDeviceCoordTexture dstCopy;
543     if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
544         return;
545     }
546
547     this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
548 }
549
550 ////////////////////////////////////////////////////////////////////////////////
551
552 bool GrDrawTarget::willUseHWAALines() const {
553     // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
554     // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
555     // our alpha is 0xff and tweaking the color for partial coverage is OK
556     if (!this->caps()->hwAALineSupport() ||
557         !this->getDrawState().isHWAntialiasState()) {
558         return false;
559     }
560     GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
561     return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
562            (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
563 }
564
565 bool GrDrawTarget::canApplyCoverage() const {
566     // we can correctly apply coverage if a) we have dual source blending
567     // or b) one of our blend optimizations applies.
568     return this->caps()->dualSourceBlendingSupport() ||
569            GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
570 }
571
572 ////////////////////////////////////////////////////////////////////////////////
573
574 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
575                                         int instanceCount,
576                                         int verticesPerInstance,
577                                         int indicesPerInstance,
578                                         const SkRect* devBounds) {
579     if (!verticesPerInstance || !indicesPerInstance) {
580         return;
581     }
582
583     int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
584     if (!maxInstancesPerDraw) {
585         return;
586     }
587
588     DrawInfo info;
589     info.fPrimitiveType = type;
590     info.fStartIndex = 0;
591     info.fStartVertex = 0;
592     info.fIndicesPerInstance = indicesPerInstance;
593     info.fVerticesPerInstance = verticesPerInstance;
594
595     // Set the same bounds for all the draws.
596     if (NULL != devBounds) {
597         info.setDevBounds(*devBounds);
598     }
599     // TODO: We should continue with incorrect blending.
600     if (!this->setupDstReadIfNecessary(&info)) {
601         return;
602     }
603
604     while (instanceCount) {
605         info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
606         info.fVertexCount = info.fInstanceCount * verticesPerInstance;
607         info.fIndexCount = info.fInstanceCount * indicesPerInstance;
608
609         if (this->checkDraw(type,
610                             info.fStartVertex,
611                             info.fStartIndex,
612                             info.fVertexCount,
613                             info.fIndexCount)) {
614             this->onDraw(info);
615         }
616         info.fStartVertex += info.fVertexCount;
617         instanceCount -= info.fInstanceCount;
618     }
619 }
620
621 ////////////////////////////////////////////////////////////////////////////////
622
623 namespace {
624
625 // position + (optional) texture coord
626 extern const GrVertexAttrib gBWRectPosUVAttribs[] = {
627     {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
628     {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
629 };
630
631 void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) {
632     if (hasUVs) {
633         drawState->setVertexAttribs<gBWRectPosUVAttribs>(2);
634     } else {
635         drawState->setVertexAttribs<gBWRectPosUVAttribs>(1);
636     }
637 }
638
639 };
640
641 void GrDrawTarget::onDrawRect(const SkRect& rect,
642                               const SkMatrix* matrix,
643                               const SkRect* localRect,
644                               const SkMatrix* localMatrix) {
645
646     GrDrawState::AutoViewMatrixRestore avmr;
647     if (NULL != matrix) {
648         avmr.set(this->drawState(), *matrix);
649     }
650
651     set_vertex_attributes(this->drawState(), NULL != localRect);
652
653     AutoReleaseGeometry geo(this, 4, 0);
654     if (!geo.succeeded()) {
655         GrPrintf("Failed to get space for vertices!\n");
656         return;
657     }
658
659     size_t vsize = this->drawState()->getVertexSize();
660     geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
661     if (NULL != localRect) {
662         GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
663                                             sizeof(GrPoint));
664         coords->setRectFan(localRect->fLeft, localRect->fTop,
665                            localRect->fRight, localRect->fBottom,
666                            vsize);
667         if (NULL != localMatrix) {
668             localMatrix->mapPointsWithStride(coords, vsize, 4);
669         }
670     }
671     SkRect bounds;
672     this->getDrawState().getViewMatrix().mapRect(&bounds, rect);
673
674     this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds);
675 }
676
677 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
678 }
679
680 ////////////////////////////////////////////////////////////////////////////////
681
682 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
683     fDrawTarget = NULL;
684 }
685
686 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
687                                                  ASRInit init,
688                                                  const SkMatrix* vm) {
689     fDrawTarget = NULL;
690     this->set(target, init, vm);
691 }
692
693 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
694     if (NULL != fDrawTarget) {
695         fDrawTarget->setDrawState(fSavedState);
696         fSavedState->unref();
697     }
698 }
699
700 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) {
701     SkASSERT(NULL == fDrawTarget);
702     fDrawTarget = target;
703     fSavedState = target->drawState();
704     SkASSERT(fSavedState);
705     fSavedState->ref();
706     if (kReset_ASRInit == init) {
707         if (NULL == vm) {
708             // calls the default cons
709             fTempState.init();
710         } else {
711             SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm));
712         }
713     } else {
714         SkASSERT(kPreserve_ASRInit == init);
715         if (NULL == vm) {
716             fTempState.set(*fSavedState);
717         } else {
718             SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm));
719         }
720     }
721     target->setDrawState(fTempState.get());
722 }
723
724 bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) {
725     SkASSERT(NULL == fDrawTarget);
726     fDrawTarget = target;
727     fSavedState = target->drawState();
728     SkASSERT(fSavedState);
729     fSavedState->ref();
730     if (kReset_ASRInit == init) {
731         // calls the default cons
732         fTempState.init();
733     } else {
734         SkASSERT(kPreserve_ASRInit == init);
735         // calls the copy cons
736         fTempState.set(*fSavedState);
737         if (!fTempState.get()->setIdentityViewMatrix()) {
738             // let go of any resources held by the temp
739             fTempState.get()->reset();
740             fDrawTarget = NULL;
741             fSavedState->unref();
742             fSavedState = NULL;
743             return false;
744         }
745     }
746     target->setDrawState(fTempState.get());
747     return true;
748 }
749
750 ////////////////////////////////////////////////////////////////////////////////
751
752 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
753                                          GrDrawTarget*  target,
754                                          int vertexCount,
755                                          int indexCount) {
756     fTarget = NULL;
757     this->set(target, vertexCount, indexCount);
758 }
759
760 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
761     fTarget = NULL;
762 }
763
764 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
765     this->reset();
766 }
767
768 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
769                                             int vertexCount,
770                                             int indexCount) {
771     this->reset();
772     fTarget = target;
773     bool success = true;
774     if (NULL != fTarget) {
775         fTarget = target;
776         success = target->reserveVertexAndIndexSpace(vertexCount,
777                                                      indexCount,
778                                                      &fVertices,
779                                                      &fIndices);
780         if (!success) {
781             fTarget = NULL;
782             this->reset();
783         }
784     }
785     SkASSERT(success == (NULL != fTarget));
786     return success;
787 }
788
789 void GrDrawTarget::AutoReleaseGeometry::reset() {
790     if (NULL != fTarget) {
791         if (NULL != fVertices) {
792             fTarget->resetVertexSource();
793         }
794         if (NULL != fIndices) {
795             fTarget->resetIndexSource();
796         }
797         fTarget = NULL;
798     }
799     fVertices = NULL;
800     fIndices = NULL;
801 }
802
803 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
804     fTarget = target;
805     fClip = fTarget->getClip();
806     fStack.init();
807     fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
808     fReplacementClip.fClipStack = fStack.get();
809     target->setClip(&fReplacementClip);
810 }
811
812 namespace {
813 // returns true if the read/written rect intersects the src/dst and false if not.
814 bool clip_srcrect_and_dstpoint(const GrSurface* dst,
815                                const GrSurface* src,
816                                const SkIRect& srcRect,
817                                const SkIPoint& dstPoint,
818                                SkIRect* clippedSrcRect,
819                                SkIPoint* clippedDstPoint) {
820     *clippedSrcRect = srcRect;
821     *clippedDstPoint = dstPoint;
822
823     // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
824     if (clippedSrcRect->fLeft < 0) {
825         clippedDstPoint->fX -= clippedSrcRect->fLeft;
826         clippedSrcRect->fLeft = 0;
827     }
828     if (clippedDstPoint->fX < 0) {
829         clippedSrcRect->fLeft -= clippedDstPoint->fX;
830         clippedDstPoint->fX = 0;
831     }
832
833     // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
834     if (clippedSrcRect->fTop < 0) {
835         clippedDstPoint->fY -= clippedSrcRect->fTop;
836         clippedSrcRect->fTop = 0;
837     }
838     if (clippedDstPoint->fY < 0) {
839         clippedSrcRect->fTop -= clippedDstPoint->fY;
840         clippedDstPoint->fY = 0;
841     }
842
843     // clip the right edge to the src and dst bounds.
844     if (clippedSrcRect->fRight > src->width()) {
845         clippedSrcRect->fRight = src->width();
846     }
847     if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
848         clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
849     }
850
851     // clip the bottom edge to the src and dst bounds.
852     if (clippedSrcRect->fBottom > src->height()) {
853         clippedSrcRect->fBottom = src->height();
854     }
855     if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
856         clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
857     }
858
859     // The above clipping steps may have inverted the rect if it didn't intersect either the src or
860     // dst bounds.
861     return !clippedSrcRect->isEmpty();
862 }
863 }
864
865 bool GrDrawTarget::copySurface(GrSurface* dst,
866                                GrSurface* src,
867                                const SkIRect& srcRect,
868                                const SkIPoint& dstPoint) {
869     SkASSERT(NULL != dst);
870     SkASSERT(NULL != src);
871
872     SkIRect clippedSrcRect;
873     SkIPoint clippedDstPoint;
874     // If the rect is outside the src or dst then we've already succeeded.
875     if (!clip_srcrect_and_dstpoint(dst,
876                                    src,
877                                    srcRect,
878                                    dstPoint,
879                                    &clippedSrcRect,
880                                    &clippedDstPoint)) {
881         SkASSERT(this->canCopySurface(dst, src, srcRect, dstPoint));
882         return true;
883     }
884
885     bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
886     SkASSERT(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint));
887     return result;
888 }
889
890 bool GrDrawTarget::canCopySurface(GrSurface* dst,
891                                   GrSurface* src,
892                                   const SkIRect& srcRect,
893                                   const SkIPoint& dstPoint) {
894     SkASSERT(NULL != dst);
895     SkASSERT(NULL != src);
896
897     SkIRect clippedSrcRect;
898     SkIPoint clippedDstPoint;
899     // If the rect is outside the src or dst then we're guaranteed success
900     if (!clip_srcrect_and_dstpoint(dst,
901                                    src,
902                                    srcRect,
903                                    dstPoint,
904                                    &clippedSrcRect,
905                                    &clippedDstPoint)) {
906         return true;
907     }
908     return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
909 }
910
911 bool GrDrawTarget::onCanCopySurface(GrSurface* dst,
912                                     GrSurface* src,
913                                     const SkIRect& srcRect,
914                                     const SkIPoint& dstPoint) {
915     // Check that the read/write rects are contained within the src/dst bounds.
916     SkASSERT(!srcRect.isEmpty());
917     SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect));
918     SkASSERT(dstPoint.fX >= 0 && dstPoint.fY >= 0);
919     SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() &&
920              dstPoint.fY + srcRect.height() <= dst->height());
921
922     return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture();
923 }
924
925 bool GrDrawTarget::onCopySurface(GrSurface* dst,
926                                  GrSurface* src,
927                                  const SkIRect& srcRect,
928                                  const SkIPoint& dstPoint) {
929     if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) {
930         return false;
931     }
932
933     GrRenderTarget* rt = dst->asRenderTarget();
934     GrTexture* tex = src->asTexture();
935
936     GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit);
937     this->drawState()->setRenderTarget(rt);
938     SkMatrix matrix;
939     matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX),
940                         SkIntToScalar(srcRect.fTop - dstPoint.fY));
941     matrix.postIDiv(tex->width(), tex->height());
942     this->drawState()->addColorTextureEffect(tex, matrix);
943     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX,
944                                         dstPoint.fY,
945                                         srcRect.width(),
946                                         srcRect.height());
947     this->drawSimpleRect(dstRect);
948     return true;
949 }
950
951 void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
952     // Make the dst of the copy be a render target because the default copySurface draws to the dst.
953     desc->fOrigin = kDefault_GrSurfaceOrigin;
954     desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
955     desc->fConfig = src->config();
956 }
957
958 ///////////////////////////////////////////////////////////////////////////////
959
960 void GrDrawTargetCaps::reset() {
961     f8BitPaletteSupport = false;
962     fMipMapSupport = false;
963     fNPOTTextureTileSupport = false;
964     fTwoSidedStencilSupport = false;
965     fStencilWrapOpsSupport = false;
966     fHWAALineSupport = false;
967     fShaderDerivativeSupport = false;
968     fGeometryShaderSupport = false;
969     fDualSourceBlendingSupport = false;
970     fBufferLockSupport = false;
971     fPathRenderingSupport = false;
972     fDstReadInShaderSupport = false;
973     fReuseScratchTextures = true;
974
975     fMaxRenderTargetSize = 0;
976     fMaxTextureSize = 0;
977     fMaxSampleCount = 0;
978
979     memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
980 }
981
982 GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
983     f8BitPaletteSupport = other.f8BitPaletteSupport;
984     fMipMapSupport = other.fMipMapSupport;
985     fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
986     fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
987     fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
988     fHWAALineSupport = other.fHWAALineSupport;
989     fShaderDerivativeSupport = other.fShaderDerivativeSupport;
990     fGeometryShaderSupport = other.fGeometryShaderSupport;
991     fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
992     fBufferLockSupport = other.fBufferLockSupport;
993     fPathRenderingSupport = other.fPathRenderingSupport;
994     fDstReadInShaderSupport = other.fDstReadInShaderSupport;
995     fReuseScratchTextures = other.fReuseScratchTextures;
996
997     fMaxRenderTargetSize = other.fMaxRenderTargetSize;
998     fMaxTextureSize = other.fMaxTextureSize;
999     fMaxSampleCount = other.fMaxSampleCount;
1000
1001     memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
1002
1003     return *this;
1004 }
1005
1006 SkString GrDrawTargetCaps::dump() const {
1007     SkString r;
1008     static const char* gNY[] = {"NO", "YES"};
1009     r.appendf("8 Bit Palette Support       : %s\n", gNY[f8BitPaletteSupport]);
1010     r.appendf("MIP Map Support             : %s\n", gNY[fMipMapSupport]);
1011     r.appendf("NPOT Texture Tile Support   : %s\n", gNY[fNPOTTextureTileSupport]);
1012     r.appendf("Two Sided Stencil Support   : %s\n", gNY[fTwoSidedStencilSupport]);
1013     r.appendf("Stencil Wrap Ops  Support   : %s\n", gNY[fStencilWrapOpsSupport]);
1014     r.appendf("HW AA Lines Support         : %s\n", gNY[fHWAALineSupport]);
1015     r.appendf("Shader Derivative Support   : %s\n", gNY[fShaderDerivativeSupport]);
1016     r.appendf("Geometry Shader Support     : %s\n", gNY[fGeometryShaderSupport]);
1017     r.appendf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1018     r.appendf("Buffer Lock Support         : %s\n", gNY[fBufferLockSupport]);
1019     r.appendf("Path Rendering Support      : %s\n", gNY[fPathRenderingSupport]);
1020     r.appendf("Dst Read In Shader Support  : %s\n", gNY[fDstReadInShaderSupport]);
1021     r.appendf("Reuse Scratch Textures      : %s\n", gNY[fReuseScratchTextures]);
1022     r.appendf("Max Texture Size            : %d\n", fMaxTextureSize);
1023     r.appendf("Max Render Target Size      : %d\n", fMaxRenderTargetSize);
1024     r.appendf("Max Sample Count            : %d\n", fMaxSampleCount);
1025
1026     static const char* kConfigNames[] = {
1027         "Unknown",  // kUnknown_GrPixelConfig
1028         "Alpha8",   // kAlpha_8_GrPixelConfig,
1029         "Index8",   // kIndex_8_GrPixelConfig,
1030         "RGB565",   // kRGB_565_GrPixelConfig,
1031         "RGBA444",  // kRGBA_4444_GrPixelConfig,
1032         "RGBA8888", // kRGBA_8888_GrPixelConfig,
1033         "BGRA8888", // kBGRA_8888_GrPixelConfig,
1034     };
1035     GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
1036     GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
1037     GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
1038     GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
1039     GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
1040     GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
1041     GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
1042     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
1043
1044     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
1045     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);
1046     for (size_t i = 0; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
1047         if (i != kUnknown_GrPixelConfig) {
1048             r.appendf("%s is renderable: %s, with MSAA: %s\n",
1049                      kConfigNames[i],
1050                      gNY[fConfigRenderSupport[i][0]],
1051                      gNY[fConfigRenderSupport[i][1]]);
1052         }
1053     }
1054     return r;
1055 }