Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: src/gpu/GrDrawContext.cpp

Issue 1151283004: Split drawing functionality out of GrContext and into new GrDrawContext (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix no-GPU builds Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrDefaultPathRenderer.cpp ('k') | src/gpu/GrDrawTarget.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "GrContext.h"
10
11 #include "GrAARectRenderer.h" 9 #include "GrAARectRenderer.h"
12 #include "GrAtlasTextContext.h"
13 #include "GrBatch.h" 10 #include "GrBatch.h"
14 #include "GrBatchFontCache.h"
15 #include "GrBatchTarget.h"
16 #include "GrBatchTest.h" 11 #include "GrBatchTest.h"
17 #include "GrCaps.h"
18 #include "GrContextOptions.h"
19 #include "GrDefaultGeoProcFactory.h" 12 #include "GrDefaultGeoProcFactory.h"
20 #include "GrGpuResource.h" 13 #include "GrDrawContext.h"
21 #include "GrGpuResourcePriv.h"
22 #include "GrGpu.h"
23 #include "GrImmediateDrawTarget.h"
24 #include "GrIndexBuffer.h"
25 #include "GrInOrderDrawBuffer.h"
26 #include "GrLayerCache.h"
27 #include "GrOvalRenderer.h" 14 #include "GrOvalRenderer.h"
28 #include "GrPathRenderer.h" 15 #include "GrPathRenderer.h"
29 #include "GrPathUtils.h"
30 #include "GrRenderTargetPriv.h"
31 #include "GrResourceCache.h"
32 #include "GrResourceProvider.h"
33 #include "GrSoftwarePathRenderer.h"
34 #include "GrStencilAndCoverTextContext.h"
35 #include "GrStrokeInfo.h"
36 #include "GrSurfacePriv.h"
37 #include "GrTextBlobCache.h"
38 #include "GrTexturePriv.h"
39 #include "GrTraceMarker.h"
40 #include "GrTracing.h"
41 #include "GrVertices.h"
42 #include "SkDashPathPriv.h"
43 #include "SkConfig8888.h"
44 #include "SkGr.h"
45 #include "SkRRect.h"
46 #include "SkStrokeRec.h"
47 #include "SkTLazy.h"
48 #include "SkTLS.h"
49 #include "SkTraceEvent.h"
50 16
51 #include "effects/GrConfigConversionEffect.h" 17 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext)
52 #include "effects/GrDashingEffect.h" 18 #define RETURN_IF_ABANDONED if (!fDrawTarget) { return; }
53 #include "effects/GrSingleTextureEffect.h" 19 #define RETURN_FALSE_IF_ABANDONED if (!fDrawTarget) { return false; }
20 #define RETURN_NULL_IF_ABANDONED if (!fDrawTarget) { return NULL; }
54 21
55 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) 22 class AutoCheckFlush {
56 #define RETURN_IF_ABANDONED if (!fDrawBuffer) { return; }
57 #define RETURN_FALSE_IF_ABANDONED if (!fDrawBuffer) { return false; }
58 #define RETURN_NULL_IF_ABANDONED if (!fDrawBuffer) { return NULL; }
59
60 class GrContext::AutoCheckFlush {
61 public: 23 public:
62 AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); } 24 AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); }
63 25 ~AutoCheckFlush() { fContext->flushIfNecessary(); }
64 ~AutoCheckFlush() {
65 if (fContext->fFlushToReduceCacheSize) {
66 fContext->flush();
67 }
68 }
69 26
70 private: 27 private:
71 GrContext* fContext; 28 GrContext* fContext;
72 }; 29 };
73 30
74 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) { 31 GrDrawContext::GrDrawContext(GrContext* context, GrDrawTarget* drawTarget)
75 GrContextOptions defaultOptions; 32 : fContext(context)
76 return Create(backend, backendContext, defaultOptions); 33 , fDrawTarget(SkRef(drawTarget)) {
77 } 34 }
78 35
79 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext, 36 void GrDrawContext::copySurface(GrRenderTarget* dst, GrSurface* src,
80 const GrContextOptions& options) { 37 const SkIRect& srcRect, const SkIPoint& dstPoint ) {
81 GrContext* context = SkNEW(GrContext); 38 if (!this->prepareToDraw(dst)) {
82
83 if (context->init(backend, backendContext, options)) {
84 return context;
85 } else {
86 context->unref();
87 return NULL;
88 }
89 }
90
91 static int32_t gNextID = 1;
92 static int32_t next_id() {
93 int32_t id;
94 do {
95 id = sk_atomic_inc(&gNextID);
96 } while (id == SK_InvalidGenID);
97 return id;
98 }
99
100 GrContext::GrContext() : fUniqueID(next_id()) {
101 fGpu = NULL;
102 fResourceCache = NULL;
103 fResourceProvider = NULL;
104 fPathRendererChain = NULL;
105 fSoftwarePathRenderer = NULL;
106 fBatchFontCache = NULL;
107 fDrawBuffer = NULL;
108 fFlushToReduceCacheSize = false;
109 fAARectRenderer = NULL;
110 fOvalRenderer = NULL;
111 fMaxTextureSizeOverride = 1 << 20;
112 }
113
114 bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
115 const GrContextOptions& options) {
116 SkASSERT(NULL == fGpu);
117
118 fGpu = GrGpu::Create(backend, backendContext, options, this);
119 if (NULL == fGpu) {
120 return false;
121 }
122 this->initCommon();
123 return true;
124 }
125
126 void GrContext::initCommon() {
127 fResourceCache = SkNEW(GrResourceCache);
128 fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
129 fResourceProvider = SkNEW_ARGS(GrResourceProvider, (fGpu, fResourceCache));
130
131 fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
132
133 fAARectRenderer = SkNEW(GrAARectRenderer);
134 fOvalRenderer = SkNEW(GrOvalRenderer);
135
136 fDidTestPMConversions = false;
137
138 #ifdef IMMEDIATE_MODE
139 fDrawBuffer = SkNEW_ARGS(GrImmediateDrawTarget, (this));
140 #else
141 fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (this));
142 #endif
143
144 // GrBatchFontCache will eventually replace GrFontCache
145 fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this));
146
147 fTextBlobCache.reset(SkNEW_ARGS(GrTextBlobCache, (TextBlobCacheOverBudgetCB, this)));
148 }
149
150 GrContext::~GrContext() {
151 if (NULL == fGpu) {
152 return; 39 return;
153 } 40 }
154 41
155 this->flush(); 42 fDrawTarget->copySurface(dst, src, srcRect, dstPoint);
156
157 for (int i = 0; i < fCleanUpData.count(); ++i) {
158 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
159 }
160
161 SkDELETE(fResourceProvider);
162 SkDELETE(fResourceCache);
163 SkDELETE(fBatchFontCache);
164 SkDELETE(fDrawBuffer);
165
166 fAARectRenderer->unref();
167 fOvalRenderer->unref();
168
169 fGpu->unref();
170 SkSafeUnref(fPathRendererChain);
171 SkSafeUnref(fSoftwarePathRenderer);
172 } 43 }
173 44
174 void GrContext::abandonContext() { 45 void GrDrawContext::drawText(GrPipelineBuilder* pipelineBuilder, GrBatch* batch) {
175 fResourceProvider->abandon(); 46 fDrawTarget->drawBatch(pipelineBuilder, batch);
176 // abandon first to so destructors
177 // don't try to free the resources in the API.
178 fResourceCache->abandonAll();
179
180 fGpu->contextAbandoned();
181
182 // a path renderer may be holding onto resources that
183 // are now unusable
184 SkSafeSetNull(fPathRendererChain);
185 SkSafeSetNull(fSoftwarePathRenderer);
186
187 SkDELETE(fDrawBuffer);
188 fDrawBuffer = NULL;
189
190 fBatchFontCache->freeAll();
191 fLayerCache->freeAll();
192 fTextBlobCache->freeAll();
193 } 47 }
194 48
195 void GrContext::resetContext(uint32_t state) { 49 void GrDrawContext::drawPaths(GrPipelineBuilder* pipelineBuilder,
196 fGpu->markContextDirty(state); 50 const GrPathProcessor* pathProc,
51 const GrPathRange* pathRange,
52 const void* indices,
53 int /*GrDrawTarget::PathIndexType*/ indexType,
54 const float transformValues[],
55 int /*GrDrawTarget::PathTransformType*/ transformT ype,
56 int count,
57 int /*GrPathRendering::FillType*/ fill) {
58 fDrawTarget->drawPaths(pipelineBuilder, pathProc, pathRange,
59 indices, (GrDrawTarget::PathIndexType) indexType,
60 transformValues,
61 (GrDrawTarget::PathTransformType) transformType,
62 count, (GrPathRendering::FillType) fill);
197 } 63 }
198 64
199 void GrContext::freeGpuResources() { 65 void GrDrawContext::discard(GrRenderTarget* renderTarget) {
200 this->flush(); 66 RETURN_IF_ABANDONED
201 67 SkASSERT(renderTarget);
202 if (fDrawBuffer) { 68 AutoCheckFlush acf(fContext);
203 fDrawBuffer->purgeResources(); 69 if (!this->prepareToDraw(renderTarget)) {
70 return;
204 } 71 }
205 72 fDrawTarget->discard(renderTarget);
206 fBatchFontCache->freeAll();
207 fLayerCache->freeAll();
208 // a path renderer may be holding onto resources
209 SkSafeSetNull(fPathRendererChain);
210 SkSafeSetNull(fSoftwarePathRenderer);
211
212 fResourceCache->purgeAllUnlocked();
213 } 73 }
214 74
215 void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const { 75 void GrDrawContext::clear(GrRenderTarget* renderTarget,
216 if (resourceCount) { 76 const SkIRect* rect,
217 *resourceCount = fResourceCache->getBudgetedResourceCount(); 77 const GrColor color,
78 bool canIgnoreRect) {
79 RETURN_IF_ABANDONED
80 SkASSERT(renderTarget);
81
82 AutoCheckFlush acf(fContext);
83 if (!this->prepareToDraw(renderTarget)) {
84 return;
218 } 85 }
219 if (resourceBytes) { 86 fDrawTarget->clear(rect, color, canIgnoreRect, renderTarget);
220 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
221 }
222 } 87 }
223 88
224 GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
225 SkGpuDevice* gpuDevice,
226 const SkDeviceProperties&
227 leakyProperties,
228 bool enableDistanceFieldFonts) {
229 if (fGpu->caps()->shaderCaps()->pathRenderingSupport() && renderTarget->isMu ltisampled()) {
230 GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencil Attachment();
231 if (sb) {
232 return GrStencilAndCoverTextContext::Create(this, gpuDevice, leakyPr operties);
233 }
234 }
235 89
236 return GrAtlasTextContext::Create(this, gpuDevice, leakyProperties, enableDi stanceFieldFonts); 90 void GrDrawContext::drawPaint(GrRenderTarget* rt,
237 } 91 const GrClip& clip,
238 92 const GrPaint& origPaint,
239 //////////////////////////////////////////////////////////////////////////////// 93 const SkMatrix& viewMatrix) {
240
241 bool GrContext::isConfigTexturable(GrPixelConfig config) const {
242 return fGpu->caps()->isConfigTexturable(config);
243 }
244
245 bool GrContext::npotTextureTileSupport() const {
246 return fGpu->caps()->npotTextureTileSupport();
247 }
248
249 void GrContext::OverBudgetCB(void* data) {
250 SkASSERT(data);
251
252 GrContext* context = reinterpret_cast<GrContext*>(data);
253
254 // Flush the InOrderDrawBuffer to possibly free up some textures
255 context->fFlushToReduceCacheSize = true;
256 }
257
258 void GrContext::TextBlobCacheOverBudgetCB(void* data) {
259 SkASSERT(data);
260
261 // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they
262 // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move
263 // drawText calls to below the GrContext level, but this is not trivial beca use they call
264 // drawPath on SkGpuDevice
265 GrContext* context = reinterpret_cast<GrContext*>(data);
266 context->flush();
267 }
268
269 int GrContext::getMaxTextureSize() const {
270 return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride);
271 }
272
273 int GrContext::getMaxRenderTargetSize() const {
274 return fGpu->caps()->maxRenderTargetSize();
275 }
276
277 int GrContext::getMaxSampleCount() const {
278 return fGpu->caps()->maxSampleCount();
279 }
280
281 ///////////////////////////////////////////////////////////////////////////////
282
283 void GrContext::clear(const SkIRect* rect,
284 const GrColor color,
285 bool canIgnoreRect,
286 GrRenderTarget* renderTarget) {
287 RETURN_IF_ABANDONED
288 ASSERT_OWNED_RESOURCE(renderTarget);
289 SkASSERT(renderTarget);
290
291 AutoCheckFlush acf(this);
292 GR_CREATE_TRACE_MARKER_CONTEXT("GrContext::clear", this);
293 GrDrawTarget* target = this->prepareToDraw();
294 if (NULL == target) {
295 return;
296 }
297 target->clear(rect, color, canIgnoreRect, renderTarget);
298 }
299
300 void GrContext::drawPaint(GrRenderTarget* rt,
301 const GrClip& clip,
302 const GrPaint& origPaint,
303 const SkMatrix& viewMatrix) {
304 RETURN_IF_ABANDONED 94 RETURN_IF_ABANDONED
305 // set rect to be big enough to fill the space, but not super-huge, so we 95 // set rect to be big enough to fill the space, but not super-huge, so we
306 // don't overflow fixed-point implementations 96 // don't overflow fixed-point implementations
307 SkRect r; 97 SkRect r;
308 r.setLTRB(0, 0, 98 r.setLTRB(0, 0,
309 SkIntToScalar(rt->width()), 99 SkIntToScalar(rt->width()),
310 SkIntToScalar(rt->height())); 100 SkIntToScalar(rt->height()));
311 SkTCopyOnFirstWrite<GrPaint> paint(origPaint); 101 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
312 102
313 // by definition this fills the entire clip, no need for AA 103 // by definition this fills the entire clip, no need for AA
(...skipping 14 matching lines...) Expand all
328 } 118 }
329 inverse.mapRect(&r); 119 inverse.mapRect(&r);
330 this->drawRect(rt, clip, *paint, viewMatrix, r); 120 this->drawRect(rt, clip, *paint, viewMatrix, r);
331 } else { 121 } else {
332 SkMatrix localMatrix; 122 SkMatrix localMatrix;
333 if (!viewMatrix.invert(&localMatrix)) { 123 if (!viewMatrix.invert(&localMatrix)) {
334 SkDebugf("Could not invert matrix\n"); 124 SkDebugf("Could not invert matrix\n");
335 return; 125 return;
336 } 126 }
337 127
338 AutoCheckFlush acf(this); 128 AutoCheckFlush acf(fContext);
339 GrPipelineBuilder pipelineBuilder; 129 GrPipelineBuilder pipelineBuilder;
340 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, p aint, &acf); 130 if (!this->prepareToDraw(&pipelineBuilder, rt, clip, paint)) {
341 if (NULL == target) {
342 return; 131 return;
343 } 132 }
344 133
345 GR_CREATE_TRACE_MARKER("GrContext::drawPaintWithPerspective", target); 134 fDrawTarget->drawBWRect(&pipelineBuilder,
346 target->drawRect(&pipelineBuilder, 135 paint->getColor(),
347 paint->getColor(), 136 SkMatrix::I(),
348 SkMatrix::I(), 137 r,
349 r, 138 NULL,
350 NULL, 139 &localMatrix);
351 &localMatrix);
352 } 140 }
353 } 141 }
354 142
355 ////////////////////////////////////////////////////////////////////////////////
356
357 static inline bool is_irect(const SkRect& r) { 143 static inline bool is_irect(const SkRect& r) {
358 return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) && 144 return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) &&
359 SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom); 145 SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
360 } 146 }
361 147
362 static bool apply_aa_to_rect(GrDrawTarget* target, 148 static bool apply_aa_to_rect(GrDrawTarget* target,
363 GrPipelineBuilder* pipelineBuilder, 149 GrPipelineBuilder* pipelineBuilder,
364 SkRect* devBoundRect, 150 SkRect* devBoundRect,
365 const SkRect& rect, 151 const SkRect& rect,
366 SkScalar strokeWidth, 152 SkScalar strokeWidth,
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 bool fHairline; 352 bool fHairline;
567 }; 353 };
568 354
569 const static int kVertsPerHairlineRect = 5; 355 const static int kVertsPerHairlineRect = 5;
570 const static int kVertsPerStrokeRect = 10; 356 const static int kVertsPerStrokeRect = 10;
571 357
572 BatchTracker fBatch; 358 BatchTracker fBatch;
573 SkSTArray<1, Geometry, true> fGeoData; 359 SkSTArray<1, Geometry, true> fGeoData;
574 }; 360 };
575 361
576 void GrContext::drawRect(GrRenderTarget* rt, 362 void GrDrawContext::drawRect(GrRenderTarget* rt,
577 const GrClip& clip, 363 const GrClip& clip,
578 const GrPaint& paint, 364 const GrPaint& paint,
579 const SkMatrix& viewMatrix, 365 const SkMatrix& viewMatrix,
580 const SkRect& rect, 366 const SkRect& rect,
581 const GrStrokeInfo* strokeInfo) { 367 const GrStrokeInfo* strokeInfo) {
582 RETURN_IF_ABANDONED 368 RETURN_IF_ABANDONED
583 if (strokeInfo && strokeInfo->isDashed()) { 369 if (strokeInfo && strokeInfo->isDashed()) {
584 SkPath path; 370 SkPath path;
585 path.setIsVolatile(true); 371 path.setIsVolatile(true);
586 path.addRect(rect); 372 path.addRect(rect);
587 this->drawPath(rt, clip, paint, viewMatrix, path, *strokeInfo); 373 this->drawPath(rt, clip, paint, viewMatrix, path, *strokeInfo);
588 return; 374 return;
589 } 375 }
590 376
591 AutoCheckFlush acf(this); 377 AutoCheckFlush acf(fContext);
592 GrPipelineBuilder pipelineBuilder; 378 GrPipelineBuilder pipelineBuilder;
593 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf); 379 if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
594 if (NULL == target) {
595 return; 380 return;
596 } 381 }
597 382
598 GR_CREATE_TRACE_MARKER("GrContext::drawRect", target);
599 SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getWidth(); 383 SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getWidth();
600 384
601 // Check if this is a full RT draw and can be replaced with a clear. We don' t bother checking 385 // Check if this is a full RT draw and can be replaced with a clear. We don' t bother checking
602 // cases where the RT is fully inside a stroke. 386 // cases where the RT is fully inside a stroke.
603 if (width < 0) { 387 if (width < 0) {
604 SkRect rtRect; 388 SkRect rtRect;
605 pipelineBuilder.getRenderTarget()->getBoundsRect(&rtRect); 389 pipelineBuilder.getRenderTarget()->getBoundsRect(&rtRect);
606 SkRect clipSpaceRTRect = rtRect; 390 SkRect clipSpaceRTRect = rtRect;
607 bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType(); 391 bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
608 if (checkClip) { 392 if (checkClip) {
609 clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX), 393 clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
610 SkIntToScalar(clip.origin().fY)); 394 SkIntToScalar(clip.origin().fY));
611 } 395 }
612 // Does the clip contain the entire RT? 396 // Does the clip contain the entire RT?
613 if (!checkClip || clip.quickContains(clipSpaceRTRect)) { 397 if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
614 SkMatrix invM; 398 SkMatrix invM;
615 if (!viewMatrix.invert(&invM)) { 399 if (!viewMatrix.invert(&invM)) {
616 return; 400 return;
617 } 401 }
618 // Does the rect bound the RT? 402 // Does the rect bound the RT?
619 SkPoint srcSpaceRTQuad[4]; 403 SkPoint srcSpaceRTQuad[4];
620 invM.mapRectToQuad(srcSpaceRTQuad, rtRect); 404 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
621 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) && 405 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
622 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) && 406 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
623 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) && 407 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
624 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) { 408 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
625 // Will it blend? 409 // Will it blend?
626 GrColor clearColor; 410 GrColor clearColor;
627 if (paint.isOpaqueAndConstantColor(&clearColor)) { 411 if (paint.isOpaqueAndConstantColor(&clearColor)) {
628 target->clear(NULL, clearColor, true, rt); 412 fDrawTarget->clear(NULL, clearColor, true, rt);
629 return; 413 return;
630 } 414 }
631 } 415 }
632 } 416 }
633 } 417 }
634 418
635 GrColor color = paint.getColor(); 419 GrColor color = paint.getColor();
636 SkRect devBoundRect; 420 SkRect devBoundRect;
637 bool needAA = paint.isAntiAlias() && !pipelineBuilder.getRenderTarget()->isM ultisampled(); 421 bool needAA = paint.isAntiAlias() && !pipelineBuilder.getRenderTarget()->isM ultisampled();
638 bool doAA = needAA && apply_aa_to_rect(target, &pipelineBuilder, &devBoundRe ct, rect, width, 422 bool doAA = needAA && apply_aa_to_rect(fDrawTarget, &pipelineBuilder, &devBo undRect, rect,
639 viewMatrix, color); 423 width, viewMatrix, color);
640 424
641 if (doAA) { 425 if (doAA) {
642 if (width >= 0) { 426 if (width >= 0) {
643 fAARectRenderer->strokeAARect(target, 427 GrAARectRenderer::StrokeAARect(fDrawTarget,
644 &pipelineBuilder, 428 &pipelineBuilder,
645 color, 429 color,
646 viewMatrix, 430 viewMatrix,
647 rect, 431 rect,
648 devBoundRect, 432 devBoundRect,
649 *strokeInfo); 433 *strokeInfo);
650 } else { 434 } else {
651 // filled AA rect 435 // filled AA rect
652 fAARectRenderer->fillAARect(target, 436 GrAARectRenderer::FillAARect(fDrawTarget,
653 &pipelineBuilder, 437 &pipelineBuilder,
654 color, 438 color,
655 viewMatrix, 439 viewMatrix,
656 rect, 440 rect,
657 devBoundRect); 441 devBoundRect);
658 } 442 }
659 return; 443 return;
660 } 444 }
661 445
662 if (width >= 0) { 446 if (width >= 0) {
663 StrokeRectBatch::Geometry geometry; 447 StrokeRectBatch::Geometry geometry;
664 geometry.fViewMatrix = viewMatrix; 448 geometry.fViewMatrix = viewMatrix;
665 geometry.fColor = color; 449 geometry.fColor = color;
666 geometry.fRect = rect; 450 geometry.fRect = rect;
667 geometry.fStrokeWidth = width; 451 geometry.fStrokeWidth = width;
668 452
669 // Non-AA hairlines are snapped to pixel centers to make which pixels ar e hit deterministic 453 // Non-AA hairlines are snapped to pixel centers to make which pixels ar e hit deterministic
670 bool snapToPixelCenters = (0 == width && !rt->isMultisampled()); 454 bool snapToPixelCenters = (0 == width && !rt->isMultisampled());
671 SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry, snapToPixe lCenters)); 455 SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry, snapToPixe lCenters));
672 456
673 // Depending on sub-pixel coordinates and the particular GPU, we may los e a corner of 457 // Depending on sub-pixel coordinates and the particular GPU, we may los e a corner of
674 // hairline rects. We jam all the vertices to pixel centers to avoid thi s, but not when MSAA 458 // hairline rects. We jam all the vertices to pixel centers to avoid thi s, but not when MSAA
675 // is enabled because it can cause ugly artifacts. 459 // is enabled because it can cause ugly artifacts.
676 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_ Flag, 460 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_ Flag,
677 snapToPixelCenters); 461 snapToPixelCenters);
678 target->drawBatch(&pipelineBuilder, batch); 462 fDrawTarget->drawBatch(&pipelineBuilder, batch);
679 } else { 463 } else {
680 // filled BW rect 464 // filled BW rect
681 target->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect); 465 fDrawTarget->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect);
682 } 466 }
683 } 467 }
684 468
685 void GrContext::drawNonAARectToRect(GrRenderTarget* rt, 469 void GrDrawContext::drawNonAARectToRect(GrRenderTarget* rt,
686 const GrClip& clip, 470 const GrClip& clip,
687 const GrPaint& paint, 471 const GrPaint& paint,
688 const SkMatrix& viewMatrix, 472 const SkMatrix& viewMatrix,
689 const SkRect& rectToDraw, 473 const SkRect& rectToDraw,
690 const SkRect& localRect, 474 const SkRect& localRect,
691 const SkMatrix* localMatrix) { 475 const SkMatrix* localMatrix) {
692 RETURN_IF_ABANDONED 476 RETURN_IF_ABANDONED
693 AutoCheckFlush acf(this); 477 AutoCheckFlush acf(fContext);
694 GrPipelineBuilder pipelineBuilder; 478 GrPipelineBuilder pipelineBuilder;
695 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf); 479 if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
696 if (NULL == target) {
697 return; 480 return;
698 } 481 }
699 482
700 GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target); 483 fDrawTarget->drawBWRect(&pipelineBuilder,
701 484 paint.getColor(),
702 target->drawRect(&pipelineBuilder, 485 viewMatrix,
703 paint.getColor(), 486 rectToDraw,
704 viewMatrix, 487 &localRect,
705 rectToDraw, 488 localMatrix);
706 &localRect,
707 localMatrix);
708 } 489 }
709 490
710 static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords, 491 static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords,
711 bool hasColors, 492 bool hasColors,
712 int* colorOffset, 493 int* colorOffset,
713 int* texOffset, 494 int* texOffset,
714 GrColor color, 495 GrColor color,
715 const SkMatrix& viewMatr ix, 496 const SkMatrix& viewMatr ix,
716 bool coverageIgnored) { 497 bool coverageIgnored) {
717 *texOffset = -1; 498 *texOffset = -1;
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 bool fHasIndices; 752 bool fHasIndices;
972 bool fHasLocalCoords; 753 bool fHasLocalCoords;
973 int fVertexCount; 754 int fVertexCount;
974 int fIndexCount; 755 int fIndexCount;
975 }; 756 };
976 757
977 BatchTracker fBatch; 758 BatchTracker fBatch;
978 SkSTArray<1, Geometry, true> fGeoData; 759 SkSTArray<1, Geometry, true> fGeoData;
979 }; 760 };
980 761
981 void GrContext::drawVertices(GrRenderTarget* rt, 762 void GrDrawContext::drawVertices(GrRenderTarget* rt,
982 const GrClip& clip, 763 const GrClip& clip,
983 const GrPaint& paint, 764 const GrPaint& paint,
984 const SkMatrix& viewMatrix, 765 const SkMatrix& viewMatrix,
985 GrPrimitiveType primitiveType, 766 GrPrimitiveType primitiveType,
986 int vertexCount, 767 int vertexCount,
987 const SkPoint positions[], 768 const SkPoint positions[],
988 const SkPoint texCoords[], 769 const SkPoint texCoords[],
989 const GrColor colors[], 770 const GrColor colors[],
990 const uint16_t indices[], 771 const uint16_t indices[],
991 int indexCount) { 772 int indexCount) {
992 RETURN_IF_ABANDONED 773 RETURN_IF_ABANDONED
993 AutoCheckFlush acf(this); 774 AutoCheckFlush acf(fContext);
994 GrPipelineBuilder pipelineBuilder; 775 GrPipelineBuilder pipelineBuilder;
995 776
996 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf); 777 if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
997 if (NULL == target) {
998 return; 778 return;
999 } 779 }
1000 780
1001 GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target);
1002
1003 // TODO clients should give us bounds 781 // TODO clients should give us bounds
1004 SkRect bounds; 782 SkRect bounds;
1005 if (!bounds.setBoundsCheck(positions, vertexCount)) { 783 if (!bounds.setBoundsCheck(positions, vertexCount)) {
1006 SkDebugf("drawVertices call empty bounds\n"); 784 SkDebugf("drawVertices call empty bounds\n");
1007 return; 785 return;
1008 } 786 }
1009 787
1010 viewMatrix.mapRect(&bounds); 788 viewMatrix.mapRect(&bounds);
1011 789
1012 // If we don't have AA then we outset for a half pixel in each direction to account for 790 // If we don't have AA then we outset for a half pixel in each direction to account for
1013 // snapping 791 // snapping
1014 if (!paint.isAntiAlias()) { 792 if (!paint.isAntiAlias()) {
1015 bounds.outset(0.5f, 0.5f); 793 bounds.outset(0.5f, 0.5f);
1016 } 794 }
1017 795
1018 DrawVerticesBatch::Geometry geometry; 796 DrawVerticesBatch::Geometry geometry;
1019 geometry.fColor = paint.getColor(); 797 geometry.fColor = paint.getColor();
1020 SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveTyp e, viewMatrix, 798 SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveTyp e, viewMatrix,
1021 positions, vertexCount , indices, 799 positions, vertexCount , indices,
1022 indexCount, colors, te xCoords, 800 indexCount, colors, te xCoords,
1023 bounds)); 801 bounds));
1024 802
1025 target->drawBatch(&pipelineBuilder, batch); 803 fDrawTarget->drawBatch(&pipelineBuilder, batch);
1026 } 804 }
1027 805
1028 /////////////////////////////////////////////////////////////////////////////// 806 ///////////////////////////////////////////////////////////////////////////////
1029 807
1030 void GrContext::drawRRect(GrRenderTarget*rt, 808 void GrDrawContext::drawRRect(GrRenderTarget*rt,
1031 const GrClip& clip, 809 const GrClip& clip,
1032 const GrPaint& paint, 810 const GrPaint& paint,
1033 const SkMatrix& viewMatrix, 811 const SkMatrix& viewMatrix,
1034 const SkRRect& rrect, 812 const SkRRect& rrect,
1035 const GrStrokeInfo& strokeInfo) { 813 const GrStrokeInfo& strokeInfo) {
1036 RETURN_IF_ABANDONED 814 RETURN_IF_ABANDONED
1037 if (rrect.isEmpty()) { 815 if (rrect.isEmpty()) {
1038 return; 816 return;
1039 } 817 }
1040 818
1041 if (strokeInfo.isDashed()) { 819 if (strokeInfo.isDashed()) {
1042 SkPath path; 820 SkPath path;
1043 path.setIsVolatile(true); 821 path.setIsVolatile(true);
1044 path.addRRect(rrect); 822 path.addRRect(rrect);
1045 this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo); 823 this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo);
1046 return; 824 return;
1047 } 825 }
1048 826
1049 AutoCheckFlush acf(this); 827 AutoCheckFlush acf(fContext);
1050 GrPipelineBuilder pipelineBuilder; 828 GrPipelineBuilder pipelineBuilder;
1051 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf); 829 if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
1052 if (NULL == target) {
1053 return; 830 return;
1054 } 831 }
1055 832
1056 GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target);
1057
1058 GrColor color = paint.getColor(); 833 GrColor color = paint.getColor();
1059 if (!fOvalRenderer->drawRRect(target, 834 if (!GrOvalRenderer::DrawRRect(fDrawTarget,
1060 &pipelineBuilder, 835 &pipelineBuilder,
1061 color, 836 color,
1062 viewMatrix, 837 viewMatrix,
1063 paint.isAntiAlias(), 838 paint.isAntiAlias(),
1064 rrect, 839 rrect,
1065 strokeInfo)) { 840 strokeInfo)) {
1066 SkPath path; 841 SkPath path;
1067 path.setIsVolatile(true); 842 path.setIsVolatile(true);
1068 path.addRRect(rrect); 843 path.addRRect(rrect);
1069 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, pain t.isAntiAlias(), 844 this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color,
1070 path, strokeInfo); 845 paint.isAntiAlias(), path, strokeInfo);
1071 } 846 }
1072 } 847 }
1073 848
1074 /////////////////////////////////////////////////////////////////////////////// 849 ///////////////////////////////////////////////////////////////////////////////
1075 850
1076 void GrContext::drawDRRect(GrRenderTarget* rt, 851 void GrDrawContext::drawDRRect(GrRenderTarget* rt,
1077 const GrClip& clip, 852 const GrClip& clip,
1078 const GrPaint& paint, 853 const GrPaint& paint,
1079 const SkMatrix& viewMatrix, 854 const SkMatrix& viewMatrix,
1080 const SkRRect& outer, 855 const SkRRect& outer,
1081 const SkRRect& inner) { 856 const SkRRect& inner) {
1082 RETURN_IF_ABANDONED 857 RETURN_IF_ABANDONED
1083 if (outer.isEmpty()) { 858 if (outer.isEmpty()) {
1084 return; 859 return;
1085 } 860 }
1086 861
1087 AutoCheckFlush acf(this); 862 AutoCheckFlush acf(fContext);
1088 GrPipelineBuilder pipelineBuilder; 863 GrPipelineBuilder pipelineBuilder;
1089 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf); 864 if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
1090 865 return;
1091 GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target); 866 }
1092 867
1093 GrColor color = paint.getColor(); 868 GrColor color = paint.getColor();
1094 if (!fOvalRenderer->drawDRRect(target, 869 if (!GrOvalRenderer::DrawDRRect(fDrawTarget,
1095 &pipelineBuilder, 870 &pipelineBuilder,
1096 color, 871 color,
1097 viewMatrix, 872 viewMatrix,
1098 paint.isAntiAlias(), 873 paint.isAntiAlias(),
1099 outer, 874 outer,
1100 inner)) { 875 inner)) {
1101 SkPath path; 876 SkPath path;
1102 path.setIsVolatile(true); 877 path.setIsVolatile(true);
1103 path.addRRect(inner); 878 path.addRRect(inner);
1104 path.addRRect(outer); 879 path.addRRect(outer);
1105 path.setFillType(SkPath::kEvenOdd_FillType); 880 path.setFillType(SkPath::kEvenOdd_FillType);
881
1106 GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle); 882 GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
1107 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, pain t.isAntiAlias(), 883 this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color,
1108 path, fillRec); 884 paint.isAntiAlias(), path, fillRec);
1109 } 885 }
1110 } 886 }
1111 887
1112 /////////////////////////////////////////////////////////////////////////////// 888 ///////////////////////////////////////////////////////////////////////////////
1113 889
1114 void GrContext::drawOval(GrRenderTarget* rt, 890 void GrDrawContext::drawOval(GrRenderTarget* rt,
1115 const GrClip& clip, 891 const GrClip& clip,
1116 const GrPaint& paint, 892 const GrPaint& paint,
1117 const SkMatrix& viewMatrix, 893 const SkMatrix& viewMatrix,
1118 const SkRect& oval, 894 const SkRect& oval,
1119 const GrStrokeInfo& strokeInfo) { 895 const GrStrokeInfo& strokeInfo) {
1120 RETURN_IF_ABANDONED 896 RETURN_IF_ABANDONED
1121 if (oval.isEmpty()) { 897 if (oval.isEmpty()) {
1122 return; 898 return;
1123 } 899 }
1124 900
1125 if (strokeInfo.isDashed()) { 901 if (strokeInfo.isDashed()) {
1126 SkPath path; 902 SkPath path;
1127 path.setIsVolatile(true); 903 path.setIsVolatile(true);
1128 path.addOval(oval); 904 path.addOval(oval);
1129 this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo); 905 this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo);
1130 return; 906 return;
1131 } 907 }
1132 908
1133 AutoCheckFlush acf(this); 909 AutoCheckFlush acf(fContext);
1134 GrPipelineBuilder pipelineBuilder; 910 GrPipelineBuilder pipelineBuilder;
1135 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf); 911 if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
1136 if (NULL == target) {
1137 return; 912 return;
1138 } 913 }
1139 914
1140 GR_CREATE_TRACE_MARKER("GrContext::drawOval", target);
1141
1142 GrColor color = paint.getColor(); 915 GrColor color = paint.getColor();
1143 if (!fOvalRenderer->drawOval(target, 916 if (!GrOvalRenderer::DrawOval(fDrawTarget,
1144 &pipelineBuilder, 917 &pipelineBuilder,
1145 color, 918 color,
1146 viewMatrix, 919 viewMatrix,
1147 paint.isAntiAlias(), 920 paint.isAntiAlias(),
1148 oval, 921 oval,
1149 strokeInfo)) { 922 strokeInfo)) {
1150 SkPath path; 923 SkPath path;
1151 path.setIsVolatile(true); 924 path.setIsVolatile(true);
1152 path.addOval(oval); 925 path.addOval(oval);
1153 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, pain t.isAntiAlias(), 926 this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color,
1154 path, strokeInfo); 927 paint.isAntiAlias(), path, strokeInfo);
1155 } 928 }
1156 } 929 }
1157 930
1158 // Can 'path' be drawn as a pair of filled nested rectangles? 931 // Can 'path' be drawn as a pair of filled nested rectangles?
1159 static bool is_nested_rects(GrDrawTarget* target, 932 static bool is_nested_rects(GrDrawTarget* target,
1160 GrPipelineBuilder* pipelineBuilder, 933 GrPipelineBuilder* pipelineBuilder,
1161 GrColor color, 934 GrColor color,
1162 const SkMatrix& viewMatrix, 935 const SkMatrix& viewMatrix,
1163 const SkPath& path, 936 const SkPath& path,
1164 const SkStrokeRec& stroke, 937 const SkStrokeRec& stroke,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1201 allGoE1 = false; 974 allGoE1 = false;
1202 } 975 }
1203 if (!SkScalarNearlyEqual(margin, temp)) { 976 if (!SkScalarNearlyEqual(margin, temp)) {
1204 allEq = false; 977 allEq = false;
1205 } 978 }
1206 } 979 }
1207 980
1208 return allEq || allGoE1; 981 return allEq || allGoE1;
1209 } 982 }
1210 983
1211 void GrContext::drawPath(GrRenderTarget* rt, 984 void GrDrawContext::drawPath(GrRenderTarget* rt,
1212 const GrClip& clip, 985 const GrClip& clip,
1213 const GrPaint& paint, 986 const GrPaint& paint,
1214 const SkMatrix& viewMatrix, 987 const SkMatrix& viewMatrix,
1215 const SkPath& path, 988 const SkPath& path,
1216 const GrStrokeInfo& strokeInfo) { 989 const GrStrokeInfo& strokeInfo) {
1217 RETURN_IF_ABANDONED 990 RETURN_IF_ABANDONED
1218 if (path.isEmpty()) { 991 if (path.isEmpty()) {
1219 if (path.isInverseFillType()) { 992 if (path.isInverseFillType()) {
1220 this->drawPaint(rt, clip, paint, viewMatrix); 993 this->drawPaint(rt, clip, paint, viewMatrix);
1221 } 994 }
1222 return; 995 return;
1223 } 996 }
1224 997
1225 GrColor color = paint.getColor(); 998 GrColor color = paint.getColor();
1226 999
1227 // Note that internalDrawPath may sw-rasterize the path into a scratch textu re. 1000 // Note that internalDrawPath may sw-rasterize the path into a scratch textu re.
1228 // Scratch textures can be recycled after they are returned to the texture 1001 // Scratch textures can be recycled after they are returned to the texture
1229 // cache. This presents a potential hazard for buffered drawing. However, 1002 // cache. This presents a potential hazard for buffered drawing. However,
1230 // the writePixels that uploads to the scratch will perform a flush so we're 1003 // the writePixels that uploads to the scratch will perform a flush so we're
1231 // OK. 1004 // OK.
1232 AutoCheckFlush acf(this); 1005 AutoCheckFlush acf(fContext);
1233 GrPipelineBuilder pipelineBuilder; 1006 GrPipelineBuilder pipelineBuilder;
1234 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf); 1007 if (!this->prepareToDraw(&pipelineBuilder, rt, clip, &paint)) {
1235 if (NULL == target) {
1236 return; 1008 return;
1237 } 1009 }
1238 1010
1239 GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isC onvex());
1240
1241 if (!strokeInfo.isDashed()) { 1011 if (!strokeInfo.isDashed()) {
1242 bool useCoverageAA = paint.isAntiAlias() && 1012 bool useCoverageAA = paint.isAntiAlias() &&
1243 !pipelineBuilder.getRenderTarget()->isMultisampled(); 1013 !pipelineBuilder.getRenderTarget()->isMultisampled();
1244 1014
1245 if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) { 1015 if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) {
1246 // Concave AA paths are expensive - try to avoid them for special ca ses 1016 // Concave AA paths are expensive - try to avoid them for special ca ses
1247 SkRect rects[2]; 1017 SkRect rects[2];
1248 1018
1249 if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, pat h, strokeInfo, 1019 if (is_nested_rects(fDrawTarget, &pipelineBuilder, color, viewMatrix , path, strokeInfo,
1250 rects)) { 1020 rects)) {
1251 fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, col or, viewMatrix, 1021 GrAARectRenderer::FillAANestedRects(fDrawTarget, &pipelineBuilde r, color,
1252 rects); 1022 viewMatrix, rects);
1253 return; 1023 return;
1254 } 1024 }
1255 } 1025 }
1256 SkRect ovalRect; 1026 SkRect ovalRect;
1257 bool isOval = path.isOval(&ovalRect); 1027 bool isOval = path.isOval(&ovalRect);
1258 1028
1259 if (isOval && !path.isInverseFillType()) { 1029 if (isOval && !path.isInverseFillType()) {
1260 if (fOvalRenderer->drawOval(target, 1030 if (GrOvalRenderer::DrawOval(fDrawTarget,
1261 &pipelineBuilder, 1031 &pipelineBuilder,
1262 color, 1032 color,
1263 viewMatrix, 1033 viewMatrix,
1264 paint.isAntiAlias(), 1034 paint.isAntiAlias(),
1265 ovalRect, 1035 ovalRect,
1266 strokeInfo)) { 1036 strokeInfo)) {
1267 return; 1037 return;
1268 } 1038 }
1269 } 1039 }
1270 } 1040 }
1271 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.is AntiAlias(), 1041 this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color, pai nt.isAntiAlias(),
1272 path, strokeInfo); 1042 path, strokeInfo);
1273 } 1043 }
1274 1044
1275 void GrContext::internalDrawPath(GrDrawTarget* target, 1045 void GrDrawContext::internalDrawPath(GrDrawTarget* target,
1276 GrPipelineBuilder* pipelineBuilder, 1046 GrPipelineBuilder* pipelineBuilder,
1277 const SkMatrix& viewMatrix, 1047 const SkMatrix& viewMatrix,
1278 GrColor color, 1048 GrColor color,
1279 bool useAA, 1049 bool useAA,
1280 const SkPath& path, 1050 const SkPath& path,
1281 const GrStrokeInfo& strokeInfo) { 1051 const GrStrokeInfo& strokeInfo) {
1282 RETURN_IF_ABANDONED 1052 RETURN_IF_ABANDONED
1283 SkASSERT(!path.isEmpty()); 1053 SkASSERT(!path.isEmpty());
1284 1054
1285 GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target);
1286
1287 1055
1288 // An Assumption here is that path renderer would use some form of tweaking 1056 // An Assumption here is that path renderer would use some form of tweaking
1289 // the src color (either the input alpha or in the frag shader) to implement 1057 // the src color (either the input alpha or in the frag shader) to implement
1290 // aa. If we have some future driver-mojo path AA that can do the right 1058 // aa. If we have some future driver-mojo path AA that can do the right
1291 // thing WRT to the blend then we'll need some query on the PR. 1059 // thing WRT to the blend then we'll need some query on the PR.
1292 bool useCoverageAA = useAA && 1060 bool useCoverageAA = useAA &&
1293 !pipelineBuilder->getRenderTarget()->isMultisampled(); 1061 !pipelineBuilder->getRenderTarget()->isMultisampled();
1294 1062
1295 1063
1296 GrPathRendererChain::DrawType type = 1064 GrPathRendererChain::DrawType type =
1297 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType : 1065 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
1298 GrPathRendererChain::kColor_DrawType; 1066 GrPathRendererChain::kColor_DrawType;
1299 1067
1300 const SkPath* pathPtr = &path; 1068 const SkPath* pathPtr = &path;
1301 SkTLazy<SkPath> tmpPath; 1069 SkTLazy<SkPath> tmpPath;
1302 const GrStrokeInfo* strokeInfoPtr = &strokeInfo; 1070 const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
1303 1071
1304 // Try a 1st time without stroking the path and without allowing the SW rend erer 1072 // Try a 1st time without stroking the path and without allowing the SW rend erer
1305 GrPathRenderer* pr = this->getPathRenderer(target, pipelineBuilder, viewMatr ix, *pathPtr, 1073 GrPathRenderer* pr = fContext->getPathRenderer(target, pipelineBuilder, view Matrix, *pathPtr,
1306 *strokeInfoPtr, false, type); 1074 *strokeInfoPtr, false, type) ;
1307 1075
1308 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false); 1076 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
1309 if (NULL == pr && strokeInfo.isDashed()) { 1077 if (NULL == pr && strokeInfo.isDashed()) {
1310 // It didn't work above, so try again with dashed stroke converted to a dashless stroke. 1078 // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
1311 if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pa thPtr)) { 1079 if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pa thPtr)) {
1312 return; 1080 return;
1313 } 1081 }
1314 pathPtr = tmpPath.get(); 1082 pathPtr = tmpPath.get();
1315 if (pathPtr->isEmpty()) { 1083 if (pathPtr->isEmpty()) {
1316 return; 1084 return;
1317 } 1085 }
1318 strokeInfoPtr = &dashlessStrokeInfo; 1086 strokeInfoPtr = &dashlessStrokeInfo;
1319 pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr , *strokeInfoPtr, 1087 pr = fContext->getPathRenderer(target, pipelineBuilder, viewMatrix, *pat hPtr, *strokeInfoPtr,
1320 false, type); 1088 false, type);
1321 } 1089 }
1322 1090
1323 if (NULL == pr) { 1091 if (NULL == pr) {
1324 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMa trix, NULL) && 1092 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMa trix, NULL) &&
1325 !strokeInfoPtr->isFillStyle()) { 1093 !strokeInfoPtr->isFillStyle()) {
1326 // It didn't work above, so try again with stroke converted to a fil l. 1094 // It didn't work above, so try again with stroke converted to a fil l.
1327 if (!tmpPath.isValid()) { 1095 if (!tmpPath.isValid()) {
1328 tmpPath.init(); 1096 tmpPath.init();
1329 } 1097 }
1330 dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()) ); 1098 dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()) );
1331 if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) { 1099 if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) {
1332 return; 1100 return;
1333 } 1101 }
1334 pathPtr = tmpPath.get(); 1102 pathPtr = tmpPath.get();
1335 if (pathPtr->isEmpty()) { 1103 if (pathPtr->isEmpty()) {
1336 return; 1104 return;
1337 } 1105 }
1338 dashlessStrokeInfo.setFillStyle(); 1106 dashlessStrokeInfo.setFillStyle();
1339 strokeInfoPtr = &dashlessStrokeInfo; 1107 strokeInfoPtr = &dashlessStrokeInfo;
1340 } 1108 }
1341 1109
1342 // This time, allow SW renderer 1110 // This time, allow SW renderer
1343 pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr , *strokeInfoPtr, 1111 pr = fContext->getPathRenderer(target, pipelineBuilder, viewMatrix, *pat hPtr, *strokeInfoPtr,
1344 true, type); 1112 true, type);
1345 } 1113 }
1346 1114
1347 if (NULL == pr) { 1115 if (NULL == pr) {
1348 #ifdef SK_DEBUG 1116 #ifdef SK_DEBUG
1349 SkDebugf("Unable to find path renderer compatible with path.\n"); 1117 SkDebugf("Unable to find path renderer compatible with path.\n");
1350 #endif 1118 #endif
1351 return; 1119 return;
1352 } 1120 }
1353 1121
1354 pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeIn foPtr, useCoverageAA); 1122 pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeIn foPtr, useCoverageAA);
1355 } 1123 }
1356 1124
1357 //////////////////////////////////////////////////////////////////////////////// 1125 bool GrDrawContext::prepareToDraw(GrPipelineBuilder* pipelineBuilder,
1126 GrRenderTarget* rt,
1127 const GrClip& clip,
1128 const GrPaint* paint) {
1129 RETURN_FALSE_IF_ABANDONED
1358 1130
1359 void GrContext::flush(int flagsBitfield) { 1131 ASSERT_OWNED_RESOURCE(rt);
1360 if (NULL == fDrawBuffer) { 1132 SkASSERT(rt && paint);
1361 return; 1133 pipelineBuilder->setFromPaint(*paint, rt, clip);
1362 }
1363
1364 if (kDiscard_FlushBit & flagsBitfield) {
1365 fDrawBuffer->reset();
1366 } else {
1367 fDrawBuffer->flush();
1368 }
1369 fResourceCache->notifyFlushOccurred();
1370 fFlushToReduceCacheSize = false;
1371 }
1372
1373 bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
1374 const void* inPixels, size_t outRowBytes, void* outPix els) {
1375 SkSrcPixelInfo srcPI;
1376 if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, NULL)) {
1377 return false;
1378 }
1379 srcPI.fAlphaType = kUnpremul_SkAlphaType;
1380 srcPI.fPixels = inPixels;
1381 srcPI.fRowBytes = inRowBytes;
1382
1383 SkDstPixelInfo dstPI;
1384 dstPI.fColorType = srcPI.fColorType;
1385 dstPI.fAlphaType = kPremul_SkAlphaType;
1386 dstPI.fPixels = outPixels;
1387 dstPI.fRowBytes = outRowBytes;
1388
1389 return srcPI.convertPixelsTo(&dstPI, width, height);
1390 }
1391
1392 bool GrContext::writeSurfacePixels(GrSurface* surface,
1393 int left, int top, int width, int height,
1394 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
1395 uint32_t pixelOpsFlags) {
1396 RETURN_FALSE_IF_ABANDONED
1397 {
1398 GrTexture* texture = NULL;
1399 if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asT exture()) &&
1400 fGpu->canWriteTexturePixels(texture, srcConfig)) {
1401
1402 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) &&
1403 surface->surfacePriv().hasPendingIO()) {
1404 this->flush();
1405 }
1406 return fGpu->writeTexturePixels(texture, left, top, width, height,
1407 srcConfig, buffer, rowBytes);
1408 // Don't need to check kFlushWrites_PixelOp here, we just did a dire ct write so the
1409 // upload is already flushed.
1410 }
1411 }
1412
1413 // If we didn't do a direct texture write then we upload the pixels to a tex ture and draw.
1414 GrRenderTarget* renderTarget = surface->asRenderTarget();
1415 if (NULL == renderTarget) {
1416 return false;
1417 }
1418
1419 // We ignore the preferred config unless it is a R/B swap of the src config. In that case
1420 // we will upload the original src data to a scratch texture but we will spo of it as the swapped
1421 // config. This scratch will then have R and B swapped. We correct for this by swapping again
1422 // when drawing the scratch to the dst using a conversion effect.
1423 bool swapRAndB = false;
1424 GrPixelConfig writeConfig = srcConfig;
1425 if (GrPixelConfigSwapRAndB(srcConfig) ==
1426 fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
1427 writeConfig = GrPixelConfigSwapRAndB(srcConfig);
1428 swapRAndB = true;
1429 }
1430
1431 GrSurfaceDesc desc;
1432 desc.fWidth = width;
1433 desc.fHeight = height;
1434 desc.fConfig = writeConfig;
1435 SkAutoTUnref<GrTexture> texture(this->textureProvider()->refScratchTexture(d esc,
1436 GrTextureProvider::kApprox_ScratchTexMatch));
1437 if (!texture) {
1438 return false;
1439 }
1440
1441 SkAutoTUnref<const GrFragmentProcessor> fp;
1442 SkMatrix textureMatrix;
1443 textureMatrix.setIDiv(texture->width(), texture->height());
1444
1445 // allocate a tmp buffer and sw convert the pixels to premul
1446 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1447
1448 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
1449 if (!GrPixelConfigIs8888(srcConfig)) {
1450 return false;
1451 }
1452 fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
1453 // handle the unpremul step on the CPU if we couldn't create an effect t o do it.
1454 if (NULL == fp) {
1455 size_t tmpRowBytes = 4 * width;
1456 tmpPixels.reset(width * height);
1457 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer , tmpRowBytes,
1458 tmpPixels.get())) {
1459 return false;
1460 }
1461 rowBytes = tmpRowBytes;
1462 buffer = tmpPixels.get();
1463 }
1464 }
1465 if (NULL == fp) {
1466 fp.reset(GrConfigConversionEffect::Create(texture,
1467 swapRAndB,
1468 GrConfigConversionEffect::kNon e_PMConversion,
1469 textureMatrix));
1470 }
1471
1472 // Even if the client told us not to flush, we still flush here. The client may have known that
1473 // writes to the original surface caused no data hazards, but they can't kno w that the scratch
1474 // we just got is safe.
1475 if (texture->surfacePriv().hasPendingIO()) {
1476 this->flush();
1477 }
1478 if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
1479 writeConfig, buffer, rowBytes)) {
1480 return false;
1481 }
1482
1483 SkMatrix matrix;
1484 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
1485
1486 // This function can be called in the midst of drawing another object (e.g., when uploading a
1487 // SW-rasterized clip while issuing a draw). So we push the current geometry state before
1488 // drawing a rect to the render target.
1489 // The bracket ensures we pop the stack if we wind up flushing below.
1490 {
1491 GrDrawTarget* drawTarget = this->prepareToDraw();
1492 if (!drawTarget) {
1493 return false;
1494 }
1495
1496 GrPipelineBuilder pipelineBuilder;
1497 pipelineBuilder.addColorProcessor(fp);
1498 pipelineBuilder.setRenderTarget(renderTarget);
1499 drawTarget->drawSimpleRect(&pipelineBuilder,
1500 GrColor_WHITE,
1501 matrix,
1502 SkRect::MakeWH(SkIntToScalar(width), SkIntToS calar(height)));
1503 }
1504
1505 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1506 this->flushSurfaceWrites(surface);
1507 }
1508
1509 return true; 1134 return true;
1510 } 1135 }
1511 1136
1512 // toggles between RGBA and BGRA 1137 bool GrDrawContext::prepareToDraw(GrRenderTarget* rt) {
1513 static SkColorType toggle_colortype32(SkColorType ct) { 1138 RETURN_FALSE_IF_ABANDONED
1514 if (kRGBA_8888_SkColorType == ct) {
1515 return kBGRA_8888_SkColorType;
1516 } else {
1517 SkASSERT(kBGRA_8888_SkColorType == ct);
1518 return kRGBA_8888_SkColorType;
1519 }
1520 }
1521 1139
1522 bool GrContext::readRenderTargetPixels(GrRenderTarget* target, 1140 ASSERT_OWNED_RESOURCE(rt);
1523 int left, int top, int width, int height, 1141 SkASSERT(rt);
1524 GrPixelConfig dstConfig, void* buffer, si ze_t rowBytes,
1525 uint32_t flags) {
1526 RETURN_FALSE_IF_ABANDONED
1527 ASSERT_OWNED_RESOURCE(target);
1528 SkASSERT(target);
1529
1530 if (!(kDontFlush_PixelOpsFlag & flags) && target->surfacePriv().hasPendingWr ite()) {
1531 this->flush();
1532 }
1533
1534 // Determine which conversions have to be applied: flipY, swapRAnd, and/or u npremul.
1535
1536 // If fGpu->readPixels would incur a y-flip cost then we will read the pixel s upside down. We'll
1537 // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
1538 bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
1539 width, height, dstConfig,
1540 rowBytes);
1541 // We ignore the preferred config if it is different than our config unless it is an R/B swap.
1542 // In that case we'll perform an R and B swap while drawing to a scratch tex ture of the swapped
1543 // config. Then we will call readPixels on the scratch with the swapped conf ig. The swaps during
1544 // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from
1545 // dstConfig.
1546 GrPixelConfig readConfig = dstConfig;
1547 bool swapRAndB = false;
1548 if (GrPixelConfigSwapRAndB(dstConfig) ==
1549 fGpu->preferredReadPixelsConfig(dstConfig, target->config())) {
1550 readConfig = GrPixelConfigSwapRAndB(readConfig);
1551 swapRAndB = true;
1552 }
1553
1554 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
1555
1556 if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
1557 // The unpremul flag is only allowed for these two configs.
1558 return false;
1559 }
1560
1561 SkAutoTUnref<GrTexture> tempTexture;
1562
1563 // If the src is a texture and we would have to do conversions after read pi xels, we instead
1564 // do the conversions by drawing the src to a scratch texture. If we handle any of the
1565 // conversions in the draw we set the corresponding bool to false so that we don't reapply it
1566 // on the read back pixels.
1567 GrTexture* src = target->asTexture();
1568 if (src && (swapRAndB || unpremul || flipY)) {
1569 // Make the scratch a render so we can read its pixels.
1570 GrSurfaceDesc desc;
1571 desc.fFlags = kRenderTarget_GrSurfaceFlag;
1572 desc.fWidth = width;
1573 desc.fHeight = height;
1574 desc.fConfig = readConfig;
1575 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1576
1577 // When a full read back is faster than a partial we could always make t he scratch exactly
1578 // match the passed rect. However, if we see many different size rectang les we will trash
1579 // our texture cache and pay the cost of creating and destroying many te xtures. So, we only
1580 // request an exact match when the caller is reading an entire RT.
1581 GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_Sc ratchTexMatch;
1582 if (0 == left &&
1583 0 == top &&
1584 target->width() == width &&
1585 target->height() == height &&
1586 fGpu->fullReadPixelsIsFasterThanPartial()) {
1587 match = GrTextureProvider::kExact_ScratchTexMatch;
1588 }
1589 tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match ));
1590 if (tempTexture) {
1591 // compute a matrix to perform the draw
1592 SkMatrix textureMatrix;
1593 textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1594 textureMatrix.postIDiv(src->width(), src->height());
1595
1596 SkAutoTUnref<const GrFragmentProcessor> fp;
1597 if (unpremul) {
1598 fp.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix ));
1599 if (fp) {
1600 unpremul = false; // we no longer need to do this on CPU aft er the read back.
1601 }
1602 }
1603 // If we failed to create a PM->UPM effect and have no other convers ions to perform then
1604 // there is no longer any point to using the scratch.
1605 if (fp || flipY || swapRAndB) {
1606 if (!fp) {
1607 fp.reset(GrConfigConversionEffect::Create(
1608 src, swapRAndB, GrConfigConversionEffect::kNone_PMCo nversion,
1609 textureMatrix));
1610 }
1611 swapRAndB = false; // we will handle the swap in the draw.
1612
1613 // We protect the existing geometry here since it may not be
1614 // clear to the caller that a draw operation (i.e., drawSimpleRe ct)
1615 // can be invoked in this method
1616 {
1617 GrPipelineBuilder pipelineBuilder;
1618 SkASSERT(fp);
1619 pipelineBuilder.addColorProcessor(fp);
1620
1621 pipelineBuilder.setRenderTarget(tempTexture->asRenderTarget( ));
1622 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToSc alar(height));
1623 fDrawBuffer->drawSimpleRect(&pipelineBuilder,
1624 GrColor_WHITE,
1625 SkMatrix::I(),
1626 rect);
1627 // we want to read back from the scratch's origin
1628 left = 0;
1629 top = 0;
1630 target = tempTexture->asRenderTarget();
1631 }
1632 this->flushSurfaceWrites(target);
1633 }
1634 }
1635 }
1636
1637 if (!fGpu->readPixels(target,
1638 left, top, width, height,
1639 readConfig, buffer, rowBytes)) {
1640 return false;
1641 }
1642 // Perform any conversions we weren't able to perform using a scratch textur e.
1643 if (unpremul || swapRAndB) {
1644 SkDstPixelInfo dstPI;
1645 if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NUL L)) {
1646 return false;
1647 }
1648 dstPI.fAlphaType = kUnpremul_SkAlphaType;
1649 dstPI.fPixels = buffer;
1650 dstPI.fRowBytes = rowBytes;
1651
1652 SkSrcPixelInfo srcPI;
1653 srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : ds tPI.fColorType;
1654 srcPI.fAlphaType = kPremul_SkAlphaType;
1655 srcPI.fPixels = buffer;
1656 srcPI.fRowBytes = rowBytes;
1657
1658 return srcPI.convertPixelsTo(&dstPI, width, height);
1659 }
1660 return true; 1142 return true;
1661 } 1143 }
1662 1144
1663 void GrContext::prepareSurfaceForExternalRead(GrSurface* surface) {
1664 RETURN_IF_ABANDONED
1665 SkASSERT(surface);
1666 ASSERT_OWNED_RESOURCE(surface);
1667 if (surface->surfacePriv().hasPendingIO()) {
1668 this->flush();
1669 }
1670 GrRenderTarget* rt = surface->asRenderTarget();
1671 if (fGpu && rt) {
1672 fGpu->resolveRenderTarget(rt);
1673 }
1674 }
1675
1676 void GrContext::discardRenderTarget(GrRenderTarget* renderTarget) {
1677 RETURN_IF_ABANDONED
1678 SkASSERT(renderTarget);
1679 ASSERT_OWNED_RESOURCE(renderTarget);
1680 AutoCheckFlush acf(this);
1681 GrDrawTarget* target = this->prepareToDraw();
1682 if (NULL == target) {
1683 return;
1684 }
1685 target->discard(renderTarget);
1686 }
1687
1688 void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe ct,
1689 const SkIPoint& dstPoint, uint32_t pixelOpsFlags) {
1690 RETURN_IF_ABANDONED
1691 if (NULL == src || NULL == dst) {
1692 return;
1693 }
1694 ASSERT_OWNED_RESOURCE(src);
1695 ASSERT_OWNED_RESOURCE(dst);
1696
1697 // Since we're going to the draw target and not GPU, no need to check kNoFlu sh
1698 // here.
1699
1700 GrDrawTarget* target = this->prepareToDraw();
1701 if (NULL == target) {
1702 return;
1703 }
1704 target->copySurface(dst, src, srcRect, dstPoint);
1705
1706 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1707 this->flush();
1708 }
1709 }
1710
1711 void GrContext::flushSurfaceWrites(GrSurface* surface) {
1712 RETURN_IF_ABANDONED
1713 if (surface->surfacePriv().hasPendingWrite()) {
1714 this->flush();
1715 }
1716 }
1717
1718 GrDrawTarget* GrContext::prepareToDraw(GrPipelineBuilder* pipelineBuilder,
1719 GrRenderTarget* rt,
1720 const GrClip& clip,
1721 const GrPaint* paint,
1722 const AutoCheckFlush* acf) {
1723 if (NULL == fGpu || NULL == fDrawBuffer) {
1724 return NULL;
1725 }
1726
1727 ASSERT_OWNED_RESOURCE(rt);
1728 SkASSERT(rt && paint && acf);
1729 pipelineBuilder->setFromPaint(*paint, rt, clip);
1730 return fDrawBuffer;
1731 }
1732
1733 GrDrawTarget* GrContext::prepareToDraw() {
1734 if (NULL == fGpu) {
1735 return NULL;
1736 }
1737 return fDrawBuffer;
1738 }
1739
1740 /*
1741 * This method finds a path renderer that can draw the specified path on
1742 * the provided target.
1743 * Due to its expense, the software path renderer has split out so it can
1744 * can be individually allowed/disallowed via the "allowSW" boolean.
1745 */
1746 GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
1747 const GrPipelineBuilder* pipelineBuil der,
1748 const SkMatrix& viewMatrix,
1749 const SkPath& path,
1750 const GrStrokeInfo& stroke,
1751 bool allowSW,
1752 GrPathRendererChain::DrawType drawTyp e,
1753 GrPathRendererChain::StencilSupport* stencilSupport) {
1754
1755 if (NULL == fPathRendererChain) {
1756 fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
1757 }
1758
1759 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target,
1760 pipelineBuilder,
1761 viewMatrix,
1762 path,
1763 stroke,
1764 drawType,
1765 stencilSupport);
1766
1767 if (NULL == pr && allowSW) {
1768 if (NULL == fSoftwarePathRenderer) {
1769 fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
1770 }
1771 pr = fSoftwarePathRenderer;
1772 }
1773
1774 return pr;
1775 }
1776
1777 ////////////////////////////////////////////////////////////////////////////////
1778 bool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
1779 return fGpu->caps()->isConfigRenderable(config, withMSAA);
1780 }
1781
1782 int GrContext::getRecommendedSampleCount(GrPixelConfig config,
1783 SkScalar dpi) const {
1784 if (!this->isConfigRenderable(config, true)) {
1785 return 0;
1786 }
1787 int chosenSampleCount = 0;
1788 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
1789 if (dpi >= 250.0f) {
1790 chosenSampleCount = 4;
1791 } else {
1792 chosenSampleCount = 16;
1793 }
1794 }
1795 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ?
1796 chosenSampleCount : 0;
1797 }
1798
1799 GrDrawTarget* GrContext::getTextTarget() {
1800 return this->prepareToDraw();
1801 }
1802
1803 namespace {
1804 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
1805 GrConfigConversionEffect::PMConversion pmToUPM;
1806 GrConfigConversionEffect::PMConversion upmToPM;
1807 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upm ToPM);
1808 *pmToUPMValue = pmToUPM;
1809 *upmToPMValue = upmToPM;
1810 }
1811 }
1812
1813 const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture,
1814 bool swapRAndB,
1815 const SkMatrix& matrix ) {
1816 if (!fDidTestPMConversions) {
1817 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1818 fDidTestPMConversions = true;
1819 }
1820 GrConfigConversionEffect::PMConversion pmToUPM =
1821 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
1822 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
1823 return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, mat rix);
1824 } else {
1825 return NULL;
1826 }
1827 }
1828
1829 const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture,
1830 bool swapRAndB,
1831 const SkMatrix& matrix ) {
1832 if (!fDidTestPMConversions) {
1833 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1834 fDidTestPMConversions = true;
1835 }
1836 GrConfigConversionEffect::PMConversion upmToPM =
1837 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
1838 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
1839 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, mat rix);
1840 } else {
1841 return NULL;
1842 }
1843 }
1844
1845 //////////////////////////////////////////////////////////////////////////////
1846
1847 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes ) const {
1848 if (maxTextures) {
1849 *maxTextures = fResourceCache->getMaxResourceCount();
1850 }
1851 if (maxTextureBytes) {
1852 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
1853 }
1854 }
1855
1856 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
1857 fResourceCache->setLimits(maxTextures, maxTextureBytes);
1858 }
1859
1860 //////////////////////////////////////////////////////////////////////////////
1861
1862 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
1863 fGpu->addGpuTraceMarker(marker);
1864 if (fDrawBuffer) {
1865 fDrawBuffer->addGpuTraceMarker(marker);
1866 }
1867 }
1868
1869 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
1870 fGpu->removeGpuTraceMarker(marker);
1871 if (fDrawBuffer) {
1872 fDrawBuffer->removeGpuTraceMarker(marker);
1873 }
1874 }
1875
1876 //////////////////////////////////////////////////////////////////////////////// /////////////////// 1145 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1877 1146
1878 #ifdef GR_TEST_UTILS 1147 #ifdef GR_TEST_UTILS
1879 1148
1880 BATCH_TEST_DEFINE(StrokeRectBatch) { 1149 BATCH_TEST_DEFINE(StrokeRectBatch) {
1881 StrokeRectBatch::Geometry geometry; 1150 StrokeRectBatch::Geometry geometry;
1882 geometry.fViewMatrix = GrTest::TestMatrix(random); 1151 geometry.fViewMatrix = GrTest::TestMatrix(random);
1883 geometry.fColor = GrRandomColor(random); 1152 geometry.fColor = GrRandomColor(random);
1884 geometry.fRect = GrTest::TestRect(random); 1153 geometry.fRect = GrTest::TestRect(random);
1885 geometry.fStrokeWidth = random->nextBool() ? 0.0f : 1.0f; 1154 geometry.fStrokeWidth = random->nextBool() ? 0.0f : 1.0f;
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1992 geometry.fColor = GrRandomColor(random); 1261 geometry.fColor = GrRandomColor(random);
1993 return DrawVerticesBatch::Create(geometry, type, viewMatrix, 1262 return DrawVerticesBatch::Create(geometry, type, viewMatrix,
1994 positions.begin(), vertexCount, 1263 positions.begin(), vertexCount,
1995 indices.begin(), hasIndices ? vertexCount : 0, 1264 indices.begin(), hasIndices ? vertexCount : 0,
1996 colors.begin(), 1265 colors.begin(),
1997 texCoords.begin(), 1266 texCoords.begin(),
1998 bounds); 1267 bounds);
1999 } 1268 }
2000 1269
2001 #endif 1270 #endif
1271
OLDNEW
« no previous file with comments | « src/gpu/GrDefaultPathRenderer.cpp ('k') | src/gpu/GrDrawTarget.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698