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

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

Powered by Google App Engine
This is Rietveld 408576698