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