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