• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "GrDrawTarget.h"
10 
11 #include "GrBatch.h"
12 #include "GrContext.h"
13 #include "GrDrawTargetCaps.h"
14 #include "GrPath.h"
15 #include "GrPipeline.h"
16 #include "GrMemoryPool.h"
17 #include "GrRectBatch.h"
18 #include "GrRenderTarget.h"
19 #include "GrRenderTargetPriv.h"
20 #include "GrSurfacePriv.h"
21 #include "GrTemplates.h"
22 #include "GrTexture.h"
23 #include "GrVertexBuffer.h"
24 
25 #include "SkStrokeRec.h"
26 
27 ////////////////////////////////////////////////////////////////////////////////
28 
29 #define DEBUG_INVAL_BUFFER 0xdeadcafe
30 #define DEBUG_INVAL_START_IDX -1
31 
GrDrawTarget(GrContext * context)32 GrDrawTarget::GrDrawTarget(GrContext* context)
33     : fContext(context)
34     , fCaps(SkRef(context->getGpu()->caps()))
35     , fGpuTraceMarkerCount(0)
36     , fFlushing(false) {
37     SkASSERT(context);
38 }
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 
setupDstReadIfNecessary(const GrPipelineBuilder & pipelineBuilder,const GrProcOptInfo & colorPOI,const GrProcOptInfo & coveragePOI,GrDeviceCoordTexture * dstCopy,const SkRect * drawBounds)42 bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
43                                            const GrProcOptInfo& colorPOI,
44                                            const GrProcOptInfo& coveragePOI,
45                                            GrDeviceCoordTexture* dstCopy,
46                                            const SkRect* drawBounds) {
47     if (!pipelineBuilder.willXPNeedDstCopy(*this->caps(), colorPOI, coveragePOI)) {
48         return true;
49     }
50 
51     GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
52 
53     if (this->caps()->textureBarrierSupport()) {
54         if (GrTexture* rtTex = rt->asTexture()) {
55             // The render target is a texture, se we can read from it directly in the shader. The XP
56             // will be responsible to detect this situation and request a texture barrier.
57             dstCopy->setTexture(rtTex);
58             dstCopy->setOffset(0, 0);
59             return true;
60         }
61     }
62 
63     SkIRect copyRect;
64     pipelineBuilder.clip().getConservativeBounds(rt, &copyRect);
65 
66     if (drawBounds) {
67         SkIRect drawIBounds;
68         drawBounds->roundOut(&drawIBounds);
69         if (!copyRect.intersect(drawIBounds)) {
70 #ifdef SK_DEBUG
71             GrContextDebugf(fContext, "Missed an early reject. "
72                                       "Bailing on draw from setupDstReadIfNecessary.\n");
73 #endif
74             return false;
75         }
76     } else {
77 #ifdef SK_DEBUG
78         //SkDebugf("No dev bounds when dst copy is made.\n");
79 #endif
80     }
81 
82     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
83     // have per-sample dst values by making the copy multisampled.
84     GrSurfaceDesc desc;
85     if (!this->getGpu()->initCopySurfaceDstDesc(rt, &desc)) {
86         desc.fOrigin = kDefault_GrSurfaceOrigin;
87         desc.fFlags = kRenderTarget_GrSurfaceFlag;
88         desc.fConfig = rt->config();
89     }
90 
91 
92     desc.fWidth = copyRect.width();
93     desc.fHeight = copyRect.height();
94 
95     SkAutoTUnref<GrTexture> copy(fContext->textureProvider()->refScratchTexture(desc,
96         GrTextureProvider::kApprox_ScratchTexMatch));
97 
98     if (!copy) {
99         SkDebugf("Failed to create temporary copy of destination texture.\n");
100         return false;
101     }
102     SkIPoint dstPoint = {0, 0};
103     if (this->copySurface(copy, rt, copyRect, dstPoint)) {
104         dstCopy->setTexture(copy);
105         dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
106         return true;
107     } else {
108         return false;
109     }
110 }
111 
flush()112 void GrDrawTarget::flush() {
113     if (fFlushing) {
114         return;
115     }
116     fFlushing = true;
117 
118     this->getGpu()->saveActiveTraceMarkers();
119 
120     this->onFlush();
121 
122     this->getGpu()->restoreActiveTraceMarkers();
123 
124     fFlushing = false;
125     this->reset();
126 }
127 
drawBatch(GrPipelineBuilder * pipelineBuilder,GrBatch * batch)128 void GrDrawTarget::drawBatch(GrPipelineBuilder* pipelineBuilder,
129                              GrBatch* batch) {
130     SkASSERT(pipelineBuilder);
131     // TODO some kind of checkdraw, but not at this level
132 
133     // Setup clip
134     GrScissorState scissorState;
135     GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
136     GrPipelineBuilder::AutoRestoreStencil ars;
137     if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, &batch->bounds())) {
138         return;
139     }
140 
141     // Batch bounds are tight, so for dev copies
142     // TODO move this into setupDstReadIfNecessary when paths are in batch
143     SkRect bounds = batch->bounds();
144     bounds.outset(0.5f, 0.5f);
145 
146     GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, batch, &bounds,
147                                             this);
148     if (pipelineInfo.mustSkipDraw()) {
149         return;
150     }
151 
152     this->onDrawBatch(batch, pipelineInfo);
153 }
154 
winding_path_stencil_settings()155 static const GrStencilSettings& winding_path_stencil_settings() {
156     GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
157         kIncClamp_StencilOp,
158         kIncClamp_StencilOp,
159         kAlwaysIfInClip_StencilFunc,
160         0xFFFF, 0xFFFF, 0xFFFF);
161     return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
162 }
163 
even_odd_path_stencil_settings()164 static const GrStencilSettings& even_odd_path_stencil_settings() {
165     GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
166         kInvert_StencilOp,
167         kInvert_StencilOp,
168         kAlwaysIfInClip_StencilFunc,
169         0xFFFF, 0xFFFF, 0xFFFF);
170     return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
171 }
172 
getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,const GrStencilAttachment * sb,GrStencilSettings * outStencilSettings)173 void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,
174                                                      const GrStencilAttachment* sb,
175                                                      GrStencilSettings* outStencilSettings) {
176 
177     switch (fill) {
178         default:
179             SkFAIL("Unexpected path fill.");
180         case GrPathRendering::kWinding_FillType:
181             *outStencilSettings = winding_path_stencil_settings();
182             break;
183         case GrPathRendering::kEvenOdd_FillType:
184             *outStencilSettings = even_odd_path_stencil_settings();
185             break;
186     }
187     this->clipMaskManager()->adjustPathStencilParams(sb, outStencilSettings);
188 }
189 
stencilPath(GrPipelineBuilder * pipelineBuilder,const GrPathProcessor * pathProc,const GrPath * path,GrPathRendering::FillType fill)190 void GrDrawTarget::stencilPath(GrPipelineBuilder* pipelineBuilder,
191                                const GrPathProcessor* pathProc,
192                                const GrPath* path,
193                                GrPathRendering::FillType fill) {
194     // TODO: extract portions of checkDraw that are relevant to path stenciling.
195     SkASSERT(path);
196     SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
197     SkASSERT(pipelineBuilder);
198 
199     // Setup clip
200     GrScissorState scissorState;
201     GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
202     GrPipelineBuilder::AutoRestoreStencil ars;
203     if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, NULL)) {
204         return;
205     }
206 
207     // set stencil settings for path
208     GrStencilSettings stencilSettings;
209     GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
210     GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
211     this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
212 
213     this->onStencilPath(*pipelineBuilder, pathProc, path, scissorState, stencilSettings);
214 }
215 
drawPath(GrPipelineBuilder * pipelineBuilder,const GrPathProcessor * pathProc,const GrPath * path,GrPathRendering::FillType fill)216 void GrDrawTarget::drawPath(GrPipelineBuilder* pipelineBuilder,
217                             const GrPathProcessor* pathProc,
218                             const GrPath* path,
219                             GrPathRendering::FillType fill) {
220     // TODO: extract portions of checkDraw that are relevant to path rendering.
221     SkASSERT(path);
222     SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
223     SkASSERT(pipelineBuilder);
224 
225     SkRect devBounds = path->getBounds();
226     pathProc->viewMatrix().mapRect(&devBounds);
227 
228     // Setup clip
229     GrScissorState scissorState;
230     GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
231     GrPipelineBuilder::AutoRestoreStencil ars;
232     if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, &devBounds)) {
233        return;
234     }
235 
236     // set stencil settings for path
237     GrStencilSettings stencilSettings;
238     GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
239     GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
240     this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
241 
242     GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, &devBounds,
243                                             this);
244     if (pipelineInfo.mustSkipDraw()) {
245         return;
246     }
247 
248     this->onDrawPath(pathProc, path, stencilSettings, pipelineInfo);
249 }
250 
drawPaths(GrPipelineBuilder * pipelineBuilder,const GrPathProcessor * pathProc,const GrPathRange * pathRange,const void * indices,PathIndexType indexType,const float transformValues[],PathTransformType transformType,int count,GrPathRendering::FillType fill)251 void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
252                              const GrPathProcessor* pathProc,
253                              const GrPathRange* pathRange,
254                              const void* indices,
255                              PathIndexType indexType,
256                              const float transformValues[],
257                              PathTransformType transformType,
258                              int count,
259                              GrPathRendering::FillType fill) {
260     SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
261     SkASSERT(pathRange);
262     SkASSERT(indices);
263     SkASSERT(0 == reinterpret_cast<long>(indices) % GrPathRange::PathIndexSizeInBytes(indexType));
264     SkASSERT(transformValues);
265     SkASSERT(pipelineBuilder);
266 
267     // Setup clip
268     GrScissorState scissorState;
269     GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
270     GrPipelineBuilder::AutoRestoreStencil ars;
271 
272     if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, NULL)) {
273         return;
274     }
275 
276     // set stencil settings for path
277     GrStencilSettings stencilSettings;
278     GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
279     GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
280     this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
281 
282     // Don't compute a bounding box for dst copy texture, we'll opt
283     // instead for it to just copy the entire dst. Realistically this is a moot
284     // point, because any context that supports NV_path_rendering will also
285     // support NV_blend_equation_advanced.
286     GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, NULL, this);
287     if (pipelineInfo.mustSkipDraw()) {
288         return;
289     }
290 
291     this->onDrawPaths(pathProc, pathRange, indices, indexType, transformValues,
292                       transformType, count, stencilSettings, pipelineInfo);
293 }
294 
drawRect(GrPipelineBuilder * pipelineBuilder,GrColor color,const SkMatrix & viewMatrix,const SkRect & rect,const SkRect * localRect,const SkMatrix * localMatrix)295 void GrDrawTarget::drawRect(GrPipelineBuilder* pipelineBuilder,
296                             GrColor color,
297                             const SkMatrix& viewMatrix,
298                             const SkRect& rect,
299                             const SkRect* localRect,
300                             const SkMatrix* localMatrix) {
301    SkAutoTUnref<GrBatch> batch(GrRectBatch::Create(color, viewMatrix, rect, localRect,
302                                                    localMatrix));
303    this->drawBatch(pipelineBuilder, batch);
304 }
305 
clear(const SkIRect * rect,GrColor color,bool canIgnoreRect,GrRenderTarget * renderTarget)306 void GrDrawTarget::clear(const SkIRect* rect,
307                          GrColor color,
308                          bool canIgnoreRect,
309                          GrRenderTarget* renderTarget) {
310     if (fCaps->useDrawInsteadOfClear()) {
311         // This works around a driver bug with clear by drawing a rect instead.
312         // The driver will ignore a clear if it is the only thing rendered to a
313         // target before the target is read.
314         SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
315         if (NULL == rect || canIgnoreRect || rect->contains(rtRect)) {
316             rect = &rtRect;
317             // We first issue a discard() since that may help tilers.
318             this->discard(renderTarget);
319         }
320 
321         GrPipelineBuilder pipelineBuilder;
322         pipelineBuilder.setRenderTarget(renderTarget);
323 
324         this->drawSimpleRect(&pipelineBuilder, color, SkMatrix::I(), *rect);
325     } else {
326         this->onClear(rect, color, canIgnoreRect, renderTarget);
327     }
328 }
329 
330 typedef GrTraceMarkerSet::Iter TMIter;
saveActiveTraceMarkers()331 void GrDrawTarget::saveActiveTraceMarkers() {
332     if (this->caps()->gpuTracingSupport()) {
333         SkASSERT(0 == fStoredTraceMarkers.count());
334         fStoredTraceMarkers.addSet(fActiveTraceMarkers);
335         for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
336             this->removeGpuTraceMarker(&(*iter));
337         }
338     }
339 }
340 
restoreActiveTraceMarkers()341 void GrDrawTarget::restoreActiveTraceMarkers() {
342     if (this->caps()->gpuTracingSupport()) {
343         SkASSERT(0 == fActiveTraceMarkers.count());
344         for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
345             this->addGpuTraceMarker(&(*iter));
346         }
347         for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) {
348             this->fStoredTraceMarkers.remove(*iter);
349         }
350     }
351 }
352 
addGpuTraceMarker(const GrGpuTraceMarker * marker)353 void GrDrawTarget::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
354     if (this->caps()->gpuTracingSupport()) {
355         SkASSERT(fGpuTraceMarkerCount >= 0);
356         this->fActiveTraceMarkers.add(*marker);
357         ++fGpuTraceMarkerCount;
358     }
359 }
360 
removeGpuTraceMarker(const GrGpuTraceMarker * marker)361 void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
362     if (this->caps()->gpuTracingSupport()) {
363         SkASSERT(fGpuTraceMarkerCount >= 1);
364         this->fActiveTraceMarkers.remove(*marker);
365         --fGpuTraceMarkerCount;
366     }
367 }
368 
369 ////////////////////////////////////////////////////////////////////////////////
370 
371 namespace {
372 // returns true if the read/written rect intersects the src/dst and false if not.
clip_srcrect_and_dstpoint(const GrSurface * dst,const GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint,SkIRect * clippedSrcRect,SkIPoint * clippedDstPoint)373 bool clip_srcrect_and_dstpoint(const GrSurface* dst,
374                                const GrSurface* src,
375                                const SkIRect& srcRect,
376                                const SkIPoint& dstPoint,
377                                SkIRect* clippedSrcRect,
378                                SkIPoint* clippedDstPoint) {
379     *clippedSrcRect = srcRect;
380     *clippedDstPoint = dstPoint;
381 
382     // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
383     if (clippedSrcRect->fLeft < 0) {
384         clippedDstPoint->fX -= clippedSrcRect->fLeft;
385         clippedSrcRect->fLeft = 0;
386     }
387     if (clippedDstPoint->fX < 0) {
388         clippedSrcRect->fLeft -= clippedDstPoint->fX;
389         clippedDstPoint->fX = 0;
390     }
391 
392     // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
393     if (clippedSrcRect->fTop < 0) {
394         clippedDstPoint->fY -= clippedSrcRect->fTop;
395         clippedSrcRect->fTop = 0;
396     }
397     if (clippedDstPoint->fY < 0) {
398         clippedSrcRect->fTop -= clippedDstPoint->fY;
399         clippedDstPoint->fY = 0;
400     }
401 
402     // clip the right edge to the src and dst bounds.
403     if (clippedSrcRect->fRight > src->width()) {
404         clippedSrcRect->fRight = src->width();
405     }
406     if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
407         clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
408     }
409 
410     // clip the bottom edge to the src and dst bounds.
411     if (clippedSrcRect->fBottom > src->height()) {
412         clippedSrcRect->fBottom = src->height();
413     }
414     if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
415         clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
416     }
417 
418     // The above clipping steps may have inverted the rect if it didn't intersect either the src or
419     // dst bounds.
420     return !clippedSrcRect->isEmpty();
421 }
422 }
423 
copySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)424 bool GrDrawTarget::copySurface(GrSurface* dst,
425                                GrSurface* src,
426                                const SkIRect& srcRect,
427                                const SkIPoint& dstPoint) {
428     SkASSERT(dst);
429     SkASSERT(src);
430 
431     SkIRect clippedSrcRect;
432     SkIPoint clippedDstPoint;
433     // If the rect is outside the src or dst then we've already succeeded.
434     if (!clip_srcrect_and_dstpoint(dst,
435                                    src,
436                                    srcRect,
437                                    dstPoint,
438                                    &clippedSrcRect,
439                                    &clippedDstPoint)) {
440         return true;
441     }
442 
443     if (this->getGpu()->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint)) {
444         this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
445         return true;
446     }
447 
448     GrRenderTarget* rt = dst->asRenderTarget();
449     GrTexture* tex = src->asTexture();
450 
451     if ((dst == src) || !rt || !tex) {
452         return false;
453     }
454 
455     GrPipelineBuilder pipelineBuilder;
456     pipelineBuilder.setRenderTarget(rt);
457     SkMatrix matrix;
458     matrix.setTranslate(SkIntToScalar(clippedSrcRect.fLeft - clippedDstPoint.fX),
459                         SkIntToScalar(clippedSrcRect.fTop - clippedDstPoint.fY));
460     matrix.postIDiv(tex->width(), tex->height());
461     pipelineBuilder.addColorTextureProcessor(tex, matrix);
462     SkIRect dstRect = SkIRect::MakeXYWH(clippedDstPoint.fX,
463                                         clippedDstPoint.fY,
464                                         clippedSrcRect.width(),
465                                         clippedSrcRect.height());
466     this->drawSimpleRect(&pipelineBuilder, GrColor_WHITE, SkMatrix::I(), dstRect);
467     return true;
468 }
469 
canCopySurface(const GrSurface * dst,const GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)470 bool GrDrawTarget::canCopySurface(const GrSurface* dst,
471                                   const GrSurface* src,
472                                   const SkIRect& srcRect,
473                                   const SkIPoint& dstPoint) {
474     SkASSERT(dst);
475     SkASSERT(src);
476 
477     SkIRect clippedSrcRect;
478     SkIPoint clippedDstPoint;
479     // If the rect is outside the src or dst then we're guaranteed success
480     if (!clip_srcrect_and_dstpoint(dst,
481                                    src,
482                                    srcRect,
483                                    dstPoint,
484                                    &clippedSrcRect,
485                                    &clippedDstPoint)) {
486         return true;
487     }
488     return ((dst != src) && dst->asRenderTarget() && src->asTexture()) ||
489            this->getGpu()->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
490 }
491 
setupPipeline(const PipelineInfo & pipelineInfo,GrPipeline * pipeline)492 void GrDrawTarget::setupPipeline(const PipelineInfo& pipelineInfo,
493                                  GrPipeline* pipeline) {
494     SkNEW_PLACEMENT_ARGS(pipeline, GrPipeline, (*pipelineInfo.fPipelineBuilder,
495                                                 pipelineInfo.fColorPOI,
496                                                 pipelineInfo.fCoveragePOI,
497                                                 *this->caps(),
498                                                 *pipelineInfo.fScissor,
499                                                 &pipelineInfo.fDstCopy));
500 }
501 ///////////////////////////////////////////////////////////////////////////////
502 
PipelineInfo(GrPipelineBuilder * pipelineBuilder,GrScissorState * scissor,const GrPrimitiveProcessor * primProc,const SkRect * devBounds,GrDrawTarget * target)503 GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder,
504                                          GrScissorState* scissor,
505                                          const GrPrimitiveProcessor* primProc,
506                                          const SkRect* devBounds,
507                                          GrDrawTarget* target)
508     : fPipelineBuilder(pipelineBuilder)
509     , fScissor(scissor) {
510     fColorPOI = fPipelineBuilder->colorProcInfo(primProc);
511     fCoveragePOI = fPipelineBuilder->coverageProcInfo(primProc);
512     if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI,
513                                          &fDstCopy, devBounds)) {
514         fPipelineBuilder = NULL;
515     }
516 }
517 
PipelineInfo(GrPipelineBuilder * pipelineBuilder,GrScissorState * scissor,const GrBatch * batch,const SkRect * devBounds,GrDrawTarget * target)518 GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder,
519                                          GrScissorState* scissor,
520                                          const GrBatch* batch,
521                                          const SkRect* devBounds,
522                                          GrDrawTarget* target)
523     : fPipelineBuilder(pipelineBuilder)
524     , fScissor(scissor) {
525     fColorPOI = fPipelineBuilder->colorProcInfo(batch);
526     fCoveragePOI = fPipelineBuilder->coverageProcInfo(batch);
527     if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI,
528                                          &fDstCopy, devBounds)) {
529         fPipelineBuilder = NULL;
530     }
531 }
532 
533 ///////////////////////////////////////////////////////////////////////////////
534 
reset()535 void GrShaderCaps::reset() {
536     fShaderDerivativeSupport = false;
537     fGeometryShaderSupport = false;
538     fPathRenderingSupport = false;
539     fDstReadInShaderSupport = false;
540     fDualSourceBlendingSupport = false;
541 
542     fShaderPrecisionVaries = false;
543 }
544 
operator =(const GrShaderCaps & other)545 GrShaderCaps& GrShaderCaps::operator=(const GrShaderCaps& other) {
546     fShaderDerivativeSupport = other.fShaderDerivativeSupport;
547     fGeometryShaderSupport = other.fGeometryShaderSupport;
548     fPathRenderingSupport = other.fPathRenderingSupport;
549     fDstReadInShaderSupport = other.fDstReadInShaderSupport;
550     fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
551 
552     fShaderPrecisionVaries = other.fShaderPrecisionVaries;
553     for (int s = 0; s < kGrShaderTypeCount; ++s) {
554         for (int p = 0; p < kGrSLPrecisionCount; ++p) {
555             fFloatPrecisions[s][p] = other.fFloatPrecisions[s][p];
556         }
557     }
558     return *this;
559 }
560 
shader_type_to_string(GrShaderType type)561 static const char* shader_type_to_string(GrShaderType type) {
562     switch (type) {
563     case kVertex_GrShaderType:
564         return "vertex";
565     case kGeometry_GrShaderType:
566         return "geometry";
567     case kFragment_GrShaderType:
568         return "fragment";
569     }
570     return "";
571 }
572 
precision_to_string(GrSLPrecision p)573 static const char* precision_to_string(GrSLPrecision p) {
574     switch (p) {
575     case kLow_GrSLPrecision:
576         return "low";
577     case kMedium_GrSLPrecision:
578         return "medium";
579     case kHigh_GrSLPrecision:
580         return "high";
581     }
582     return "";
583 }
584 
dump() const585 SkString GrShaderCaps::dump() const {
586     SkString r;
587     static const char* gNY[] = { "NO", "YES" };
588     r.appendf("Shader Derivative Support          : %s\n", gNY[fShaderDerivativeSupport]);
589     r.appendf("Geometry Shader Support            : %s\n", gNY[fGeometryShaderSupport]);
590     r.appendf("Path Rendering Support             : %s\n", gNY[fPathRenderingSupport]);
591     r.appendf("Dst Read In Shader Support         : %s\n", gNY[fDstReadInShaderSupport]);
592     r.appendf("Dual Source Blending Support       : %s\n", gNY[fDualSourceBlendingSupport]);
593 
594     r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]);
595 
596     for (int s = 0; s < kGrShaderTypeCount; ++s) {
597         GrShaderType shaderType = static_cast<GrShaderType>(s);
598         r.appendf("\t%s:\n", shader_type_to_string(shaderType));
599         for (int p = 0; p < kGrSLPrecisionCount; ++p) {
600             if (fFloatPrecisions[s][p].supported()) {
601                 GrSLPrecision precision = static_cast<GrSLPrecision>(p);
602                 r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n",
603                     precision_to_string(precision),
604                     fFloatPrecisions[s][p].fLogRangeLow,
605                     fFloatPrecisions[s][p].fLogRangeHigh,
606                     fFloatPrecisions[s][p].fBits);
607             }
608         }
609     }
610 
611     return r;
612 }
613 
614 ///////////////////////////////////////////////////////////////////////////////
615 
reset()616 void GrDrawTargetCaps::reset() {
617     fMipMapSupport = false;
618     fNPOTTextureTileSupport = false;
619     fTwoSidedStencilSupport = false;
620     fStencilWrapOpsSupport = false;
621     fDiscardRenderTargetSupport = false;
622     fReuseScratchTextures = true;
623     fGpuTracingSupport = false;
624     fCompressedTexSubImageSupport = false;
625     fOversizedStencilSupport = false;
626     fTextureBarrierSupport = false;
627 
628     fUseDrawInsteadOfClear = false;
629 
630     fBlendEquationSupport = kBasic_BlendEquationSupport;
631     fMapBufferFlags = kNone_MapFlags;
632 
633     fMaxRenderTargetSize = 0;
634     fMaxTextureSize = 0;
635     fMaxSampleCount = 0;
636 
637     memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
638     memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport));
639 }
640 
operator =(const GrDrawTargetCaps & other)641 GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
642     fMipMapSupport = other.fMipMapSupport;
643     fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
644     fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
645     fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
646     fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport;
647     fReuseScratchTextures = other.fReuseScratchTextures;
648     fGpuTracingSupport = other.fGpuTracingSupport;
649     fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport;
650     fOversizedStencilSupport = other.fOversizedStencilSupport;
651     fTextureBarrierSupport = other.fTextureBarrierSupport;
652 
653     fUseDrawInsteadOfClear = other.fUseDrawInsteadOfClear;
654 
655     fBlendEquationSupport = other.fBlendEquationSupport;
656     fMapBufferFlags = other.fMapBufferFlags;
657 
658     fMaxRenderTargetSize = other.fMaxRenderTargetSize;
659     fMaxTextureSize = other.fMaxTextureSize;
660     fMaxSampleCount = other.fMaxSampleCount;
661 
662     memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
663     memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport));
664 
665     return *this;
666 }
667 
map_flags_to_string(uint32_t flags)668 static SkString map_flags_to_string(uint32_t flags) {
669     SkString str;
670     if (GrDrawTargetCaps::kNone_MapFlags == flags) {
671         str = "none";
672     } else {
673         SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags);
674         SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag);
675         str = "can_map";
676 
677         if (GrDrawTargetCaps::kSubset_MapFlag & flags) {
678             str.append(" partial");
679         } else {
680             str.append(" full");
681         }
682         SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag);
683     }
684     SkASSERT(0 == flags); // Make sure we handled all the flags.
685     return str;
686 }
687 
dump() const688 SkString GrDrawTargetCaps::dump() const {
689     SkString r;
690     static const char* gNY[] = {"NO", "YES"};
691     r.appendf("MIP Map Support                    : %s\n", gNY[fMipMapSupport]);
692     r.appendf("NPOT Texture Tile Support          : %s\n", gNY[fNPOTTextureTileSupport]);
693     r.appendf("Two Sided Stencil Support          : %s\n", gNY[fTwoSidedStencilSupport]);
694     r.appendf("Stencil Wrap Ops  Support          : %s\n", gNY[fStencilWrapOpsSupport]);
695     r.appendf("Discard Render Target Support      : %s\n", gNY[fDiscardRenderTargetSupport]);
696     r.appendf("Reuse Scratch Textures             : %s\n", gNY[fReuseScratchTextures]);
697     r.appendf("Gpu Tracing Support                : %s\n", gNY[fGpuTracingSupport]);
698     r.appendf("Compressed Update Support          : %s\n", gNY[fCompressedTexSubImageSupport]);
699     r.appendf("Oversized Stencil Support          : %s\n", gNY[fOversizedStencilSupport]);
700     r.appendf("Texture Barrier Support            : %s\n", gNY[fTextureBarrierSupport]);
701     r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]);
702 
703     r.appendf("Max Texture Size                   : %d\n", fMaxTextureSize);
704     r.appendf("Max Render Target Size             : %d\n", fMaxRenderTargetSize);
705     r.appendf("Max Sample Count                   : %d\n", fMaxSampleCount);
706 
707     static const char* kBlendEquationSupportNames[] = {
708         "Basic",
709         "Advanced",
710         "Advanced Coherent",
711     };
712     GR_STATIC_ASSERT(0 == kBasic_BlendEquationSupport);
713     GR_STATIC_ASSERT(1 == kAdvanced_BlendEquationSupport);
714     GR_STATIC_ASSERT(2 == kAdvancedCoherent_BlendEquationSupport);
715     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kBlendEquationSupportNames) == kLast_BlendEquationSupport + 1);
716 
717     r.appendf("Blend Equation Support             : %s\n",
718               kBlendEquationSupportNames[fBlendEquationSupport]);
719     r.appendf("Map Buffer Support                 : %s\n",
720               map_flags_to_string(fMapBufferFlags).c_str());
721 
722     static const char* kConfigNames[] = {
723         "Unknown",  // kUnknown_GrPixelConfig
724         "Alpha8",   // kAlpha_8_GrPixelConfig,
725         "Index8",   // kIndex_8_GrPixelConfig,
726         "RGB565",   // kRGB_565_GrPixelConfig,
727         "RGBA444",  // kRGBA_4444_GrPixelConfig,
728         "RGBA8888", // kRGBA_8888_GrPixelConfig,
729         "BGRA8888", // kBGRA_8888_GrPixelConfig,
730         "SRGBA8888",// kSRGBA_8888_GrPixelConfig,
731         "ETC1",     // kETC1_GrPixelConfig,
732         "LATC",     // kLATC_GrPixelConfig,
733         "R11EAC",   // kR11_EAC_GrPixelConfig,
734         "ASTC12x12",// kASTC_12x12_GrPixelConfig,
735         "RGBAFloat",// kRGBA_float_GrPixelConfig
736         "AlphaHalf",// kAlpha_half_GrPixelConfig
737     };
738     GR_STATIC_ASSERT(0  == kUnknown_GrPixelConfig);
739     GR_STATIC_ASSERT(1  == kAlpha_8_GrPixelConfig);
740     GR_STATIC_ASSERT(2  == kIndex_8_GrPixelConfig);
741     GR_STATIC_ASSERT(3  == kRGB_565_GrPixelConfig);
742     GR_STATIC_ASSERT(4  == kRGBA_4444_GrPixelConfig);
743     GR_STATIC_ASSERT(5  == kRGBA_8888_GrPixelConfig);
744     GR_STATIC_ASSERT(6  == kBGRA_8888_GrPixelConfig);
745     GR_STATIC_ASSERT(7  == kSRGBA_8888_GrPixelConfig);
746     GR_STATIC_ASSERT(8  == kETC1_GrPixelConfig);
747     GR_STATIC_ASSERT(9  == kLATC_GrPixelConfig);
748     GR_STATIC_ASSERT(10  == kR11_EAC_GrPixelConfig);
749     GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig);
750     GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig);
751     GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig);
752     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
753 
754     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
755     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);
756 
757     for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
758         r.appendf("%s is renderable: %s, with MSAA: %s\n",
759                   kConfigNames[i],
760                   gNY[fConfigRenderSupport[i][0]],
761                   gNY[fConfigRenderSupport[i][1]]);
762     }
763 
764     SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]);
765 
766     for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
767         r.appendf("%s is uploadable to a texture: %s\n",
768                   kConfigNames[i],
769                   gNY[fConfigTextureSupport[i]]);
770     }
771 
772     return r;
773 }
774 
775 ///////////////////////////////////////////////////////////////////////////////////////////////////
776 
setupClip(GrPipelineBuilder * pipelineBuilder,GrPipelineBuilder::AutoRestoreFragmentProcessors * arfp,GrPipelineBuilder::AutoRestoreStencil * ars,GrScissorState * scissorState,const SkRect * devBounds)777 bool GrClipTarget::setupClip(GrPipelineBuilder* pipelineBuilder,
778                              GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp,
779                              GrPipelineBuilder::AutoRestoreStencil* ars,
780                              GrScissorState* scissorState,
781                              const SkRect* devBounds) {
782     return fClipMaskManager.setupClipping(pipelineBuilder,
783                                           arfp,
784                                           ars,
785                                           scissorState,
786                                           devBounds);
787 }
788