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

Side by Side Diff: src/gpu/GrContext.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: Address code review comments 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
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 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" 9 #include "GrContext.h"
10 10
11 #include "GrAARectRenderer.h" 11 #include "GrAARectRenderer.h"
12 #include "GrAtlasTextContext.h" 12 #include "GrAtlasTextContext.h"
13 #include "GrBatch.h" 13 #include "GrBatch.h"
14 #include "GrBatchFontCache.h" 14 #include "GrBatchFontCache.h"
15 #include "GrBatchTarget.h" 15 #include "GrBatchTarget.h"
16 #include "GrBatchTest.h" 16 #include "GrDrawContext.h"
17 #include "GrDefaultGeoProcFactory.h"
18 #include "GrGpuResource.h" 17 #include "GrGpuResource.h"
19 #include "GrGpuResourcePriv.h" 18 #include "GrGpuResourcePriv.h"
20 #include "GrDrawTargetCaps.h" 19 #include "GrDrawTargetCaps.h"
21 #include "GrGpu.h" 20 #include "GrGpu.h"
22 #include "GrImmediateDrawTarget.h" 21 #include "GrImmediateDrawTarget.h"
23 #include "GrIndexBuffer.h" 22 #include "GrIndexBuffer.h"
24 #include "GrInOrderDrawBuffer.h" 23 #include "GrInOrderDrawBuffer.h"
25 #include "GrLayerCache.h" 24 #include "GrLayerCache.h"
26 #include "GrOvalRenderer.h" 25 #include "GrOvalRenderer.h"
27 #include "GrPathRenderer.h" 26 #include "GrPathRenderer.h"
(...skipping 17 matching lines...) Expand all
45 #include "SkStrokeRec.h" 44 #include "SkStrokeRec.h"
46 #include "SkTLazy.h" 45 #include "SkTLazy.h"
47 #include "SkTLS.h" 46 #include "SkTLS.h"
48 #include "SkTraceEvent.h" 47 #include "SkTraceEvent.h"
49 48
50 #include "effects/GrConfigConversionEffect.h" 49 #include "effects/GrConfigConversionEffect.h"
51 #include "effects/GrDashingEffect.h" 50 #include "effects/GrDashingEffect.h"
52 #include "effects/GrSingleTextureEffect.h" 51 #include "effects/GrSingleTextureEffect.h"
53 52
54 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this) 53 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
55 #define RETURN_IF_ABANDONED if (!fDrawBuffer) { return; } 54 #define RETURN_IF_ABANDONED if (fDrawingMgr.abandoned()) { return; }
56 #define RETURN_FALSE_IF_ABANDONED if (!fDrawBuffer) { return false; } 55 #define RETURN_FALSE_IF_ABANDONED if (fDrawingMgr.abandoned()) { return false; }
57 #define RETURN_NULL_IF_ABANDONED if (!fDrawBuffer) { return NULL; } 56 #define RETURN_NULL_IF_ABANDONED if (fDrawingMgr.abandoned()) { return NULL; }
58 57
59 class GrContext::AutoCheckFlush {
60 public:
61 AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); }
62 58
63 ~AutoCheckFlush() { 59 ////////////////////////////////////////////////////////////////////////////////
64 if (fContext->fFlushToReduceCacheSize) { 60
65 fContext->flush(); 61 void GrContext::DrawingMgr::init(GrContext* context) {
66 } 62 #ifdef IMMEDIATE_MODE
63 fDrawTarget = SkNEW_ARGS(GrImmediateDrawTarget, (context));
64 #else
65 fDrawTarget = SkNEW_ARGS(GrInOrderDrawBuffer, (context));
66 #endif
67
68 fDrawContext = SkNEW_ARGS(GrDrawContext, (context, fDrawTarget));
69 }
70
71 GrContext::DrawingMgr::~DrawingMgr() {
72 SkSafeUnref(fDrawTarget);
73 SkSafeUnref(fDrawContext);
74 }
75
76 void GrContext::DrawingMgr::abandon() {
77 SkSafeSetNull(fDrawTarget);
78 fDrawContext->fDrawTarget.reset(NULL);
79 SkSafeSetNull(fDrawContext);
80 }
81
82 void GrContext::DrawingMgr::purgeResources() {
83 if (fDrawTarget) {
84 fDrawTarget->purgeResources();
67 } 85 }
86 }
68 87
69 private: 88 void GrContext::DrawingMgr::reset() {
70 GrContext* fContext; 89 if (fDrawTarget) {
71 }; 90 fDrawTarget->reset();
91 }
92 }
93
94 void GrContext::DrawingMgr::flush() {
95 if (fDrawTarget) {
96 fDrawTarget->flush();
97 }
98 }
99
100 GrDrawContext* GrContext::DrawingMgr::drawContext() {
101 if (this->abandoned()) {
102 return NULL;
103 }
104 return fDrawContext;
105 }
106
107 ////////////////////////////////////////////////////////////////////////////////
108
72 109
73 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext, 110 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
74 const Options* opts) { 111 const Options* opts) {
75 GrContext* context; 112 GrContext* context;
76 if (NULL == opts) { 113 if (!opts) {
77 context = SkNEW_ARGS(GrContext, (Options())); 114 context = SkNEW_ARGS(GrContext, (Options()));
78 } else { 115 } else {
79 context = SkNEW_ARGS(GrContext, (*opts)); 116 context = SkNEW_ARGS(GrContext, (*opts));
80 } 117 }
81 118
82 if (context->init(backend, backendContext)) { 119 if (context->init(backend, backendContext)) {
83 return context; 120 return context;
84 } else { 121 } else {
85 context->unref(); 122 context->unref();
86 return NULL; 123 return NULL;
87 } 124 }
88 } 125 }
89 126
90 static int32_t gNextID = 1; 127 static int32_t gNextID = 1;
91 static int32_t next_id() { 128 static int32_t next_id() {
92 int32_t id; 129 int32_t id;
93 do { 130 do {
94 id = sk_atomic_inc(&gNextID); 131 id = sk_atomic_inc(&gNextID);
95 } while (id == SK_InvalidGenID); 132 } while (id == SK_InvalidGenID);
96 return id; 133 return id;
97 } 134 }
98 135
99 GrContext::GrContext(const Options& opts) : fOptions(opts), fUniqueID(next_id()) { 136 GrContext::GrContext(const Options& opts) : fOptions(opts), fUniqueID(next_id()) {
100 fGpu = NULL; 137 fGpu = NULL;
101 fResourceCache = NULL; 138 fResourceCache = NULL;
102 fResourceProvider = NULL; 139 fResourceProvider = NULL;
103 fPathRendererChain = NULL; 140 fPathRendererChain = NULL;
104 fSoftwarePathRenderer = NULL; 141 fSoftwarePathRenderer = NULL;
105 fBatchFontCache = NULL; 142 fBatchFontCache = NULL;
106 fDrawBuffer = NULL;
107 fFlushToReduceCacheSize = false; 143 fFlushToReduceCacheSize = false;
108 fAARectRenderer = NULL;
109 fOvalRenderer = NULL;
110 fMaxTextureSizeOverride = 1 << 20; 144 fMaxTextureSizeOverride = 1 << 20;
111 } 145 }
112 146
113 bool GrContext::init(GrBackend backend, GrBackendContext backendContext) { 147 bool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
114 SkASSERT(NULL == fGpu); 148 SkASSERT(!fGpu);
115 149
116 fGpu = GrGpu::Create(backend, backendContext, this); 150 fGpu = GrGpu::Create(backend, backendContext, this);
117 if (NULL == fGpu) { 151 if (!fGpu) {
118 return false; 152 return false;
119 } 153 }
120 this->initCommon(); 154 this->initCommon();
121 return true; 155 return true;
122 } 156 }
123 157
124 void GrContext::initCommon() { 158 void GrContext::initCommon() {
125 fResourceCache = SkNEW(GrResourceCache); 159 fResourceCache = SkNEW(GrResourceCache);
126 fResourceCache->setOverBudgetCallback(OverBudgetCB, this); 160 fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
127 fResourceProvider = SkNEW_ARGS(GrResourceProvider, (fGpu, fResourceCache)); 161 fResourceProvider = SkNEW_ARGS(GrResourceProvider, (fGpu, fResourceCache));
128 162
129 fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this))); 163 fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
130 164
131 fAARectRenderer = SkNEW(GrAARectRenderer);
132 fOvalRenderer = SkNEW(GrOvalRenderer);
133
134 fDidTestPMConversions = false; 165 fDidTestPMConversions = false;
135 166
136 #ifdef IMMEDIATE_MODE 167 fDrawingMgr.init(this);
137 fDrawBuffer = SkNEW_ARGS(GrImmediateDrawTarget, (this));
138 #else
139 fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (this));
140 #endif
141 168
142 // GrBatchFontCache will eventually replace GrFontCache 169 // GrBatchFontCache will eventually replace GrFontCache
143 fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this)); 170 fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this));
144 171
145 fTextBlobCache.reset(SkNEW_ARGS(GrTextBlobCache, (TextBlobCacheOverBudgetCB, this))); 172 fTextBlobCache.reset(SkNEW_ARGS(GrTextBlobCache, (TextBlobCacheOverBudgetCB, this)));
146 } 173 }
147 174
148 GrContext::~GrContext() { 175 GrContext::~GrContext() {
149 if (NULL == fGpu) { 176 if (!fGpu) {
150 return; 177 return;
151 } 178 }
152 179
153 this->flush(); 180 this->flush();
154 181
155 for (int i = 0; i < fCleanUpData.count(); ++i) { 182 for (int i = 0; i < fCleanUpData.count(); ++i) {
156 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo); 183 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
157 } 184 }
158 185
159 SkDELETE(fResourceProvider); 186 SkDELETE(fResourceProvider);
160 SkDELETE(fResourceCache); 187 SkDELETE(fResourceCache);
161 SkDELETE(fBatchFontCache); 188 SkDELETE(fBatchFontCache);
162 SkDELETE(fDrawBuffer);
163
164 fAARectRenderer->unref();
165 fOvalRenderer->unref();
166 189
167 fGpu->unref(); 190 fGpu->unref();
168 SkSafeUnref(fPathRendererChain); 191 SkSafeUnref(fPathRendererChain);
169 SkSafeUnref(fSoftwarePathRenderer); 192 SkSafeUnref(fSoftwarePathRenderer);
170 } 193 }
171 194
172 void GrContext::abandonContext() { 195 void GrContext::abandonContext() {
173 fResourceProvider->abandon(); 196 fResourceProvider->abandon();
174 // abandon first to so destructors 197 // abandon first to so destructors
175 // don't try to free the resources in the API. 198 // don't try to free the resources in the API.
176 fResourceCache->abandonAll(); 199 fResourceCache->abandonAll();
177 200
178 fGpu->contextAbandoned(); 201 fGpu->contextAbandoned();
179 202
180 // a path renderer may be holding onto resources that 203 // a path renderer may be holding onto resources that
181 // are now unusable 204 // are now unusable
182 SkSafeSetNull(fPathRendererChain); 205 SkSafeSetNull(fPathRendererChain);
183 SkSafeSetNull(fSoftwarePathRenderer); 206 SkSafeSetNull(fSoftwarePathRenderer);
184 207
185 SkDELETE(fDrawBuffer); 208 fDrawingMgr.abandon();
186 fDrawBuffer = NULL;
187 209
188 fBatchFontCache->freeAll(); 210 fBatchFontCache->freeAll();
189 fLayerCache->freeAll(); 211 fLayerCache->freeAll();
190 fTextBlobCache->freeAll(); 212 fTextBlobCache->freeAll();
191 } 213 }
192 214
193 void GrContext::resetContext(uint32_t state) { 215 void GrContext::resetContext(uint32_t state) {
194 fGpu->markContextDirty(state); 216 fGpu->markContextDirty(state);
195 } 217 }
196 218
197 void GrContext::freeGpuResources() { 219 void GrContext::freeGpuResources() {
198 this->flush(); 220 this->flush();
199 221
200 if (fDrawBuffer) { 222 fDrawingMgr.purgeResources();
201 fDrawBuffer->purgeResources();
202 }
203 223
204 fBatchFontCache->freeAll(); 224 fBatchFontCache->freeAll();
205 fLayerCache->freeAll(); 225 fLayerCache->freeAll();
206 // a path renderer may be holding onto resources 226 // a path renderer may be holding onto resources
207 SkSafeSetNull(fPathRendererChain); 227 SkSafeSetNull(fPathRendererChain);
208 SkSafeSetNull(fSoftwarePathRenderer); 228 SkSafeSetNull(fSoftwarePathRenderer);
209 229
210 fResourceCache->purgeAllUnlocked(); 230 fResourceCache->purgeAllUnlocked();
211 } 231 }
212 232
(...skipping 16 matching lines...) Expand all
229 if (sb) { 249 if (sb) {
230 return GrStencilAndCoverTextContext::Create(this, gpuDevice, leakyPr operties); 250 return GrStencilAndCoverTextContext::Create(this, gpuDevice, leakyPr operties);
231 } 251 }
232 } 252 }
233 253
234 return GrAtlasTextContext::Create(this, gpuDevice, leakyProperties, enableDi stanceFieldFonts); 254 return GrAtlasTextContext::Create(this, gpuDevice, leakyProperties, enableDi stanceFieldFonts);
235 } 255 }
236 256
237 //////////////////////////////////////////////////////////////////////////////// 257 ////////////////////////////////////////////////////////////////////////////////
238 258
259 bool GrContext::shaderDerivativeSupport() const {
260 return fGpu->caps()->shaderCaps()->shaderDerivativeSupport();
261 }
262
239 bool GrContext::isConfigTexturable(GrPixelConfig config) const { 263 bool GrContext::isConfigTexturable(GrPixelConfig config) const {
240 return fGpu->caps()->isConfigTexturable(config); 264 return fGpu->caps()->isConfigTexturable(config);
241 } 265 }
242 266
243 bool GrContext::npotTextureTileSupport() const { 267 bool GrContext::npotTextureTileSupport() const {
244 return fGpu->caps()->npotTextureTileSupport(); 268 return fGpu->caps()->npotTextureTileSupport();
245 } 269 }
246 270
247 void GrContext::OverBudgetCB(void* data) { 271 void GrContext::OverBudgetCB(void* data) {
248 SkASSERT(data); 272 SkASSERT(data);
(...skipping 20 matching lines...) Expand all
269 } 293 }
270 294
271 int GrContext::getMaxRenderTargetSize() const { 295 int GrContext::getMaxRenderTargetSize() const {
272 return fGpu->caps()->maxRenderTargetSize(); 296 return fGpu->caps()->maxRenderTargetSize();
273 } 297 }
274 298
275 int GrContext::getMaxSampleCount() const { 299 int GrContext::getMaxSampleCount() const {
276 return fGpu->caps()->maxSampleCount(); 300 return fGpu->caps()->maxSampleCount();
277 } 301 }
278 302
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
303 // set rect to be big enough to fill the space, but not super-huge, so we
304 // don't overflow fixed-point implementations
305 SkRect r;
306 r.setLTRB(0, 0,
307 SkIntToScalar(rt->width()),
308 SkIntToScalar(rt->height()));
309 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
310
311 // by definition this fills the entire clip, no need for AA
312 if (paint->isAntiAlias()) {
313 paint.writable()->setAntiAlias(false);
314 }
315
316 bool isPerspective = viewMatrix.hasPerspective();
317
318 // We attempt to map r by the inverse matrix and draw that. mapRect will
319 // map the four corners and bound them with a new rect. This will not
320 // produce a correct result for some perspective matrices.
321 if (!isPerspective) {
322 SkMatrix inverse;
323 if (!viewMatrix.invert(&inverse)) {
324 SkDebugf("Could not invert matrix\n");
325 return;
326 }
327 inverse.mapRect(&r);
328 this->drawRect(rt, clip, *paint, viewMatrix, r);
329 } else {
330 SkMatrix localMatrix;
331 if (!viewMatrix.invert(&localMatrix)) {
332 SkDebugf("Could not invert matrix\n");
333 return;
334 }
335
336 AutoCheckFlush acf(this);
337 GrPipelineBuilder pipelineBuilder;
338 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, p aint, &acf);
339 if (NULL == target) {
340 return;
341 }
342
343 GR_CREATE_TRACE_MARKER("GrContext::drawPaintWithPerspective", target);
344 target->drawRect(&pipelineBuilder,
345 paint->getColor(),
346 SkMatrix::I(),
347 r,
348 NULL,
349 &localMatrix);
350 }
351 }
352
353 ////////////////////////////////////////////////////////////////////////////////
354
355 static inline bool is_irect(const SkRect& r) {
356 return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) &&
357 SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
358 }
359
360 static bool apply_aa_to_rect(GrDrawTarget* target,
361 GrPipelineBuilder* pipelineBuilder,
362 SkRect* devBoundRect,
363 const SkRect& rect,
364 SkScalar strokeWidth,
365 const SkMatrix& combinedMatrix,
366 GrColor color) {
367 if (pipelineBuilder->getRenderTarget()->isMultisampled()) {
368 return false;
369 }
370
371 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
372 if (strokeWidth >= 0) {
373 #endif
374 if (!combinedMatrix.preservesAxisAlignment()) {
375 return false;
376 }
377
378 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
379 } else {
380 if (!combinedMatrix.preservesRightAngles()) {
381 return false;
382 }
383 }
384 #endif
385
386 combinedMatrix.mapRect(devBoundRect, rect);
387 if (!combinedMatrix.rectStaysRect()) {
388 return true;
389 }
390
391 if (strokeWidth < 0) {
392 return !is_irect(*devBoundRect);
393 }
394
395 return true;
396 }
397
398 static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& po int) {
399 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
400 point.fY >= rect.fTop && point.fY <= rect.fBottom;
401 }
402
403 class StrokeRectBatch : public GrBatch {
404 public:
405 struct Geometry {
406 GrColor fColor;
407 SkMatrix fViewMatrix;
408 SkRect fRect;
409 SkScalar fStrokeWidth;
410 };
411
412 static GrBatch* Create(const Geometry& geometry, bool snapToPixelCenters) {
413 return SkNEW_ARGS(StrokeRectBatch, (geometry, snapToPixelCenters));
414 }
415
416 const char* name() const override { return "StrokeRectBatch"; }
417
418 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
419 // When this is called on a batch, there is only one geometry bundle
420 out->setKnownFourComponents(fGeoData[0].fColor);
421 }
422
423 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
424 out->setKnownSingleComponent(0xff);
425 }
426
427 void initBatchTracker(const GrPipelineInfo& init) override {
428 // Handle any color overrides
429 if (init.fColorIgnored) {
430 fGeoData[0].fColor = GrColor_ILLEGAL;
431 } else if (GrColor_ILLEGAL != init.fOverrideColor) {
432 fGeoData[0].fColor = init.fOverrideColor;
433 }
434
435 // setup batch properties
436 fBatch.fColorIgnored = init.fColorIgnored;
437 fBatch.fColor = fGeoData[0].fColor;
438 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
439 fBatch.fCoverageIgnored = init.fCoverageIgnored;
440 }
441
442 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override {
443 SkAutoTUnref<const GrGeometryProcessor> gp(
444 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPositi on_GPType,
445 this->color(),
446 this->usesLocalCoords(),
447 this->coverageIgnored(),
448 this->viewMatrix(),
449 SkMatrix::I()));
450
451 batchTarget->initDraw(gp, pipeline);
452
453 size_t vertexStride = gp->getVertexStride();
454
455 SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr));
456
457 Geometry& args = fGeoData[0];
458
459 int vertexCount = kVertsPerHairlineRect;
460 if (args.fStrokeWidth > 0) {
461 vertexCount = kVertsPerStrokeRect;
462 }
463
464 const GrVertexBuffer* vertexBuffer;
465 int firstVertex;
466
467 void* verts = batchTarget->makeVertSpace(vertexStride, vertexCount,
468 &vertexBuffer, &firstVertex);
469
470 if (!verts) {
471 SkDebugf("Could not allocate vertices\n");
472 return;
473 }
474
475 SkPoint* vertex = reinterpret_cast<SkPoint*>(verts);
476
477 GrPrimitiveType primType;
478
479 if (args.fStrokeWidth > 0) {;
480 primType = kTriangleStrip_GrPrimitiveType;
481 args.fRect.sort();
482 this->setStrokeRectStrip(vertex, args.fRect, args.fStrokeWidth);
483 } else {
484 // hairline
485 primType = kLineStrip_GrPrimitiveType;
486 vertex[0].set(args.fRect.fLeft, args.fRect.fTop);
487 vertex[1].set(args.fRect.fRight, args.fRect.fTop);
488 vertex[2].set(args.fRect.fRight, args.fRect.fBottom);
489 vertex[3].set(args.fRect.fLeft, args.fRect.fBottom);
490 vertex[4].set(args.fRect.fLeft, args.fRect.fTop);
491 }
492
493 GrVertices vertices;
494 vertices.init(primType, vertexBuffer, firstVertex, vertexCount);
495 batchTarget->draw(vertices);
496 }
497
498 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
499
500 private:
501 StrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters) {
502 this->initClassID<StrokeRectBatch>();
503
504 fBatch.fHairline = geometry.fStrokeWidth == 0;
505
506 fGeoData.push_back(geometry);
507
508 // setup bounds
509 fBounds = geometry.fRect;
510 SkScalar rad = SkScalarHalf(geometry.fStrokeWidth);
511 fBounds.outset(rad, rad);
512 geometry.fViewMatrix.mapRect(&fBounds);
513
514 // If our caller snaps to pixel centers then we have to round out the bo unds
515 if (snapToPixelCenters) {
516 fBounds.roundOut();
517 }
518 }
519
520 /* create a triangle strip that strokes the specified rect. There are 8
521 unique vertices, but we repeat the last 2 to close up. Alternatively we
522 could use an indices array, and then only send 8 verts, but not sure that
523 would be faster.
524 */
525 void setStrokeRectStrip(SkPoint verts[10], const SkRect& rect, SkScalar widt h) {
526 const SkScalar rad = SkScalarHalf(width);
527 // TODO we should be able to enable this assert, but we'd have to filter these draws
528 // this is a bug
529 //SkASSERT(rad < rect.width() / 2 && rad < rect.height() / 2);
530
531 verts[0].set(rect.fLeft + rad, rect.fTop + rad);
532 verts[1].set(rect.fLeft - rad, rect.fTop - rad);
533 verts[2].set(rect.fRight - rad, rect.fTop + rad);
534 verts[3].set(rect.fRight + rad, rect.fTop - rad);
535 verts[4].set(rect.fRight - rad, rect.fBottom - rad);
536 verts[5].set(rect.fRight + rad, rect.fBottom + rad);
537 verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
538 verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
539 verts[8] = verts[0];
540 verts[9] = verts[1];
541 }
542
543
544 GrColor color() const { return fBatch.fColor; }
545 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
546 bool colorIgnored() const { return fBatch.fColorIgnored; }
547 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
548 bool hairline() const { return fBatch.fHairline; }
549 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
550
551 bool onCombineIfPossible(GrBatch* t) override {
552 // StrokeRectBatch* that = t->cast<StrokeRectBatch>();
553
554 // NonAA stroke rects cannot batch right now
555 // TODO make these batchable
556 return false;
557 }
558
559 struct BatchTracker {
560 GrColor fColor;
561 bool fUsesLocalCoords;
562 bool fColorIgnored;
563 bool fCoverageIgnored;
564 bool fHairline;
565 };
566
567 const static int kVertsPerHairlineRect = 5;
568 const static int kVertsPerStrokeRect = 10;
569
570 BatchTracker fBatch;
571 SkSTArray<1, Geometry, true> fGeoData;
572 };
573
574 void GrContext::drawRect(GrRenderTarget* rt,
575 const GrClip& clip,
576 const GrPaint& paint,
577 const SkMatrix& viewMatrix,
578 const SkRect& rect,
579 const GrStrokeInfo* strokeInfo) {
580 RETURN_IF_ABANDONED
581 if (strokeInfo && strokeInfo->isDashed()) {
582 SkPath path;
583 path.setIsVolatile(true);
584 path.addRect(rect);
585 this->drawPath(rt, clip, paint, viewMatrix, path, *strokeInfo);
586 return;
587 }
588
589 AutoCheckFlush acf(this);
590 GrPipelineBuilder pipelineBuilder;
591 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf);
592 if (NULL == target) {
593 return;
594 }
595
596 GR_CREATE_TRACE_MARKER("GrContext::drawRect", target);
597 SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getWidth();
598
599 // 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.
601 if (width < 0) {
602 SkRect rtRect;
603 pipelineBuilder.getRenderTarget()->getBoundsRect(&rtRect);
604 SkRect clipSpaceRTRect = rtRect;
605 bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
606 if (checkClip) {
607 clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
608 SkIntToScalar(clip.origin().fY));
609 }
610 // Does the clip contain the entire RT?
611 if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
612 SkMatrix invM;
613 if (!viewMatrix.invert(&invM)) {
614 return;
615 }
616 // Does the rect bound the RT?
617 SkPoint srcSpaceRTQuad[4];
618 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
619 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
620 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
621 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
622 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
623 // Will it blend?
624 GrColor clearColor;
625 if (paint.isOpaqueAndConstantColor(&clearColor)) {
626 target->clear(NULL, clearColor, true, rt);
627 return;
628 }
629 }
630 }
631 }
632
633 GrColor color = paint.getColor();
634 SkRect devBoundRect;
635 bool needAA = paint.isAntiAlias() && !pipelineBuilder.getRenderTarget()->isM ultisampled();
636 bool doAA = needAA && apply_aa_to_rect(target, &pipelineBuilder, &devBoundRe ct, rect, width,
637 viewMatrix, color);
638
639 if (doAA) {
640 if (width >= 0) {
641 fAARectRenderer->strokeAARect(target,
642 &pipelineBuilder,
643 color,
644 viewMatrix,
645 rect,
646 devBoundRect,
647 *strokeInfo);
648 } else {
649 // filled AA rect
650 fAARectRenderer->fillAARect(target,
651 &pipelineBuilder,
652 color,
653 viewMatrix,
654 rect,
655 devBoundRect);
656 }
657 return;
658 }
659
660 if (width >= 0) {
661 StrokeRectBatch::Geometry geometry;
662 geometry.fViewMatrix = viewMatrix;
663 geometry.fColor = color;
664 geometry.fRect = rect;
665 geometry.fStrokeWidth = width;
666
667 // Non-AA hairlines are snapped to pixel centers to make which pixels ar e hit deterministic
668 bool snapToPixelCenters = (0 == width && !rt->isMultisampled());
669 SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry, snapToPixe lCenters));
670
671 // 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
673 // is enabled because it can cause ugly artifacts.
674 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_ Flag,
675 snapToPixelCenters);
676 target->drawBatch(&pipelineBuilder, batch);
677 } else {
678 // filled BW rect
679 target->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect);
680 }
681 }
682
683 void GrContext::drawNonAARectToRect(GrRenderTarget* rt,
684 const GrClip& clip,
685 const GrPaint& paint,
686 const SkMatrix& viewMatrix,
687 const SkRect& rectToDraw,
688 const SkRect& localRect,
689 const SkMatrix* localMatrix) {
690 RETURN_IF_ABANDONED
691 AutoCheckFlush acf(this);
692 GrPipelineBuilder pipelineBuilder;
693 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf);
694 if (NULL == target) {
695 return;
696 }
697
698 GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target);
699
700 target->drawRect(&pipelineBuilder,
701 paint.getColor(),
702 viewMatrix,
703 rectToDraw,
704 &localRect,
705 localMatrix);
706 }
707
708 static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords,
709 bool hasColors,
710 int* colorOffset,
711 int* texOffset,
712 GrColor color,
713 const SkMatrix& viewMatr ix,
714 bool coverageIgnored) {
715 *texOffset = -1;
716 *colorOffset = -1;
717 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
718 if (hasLocalCoords && hasColors) {
719 *colorOffset = sizeof(SkPoint);
720 *texOffset = sizeof(SkPoint) + sizeof(GrColor);
721 flags |= GrDefaultGeoProcFactory::kColor_GPType |
722 GrDefaultGeoProcFactory::kLocalCoord_GPType;
723 } else if (hasLocalCoords) {
724 *texOffset = sizeof(SkPoint);
725 flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType;
726 } else if (hasColors) {
727 *colorOffset = sizeof(SkPoint);
728 flags |= GrDefaultGeoProcFactory::kColor_GPType;
729 }
730 return GrDefaultGeoProcFactory::Create(flags, color, hasLocalCoords, coverag eIgnored,
731 viewMatrix, SkMatrix::I());
732 }
733
734 class DrawVerticesBatch : public GrBatch {
735 public:
736 struct Geometry {
737 GrColor fColor;
738 SkTDArray<SkPoint> fPositions;
739 SkTDArray<uint16_t> fIndices;
740 SkTDArray<GrColor> fColors;
741 SkTDArray<SkPoint> fLocalCoords;
742 };
743
744 static GrBatch* Create(const Geometry& geometry, GrPrimitiveType primitiveTy pe,
745 const SkMatrix& viewMatrix,
746 const SkPoint* positions, int vertexCount,
747 const uint16_t* indices, int indexCount,
748 const GrColor* colors, const SkPoint* localCoords,
749 const SkRect& bounds) {
750 return SkNEW_ARGS(DrawVerticesBatch, (geometry, primitiveType, viewMatri x, positions,
751 vertexCount, indices, indexCount, colors,
752 localCoords, bounds));
753 }
754
755 const char* name() const override { return "DrawVerticesBatch"; }
756
757 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
758 // When this is called on a batch, there is only one geometry bundle
759 if (this->hasColors()) {
760 out->setUnknownFourComponents();
761 } else {
762 out->setKnownFourComponents(fGeoData[0].fColor);
763 }
764 }
765
766 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
767 out->setKnownSingleComponent(0xff);
768 }
769
770 void initBatchTracker(const GrPipelineInfo& init) override {
771 // Handle any color overrides
772 if (init.fColorIgnored) {
773 fGeoData[0].fColor = GrColor_ILLEGAL;
774 } else if (GrColor_ILLEGAL != init.fOverrideColor) {
775 fGeoData[0].fColor = init.fOverrideColor;
776 }
777
778 // setup batch properties
779 fBatch.fColorIgnored = init.fColorIgnored;
780 fBatch.fColor = fGeoData[0].fColor;
781 fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
782 fBatch.fCoverageIgnored = init.fCoverageIgnored;
783 }
784
785 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override {
786 int colorOffset = -1, texOffset = -1;
787 SkAutoTUnref<const GrGeometryProcessor> gp(
788 set_vertex_attributes(this->hasLocalCoords(), this->hasColors(), &colorOffset,
789 &texOffset, this->color(), this->viewMatri x(),
790 this->coverageIgnored()));
791
792 batchTarget->initDraw(gp, pipeline);
793
794 size_t vertexStride = gp->getVertexStride();
795
796 SkASSERT(vertexStride == sizeof(SkPoint) + (this->hasLocalCoords() ? siz eof(SkPoint) : 0)
797 + (this->hasColors() ? sizeof(G rColor) : 0));
798
799 int instanceCount = fGeoData.count();
800
801 const GrVertexBuffer* vertexBuffer;
802 int firstVertex;
803
804 void* verts = batchTarget->makeVertSpace(vertexStride, this->vertexCount (),
805 &vertexBuffer, &firstVertex);
806
807 if (!verts) {
808 SkDebugf("Could not allocate vertices\n");
809 return;
810 }
811
812 const GrIndexBuffer* indexBuffer = NULL;
813 int firstIndex = 0;
814
815 uint16_t* indices = NULL;
816 if (this->hasIndices()) {
817 indices = batchTarget->makeIndexSpace(this->indexCount(), &indexBuff er, &firstIndex);
818
819 if (!indices) {
820 SkDebugf("Could not allocate indices\n");
821 return;
822 }
823 }
824
825 int indexOffset = 0;
826 int vertexOffset = 0;
827 for (int i = 0; i < instanceCount; i++) {
828 const Geometry& args = fGeoData[i];
829
830 // TODO we can actually cache this interleaved and then just memcopy
831 if (this->hasIndices()) {
832 for (int j = 0; j < args.fIndices.count(); ++j, ++indexOffset) {
833 *(indices + indexOffset) = args.fIndices[j] + vertexOffset;
834 }
835 }
836
837 for (int j = 0; j < args.fPositions.count(); ++j) {
838 *((SkPoint*)verts) = args.fPositions[j];
839 if (this->hasColors()) {
840 *(GrColor*)((intptr_t)verts + colorOffset) = args.fColors[j] ;
841 }
842 if (this->hasLocalCoords()) {
843 *(SkPoint*)((intptr_t)verts + texOffset) = args.fLocalCoords [j];
844 }
845 verts = (void*)((intptr_t)verts + vertexStride);
846 vertexOffset++;
847 }
848 }
849
850 GrVertices vertices;
851 if (this->hasIndices()) {
852 vertices.initIndexed(this->primitiveType(), vertexBuffer, indexBuffe r, firstVertex,
853 firstIndex, this->vertexCount(), this->indexCou nt());
854
855 } else {
856 vertices.init(this->primitiveType(), vertexBuffer, firstVertex, this ->vertexCount());
857 }
858 batchTarget->draw(vertices);
859 }
860
861 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
862
863 private:
864 DrawVerticesBatch(const Geometry& geometry, GrPrimitiveType primitiveType,
865 const SkMatrix& viewMatrix,
866 const SkPoint* positions, int vertexCount,
867 const uint16_t* indices, int indexCount,
868 const GrColor* colors, const SkPoint* localCoords, const S kRect& bounds) {
869 this->initClassID<DrawVerticesBatch>();
870 SkASSERT(positions);
871
872 fBatch.fViewMatrix = viewMatrix;
873 Geometry& installedGeo = fGeoData.push_back(geometry);
874
875 installedGeo.fPositions.append(vertexCount, positions);
876 if (indices) {
877 installedGeo.fIndices.append(indexCount, indices);
878 fBatch.fHasIndices = true;
879 } else {
880 fBatch.fHasIndices = false;
881 }
882
883 if (colors) {
884 installedGeo.fColors.append(vertexCount, colors);
885 fBatch.fHasColors = true;
886 } else {
887 fBatch.fHasColors = false;
888 }
889
890 if (localCoords) {
891 installedGeo.fLocalCoords.append(vertexCount, localCoords);
892 fBatch.fHasLocalCoords = true;
893 } else {
894 fBatch.fHasLocalCoords = false;
895 }
896 fBatch.fVertexCount = vertexCount;
897 fBatch.fIndexCount = indexCount;
898 fBatch.fPrimitiveType = primitiveType;
899
900 this->setBounds(bounds);
901 }
902
903 GrPrimitiveType primitiveType() const { return fBatch.fPrimitiveType; }
904 bool batchablePrimitiveType() const {
905 return kTriangles_GrPrimitiveType == fBatch.fPrimitiveType ||
906 kLines_GrPrimitiveType == fBatch.fPrimitiveType ||
907 kPoints_GrPrimitiveType == fBatch.fPrimitiveType;
908 }
909 GrColor color() const { return fBatch.fColor; }
910 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
911 bool colorIgnored() const { return fBatch.fColorIgnored; }
912 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
913 bool hasColors() const { return fBatch.fHasColors; }
914 bool hasIndices() const { return fBatch.fHasIndices; }
915 bool hasLocalCoords() const { return fBatch.fHasLocalCoords; }
916 int vertexCount() const { return fBatch.fVertexCount; }
917 int indexCount() const { return fBatch.fIndexCount; }
918 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
919
920 bool onCombineIfPossible(GrBatch* t) override {
921 DrawVerticesBatch* that = t->cast<DrawVerticesBatch>();
922
923 if (!this->batchablePrimitiveType() || this->primitiveType() != that->pr imitiveType()) {
924 return false;
925 }
926
927 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
928
929 // We currently use a uniform viewmatrix for this batch
930 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
931 return false;
932 }
933
934 if (this->hasColors() != that->hasColors()) {
935 return false;
936 }
937
938 if (this->hasIndices() != that->hasIndices()) {
939 return false;
940 }
941
942 if (this->hasLocalCoords() != that->hasLocalCoords()) {
943 return false;
944 }
945
946 if (!this->hasColors() && this->color() != that->color()) {
947 return false;
948 }
949
950 if (this->color() != that->color()) {
951 fBatch.fColor = GrColor_ILLEGAL;
952 }
953 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
954 fBatch.fVertexCount += that->vertexCount();
955 fBatch.fIndexCount += that->indexCount();
956
957 this->joinBounds(that->bounds());
958 return true;
959 }
960
961 struct BatchTracker {
962 GrPrimitiveType fPrimitiveType;
963 SkMatrix fViewMatrix;
964 GrColor fColor;
965 bool fUsesLocalCoords;
966 bool fColorIgnored;
967 bool fCoverageIgnored;
968 bool fHasColors;
969 bool fHasIndices;
970 bool fHasLocalCoords;
971 int fVertexCount;
972 int fIndexCount;
973 };
974
975 BatchTracker fBatch;
976 SkSTArray<1, Geometry, true> fGeoData;
977 };
978
979 void GrContext::drawVertices(GrRenderTarget* rt,
980 const GrClip& clip,
981 const GrPaint& paint,
982 const SkMatrix& viewMatrix,
983 GrPrimitiveType primitiveType,
984 int vertexCount,
985 const SkPoint positions[],
986 const SkPoint texCoords[],
987 const GrColor colors[],
988 const uint16_t indices[],
989 int indexCount) {
990 RETURN_IF_ABANDONED
991 AutoCheckFlush acf(this);
992 GrPipelineBuilder pipelineBuilder;
993
994 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf);
995 if (NULL == target) {
996 return;
997 }
998
999 GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target);
1000
1001 // TODO clients should give us bounds
1002 SkRect bounds;
1003 if (!bounds.setBoundsCheck(positions, vertexCount)) {
1004 SkDebugf("drawVertices call empty bounds\n");
1005 return;
1006 }
1007
1008 viewMatrix.mapRect(&bounds);
1009
1010 // If we don't have AA then we outset for a half pixel in each direction to account for
1011 // snapping
1012 if (!paint.isAntiAlias()) {
1013 bounds.outset(0.5f, 0.5f);
1014 }
1015
1016 DrawVerticesBatch::Geometry geometry;
1017 geometry.fColor = paint.getColor();
1018 SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveTyp e, viewMatrix,
1019 positions, vertexCount , indices,
1020 indexCount, colors, te xCoords,
1021 bounds));
1022
1023 target->drawBatch(&pipelineBuilder, batch);
1024 }
1025
1026 ///////////////////////////////////////////////////////////////////////////////
1027
1028 void GrContext::drawRRect(GrRenderTarget*rt,
1029 const GrClip& clip,
1030 const GrPaint& paint,
1031 const SkMatrix& viewMatrix,
1032 const SkRRect& rrect,
1033 const GrStrokeInfo& strokeInfo) {
1034 RETURN_IF_ABANDONED
1035 if (rrect.isEmpty()) {
1036 return;
1037 }
1038
1039 if (strokeInfo.isDashed()) {
1040 SkPath path;
1041 path.setIsVolatile(true);
1042 path.addRRect(rrect);
1043 this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo);
1044 return;
1045 }
1046
1047 AutoCheckFlush acf(this);
1048 GrPipelineBuilder pipelineBuilder;
1049 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf);
1050 if (NULL == target) {
1051 return;
1052 }
1053
1054 GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target);
1055
1056 GrColor color = paint.getColor();
1057 if (!fOvalRenderer->drawRRect(target,
1058 &pipelineBuilder,
1059 color,
1060 viewMatrix,
1061 paint.isAntiAlias(),
1062 rrect,
1063 strokeInfo)) {
1064 SkPath path;
1065 path.setIsVolatile(true);
1066 path.addRRect(rrect);
1067 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, pain t.isAntiAlias(),
1068 path, strokeInfo);
1069 }
1070 }
1071
1072 ///////////////////////////////////////////////////////////////////////////////
1073
1074 void GrContext::drawDRRect(GrRenderTarget* rt,
1075 const GrClip& clip,
1076 const GrPaint& paint,
1077 const SkMatrix& viewMatrix,
1078 const SkRRect& outer,
1079 const SkRRect& inner) {
1080 RETURN_IF_ABANDONED
1081 if (outer.isEmpty()) {
1082 return;
1083 }
1084
1085 AutoCheckFlush acf(this);
1086 GrPipelineBuilder pipelineBuilder;
1087 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf);
1088
1089 GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target);
1090
1091 GrColor color = paint.getColor();
1092 if (!fOvalRenderer->drawDRRect(target,
1093 &pipelineBuilder,
1094 color,
1095 viewMatrix,
1096 paint.isAntiAlias(),
1097 outer,
1098 inner)) {
1099 SkPath path;
1100 path.setIsVolatile(true);
1101 path.addRRect(inner);
1102 path.addRRect(outer);
1103 path.setFillType(SkPath::kEvenOdd_FillType);
1104 GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
1105 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, pain t.isAntiAlias(),
1106 path, fillRec);
1107 }
1108 }
1109
1110 ///////////////////////////////////////////////////////////////////////////////
1111
1112 void GrContext::drawOval(GrRenderTarget* rt,
1113 const GrClip& clip,
1114 const GrPaint& paint,
1115 const SkMatrix& viewMatrix,
1116 const SkRect& oval,
1117 const GrStrokeInfo& strokeInfo) {
1118 RETURN_IF_ABANDONED
1119 if (oval.isEmpty()) {
1120 return;
1121 }
1122
1123 if (strokeInfo.isDashed()) {
1124 SkPath path;
1125 path.setIsVolatile(true);
1126 path.addOval(oval);
1127 this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo);
1128 return;
1129 }
1130
1131 AutoCheckFlush acf(this);
1132 GrPipelineBuilder pipelineBuilder;
1133 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf);
1134 if (NULL == target) {
1135 return;
1136 }
1137
1138 GR_CREATE_TRACE_MARKER("GrContext::drawOval", target);
1139
1140 GrColor color = paint.getColor();
1141 if (!fOvalRenderer->drawOval(target,
1142 &pipelineBuilder,
1143 color,
1144 viewMatrix,
1145 paint.isAntiAlias(),
1146 oval,
1147 strokeInfo)) {
1148 SkPath path;
1149 path.setIsVolatile(true);
1150 path.addOval(oval);
1151 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, pain t.isAntiAlias(),
1152 path, strokeInfo);
1153 }
1154 }
1155
1156 // Can 'path' be drawn as a pair of filled nested rectangles?
1157 static bool is_nested_rects(GrDrawTarget* target,
1158 GrPipelineBuilder* pipelineBuilder,
1159 GrColor color,
1160 const SkMatrix& viewMatrix,
1161 const SkPath& path,
1162 const SkStrokeRec& stroke,
1163 SkRect rects[2]) {
1164 SkASSERT(stroke.isFillStyle());
1165
1166 if (path.isInverseFillType()) {
1167 return false;
1168 }
1169
1170 // TODO: this restriction could be lifted if we were willing to apply
1171 // the matrix to all the points individually rather than just to the rect
1172 if (!viewMatrix.preservesAxisAlignment()) {
1173 return false;
1174 }
1175
1176 SkPath::Direction dirs[2];
1177 if (!path.isNestedFillRects(rects, dirs)) {
1178 return false;
1179 }
1180
1181 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1182 // The two rects need to be wound opposite to each other
1183 return false;
1184 }
1185
1186 // Right now, nested rects where the margin is not the same width
1187 // all around do not render correctly
1188 const SkScalar* outer = rects[0].asScalars();
1189 const SkScalar* inner = rects[1].asScalars();
1190
1191 bool allEq = true;
1192
1193 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1194 bool allGoE1 = margin >= SK_Scalar1;
1195
1196 for (int i = 1; i < 4; ++i) {
1197 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1198 if (temp < SK_Scalar1) {
1199 allGoE1 = false;
1200 }
1201 if (!SkScalarNearlyEqual(margin, temp)) {
1202 allEq = false;
1203 }
1204 }
1205
1206 return allEq || allGoE1;
1207 }
1208
1209 void GrContext::drawPath(GrRenderTarget* rt,
1210 const GrClip& clip,
1211 const GrPaint& paint,
1212 const SkMatrix& viewMatrix,
1213 const SkPath& path,
1214 const GrStrokeInfo& strokeInfo) {
1215 RETURN_IF_ABANDONED
1216 if (path.isEmpty()) {
1217 if (path.isInverseFillType()) {
1218 this->drawPaint(rt, clip, paint, viewMatrix);
1219 }
1220 return;
1221 }
1222
1223 GrColor color = paint.getColor();
1224
1225 // 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
1227 // 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
1229 // OK.
1230 AutoCheckFlush acf(this);
1231 GrPipelineBuilder pipelineBuilder;
1232 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &pain t, &acf);
1233 if (NULL == target) {
1234 return;
1235 }
1236
1237 GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isC onvex());
1238
1239 if (!strokeInfo.isDashed()) {
1240 bool useCoverageAA = paint.isAntiAlias() &&
1241 !pipelineBuilder.getRenderTarget()->isMultisampled();
1242
1243 if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) {
1244 // Concave AA paths are expensive - try to avoid them for special ca ses
1245 SkRect rects[2];
1246
1247 if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, pat h, strokeInfo,
1248 rects)) {
1249 fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, col or, viewMatrix,
1250 rects);
1251 return;
1252 }
1253 }
1254 SkRect ovalRect;
1255 bool isOval = path.isOval(&ovalRect);
1256
1257 if (isOval && !path.isInverseFillType()) {
1258 if (fOvalRenderer->drawOval(target,
1259 &pipelineBuilder,
1260 color,
1261 viewMatrix,
1262 paint.isAntiAlias(),
1263 ovalRect,
1264 strokeInfo)) {
1265 return;
1266 }
1267 }
1268 }
1269 this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.is AntiAlias(),
1270 path, strokeInfo);
1271 }
1272
1273 void GrContext::internalDrawPath(GrDrawTarget* target,
1274 GrPipelineBuilder* pipelineBuilder,
1275 const SkMatrix& viewMatrix,
1276 GrColor color,
1277 bool useAA,
1278 const SkPath& path,
1279 const GrStrokeInfo& strokeInfo) {
1280 RETURN_IF_ABANDONED
1281 SkASSERT(!path.isEmpty());
1282
1283 GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target);
1284
1285
1286 // 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
1288 // 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.
1290 bool useCoverageAA = useAA &&
1291 !pipelineBuilder->getRenderTarget()->isMultisampled();
1292
1293
1294 GrPathRendererChain::DrawType type =
1295 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
1296 GrPathRendererChain::kColor_DrawType;
1297
1298 const SkPath* pathPtr = &path;
1299 SkTLazy<SkPath> tmpPath;
1300 const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
1301
1302 // 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,
1304 *strokeInfoPtr, false, type);
1305
1306 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
1307 if (NULL == pr && strokeInfo.isDashed()) {
1308 // 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)) {
1310 return;
1311 }
1312 pathPtr = tmpPath.get();
1313 if (pathPtr->isEmpty()) {
1314 return;
1315 }
1316 strokeInfoPtr = &dashlessStrokeInfo;
1317 pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr , *strokeInfoPtr,
1318 false, type);
1319 }
1320
1321 if (NULL == pr) {
1322 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMa trix, NULL) &&
1323 !strokeInfoPtr->isFillStyle()) {
1324 // It didn't work above, so try again with stroke converted to a fil l.
1325 if (!tmpPath.isValid()) {
1326 tmpPath.init();
1327 }
1328 dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()) );
1329 if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) {
1330 return;
1331 }
1332 pathPtr = tmpPath.get();
1333 if (pathPtr->isEmpty()) {
1334 return;
1335 }
1336 dashlessStrokeInfo.setFillStyle();
1337 strokeInfoPtr = &dashlessStrokeInfo;
1338 }
1339
1340 // This time, allow SW renderer
1341 pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr , *strokeInfoPtr,
1342 true, type);
1343 }
1344
1345 if (NULL == pr) {
1346 #ifdef SK_DEBUG
1347 SkDebugf("Unable to find path renderer compatible with path.\n");
1348 #endif
1349 return;
1350 }
1351
1352 pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeIn foPtr, useCoverageAA);
1353 }
1354
1355 //////////////////////////////////////////////////////////////////////////////// 303 ////////////////////////////////////////////////////////////////////////////////
1356 304
1357 void GrContext::flush(int flagsBitfield) { 305 void GrContext::flush(int flagsBitfield) {
1358 if (NULL == fDrawBuffer) { 306 RETURN_IF_ABANDONED
1359 return;
1360 }
1361 307
1362 if (kDiscard_FlushBit & flagsBitfield) { 308 if (kDiscard_FlushBit & flagsBitfield) {
1363 fDrawBuffer->reset(); 309 fDrawingMgr.reset();
1364 } else { 310 } else {
1365 fDrawBuffer->flush(); 311 fDrawingMgr.flush();
1366 } 312 }
1367 fResourceCache->notifyFlushOccurred(); 313 fResourceCache->notifyFlushOccurred();
1368 fFlushToReduceCacheSize = false; 314 fFlushToReduceCacheSize = false;
1369 } 315 }
1370 316
1371 bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes, 317 bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
1372 const void* inPixels, size_t outRowBytes, void* outPix els) { 318 const void* inPixels, size_t outRowBytes, void* outPix els) {
1373 SkSrcPixelInfo srcPI; 319 SkSrcPixelInfo srcPI;
1374 if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, NULL)) { 320 if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, NULL)) {
1375 return false; 321 return false;
(...skipping 27 matching lines...) Expand all
1403 } 349 }
1404 return fGpu->writeTexturePixels(texture, left, top, width, height, 350 return fGpu->writeTexturePixels(texture, left, top, width, height,
1405 srcConfig, buffer, rowBytes); 351 srcConfig, buffer, rowBytes);
1406 // Don't need to check kFlushWrites_PixelOp here, we just did a dire ct write so the 352 // Don't need to check kFlushWrites_PixelOp here, we just did a dire ct write so the
1407 // upload is already flushed. 353 // upload is already flushed.
1408 } 354 }
1409 } 355 }
1410 356
1411 // If we didn't do a direct texture write then we upload the pixels to a tex ture and draw. 357 // 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(); 358 GrRenderTarget* renderTarget = surface->asRenderTarget();
1413 if (NULL == renderTarget) { 359 if (!renderTarget) {
1414 return false; 360 return false;
1415 } 361 }
1416 362
1417 // We ignore the preferred config unless it is a R/B swap of the src config. In that case 363 // 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 364 // 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 365 // 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. 366 // when drawing the scratch to the dst using a conversion effect.
1421 bool swapRAndB = false; 367 bool swapRAndB = false;
1422 GrPixelConfig writeConfig = srcConfig; 368 GrPixelConfig writeConfig = srcConfig;
1423 if (GrPixelConfigSwapRAndB(srcConfig) == 369 if (GrPixelConfigSwapRAndB(srcConfig) ==
(...skipping 18 matching lines...) Expand all
1442 388
1443 // allocate a tmp buffer and sw convert the pixels to premul 389 // allocate a tmp buffer and sw convert the pixels to premul
1444 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); 390 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1445 391
1446 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) { 392 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
1447 if (!GrPixelConfigIs8888(srcConfig)) { 393 if (!GrPixelConfigIs8888(srcConfig)) {
1448 return false; 394 return false;
1449 } 395 }
1450 fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix)); 396 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. 397 // handle the unpremul step on the CPU if we couldn't create an effect t o do it.
1452 if (NULL == fp) { 398 if (!fp) {
1453 size_t tmpRowBytes = 4 * width; 399 size_t tmpRowBytes = 4 * width;
1454 tmpPixels.reset(width * height); 400 tmpPixels.reset(width * height);
1455 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer , tmpRowBytes, 401 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer , tmpRowBytes,
1456 tmpPixels.get())) { 402 tmpPixels.get())) {
1457 return false; 403 return false;
1458 } 404 }
1459 rowBytes = tmpRowBytes; 405 rowBytes = tmpRowBytes;
1460 buffer = tmpPixels.get(); 406 buffer = tmpPixels.get();
1461 } 407 }
1462 } 408 }
1463 if (NULL == fp) { 409 if (!fp) {
1464 fp.reset(GrConfigConversionEffect::Create(texture, 410 fp.reset(GrConfigConversionEffect::Create(texture,
1465 swapRAndB, 411 swapRAndB,
1466 GrConfigConversionEffect::kNon e_PMConversion, 412 GrConfigConversionEffect::kNon e_PMConversion,
1467 textureMatrix)); 413 textureMatrix));
1468 } 414 }
1469 415
1470 // Even if the client told us not to flush, we still flush here. The client may have known that 416 // 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 417 // writes to the original surface caused no data hazards, but they can't kno w that the scratch
1472 // we just got is safe. 418 // we just got is safe.
1473 if (texture->surfacePriv().hasPendingIO()) { 419 if (texture->surfacePriv().hasPendingIO()) {
1474 this->flush(); 420 this->flush();
1475 } 421 }
1476 if (!fGpu->writeTexturePixels(texture, 0, 0, width, height, 422 if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
1477 writeConfig, buffer, rowBytes)) { 423 writeConfig, buffer, rowBytes)) {
1478 return false; 424 return false;
1479 } 425 }
1480 426
1481 SkMatrix matrix; 427 SkMatrix matrix;
1482 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); 428 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
1483 429
1484 // This function can be called in the midst of drawing another object (e.g., when uploading a 430 GrDrawContext* drawContext = this->drawContext();
1485 // SW-rasterized clip while issuing a draw). So we push the current geometry state before 431 if (!drawContext) {
1486 // drawing a rect to the render target. 432 return false;
1487 // The bracket ensures we pop the stack if we wind up flushing below. 433 }
1488 {
1489 GrDrawTarget* drawTarget = this->prepareToDraw();
1490 if (!drawTarget) {
1491 return false;
1492 }
1493 434
1494 GrPipelineBuilder pipelineBuilder; 435 GrPaint paint;
1495 pipelineBuilder.addColorProcessor(fp); 436 paint.addColorProcessor(fp);
1496 pipelineBuilder.setRenderTarget(renderTarget); 437
1497 drawTarget->drawSimpleRect(&pipelineBuilder, 438 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
1498 GrColor_WHITE, 439
1499 matrix, 440 drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL);
1500 SkRect::MakeWH(SkIntToScalar(width), SkIntToS calar(height)));
1501 }
1502 441
1503 if (kFlushWrites_PixelOp & pixelOpsFlags) { 442 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1504 this->flushSurfaceWrites(surface); 443 this->flushSurfaceWrites(surface);
1505 } 444 }
1506 445
1507 return true; 446 return true;
1508 } 447 }
1509 448
1510 // toggles between RGBA and BGRA 449 // toggles between RGBA and BGRA
1511 static SkColorType toggle_colortype32(SkColorType ct) { 450 static SkColorType toggle_colortype32(SkColorType ct) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1605 fp.reset(GrConfigConversionEffect::Create( 544 fp.reset(GrConfigConversionEffect::Create(
1606 src, swapRAndB, GrConfigConversionEffect::kNone_PMCo nversion, 545 src, swapRAndB, GrConfigConversionEffect::kNone_PMCo nversion,
1607 textureMatrix)); 546 textureMatrix));
1608 } 547 }
1609 swapRAndB = false; // we will handle the swap in the draw. 548 swapRAndB = false; // we will handle the swap in the draw.
1610 549
1611 // We protect the existing geometry here since it may not be 550 // We protect the existing geometry here since it may not be
1612 // clear to the caller that a draw operation (i.e., drawSimpleRe ct) 551 // clear to the caller that a draw operation (i.e., drawSimpleRe ct)
1613 // can be invoked in this method 552 // can be invoked in this method
1614 { 553 {
1615 GrPipelineBuilder pipelineBuilder; 554 GrDrawContext* drawContext = this->drawContext();
1616 SkASSERT(fp); 555 if (!drawContext) {
1617 pipelineBuilder.addColorProcessor(fp); 556 return false;
557 }
1618 558
1619 pipelineBuilder.setRenderTarget(tempTexture->asRenderTarget( )); 559 GrPaint paint;
560 paint.addColorProcessor(fp);
561
1620 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToSc alar(height)); 562 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToSc alar(height));
1621 fDrawBuffer->drawSimpleRect(&pipelineBuilder, 563
1622 GrColor_WHITE, 564 drawContext->drawRect(tempTexture->asRenderTarget(), GrClip: :WideOpen(), paint,
1623 SkMatrix::I(), 565 SkMatrix::I(), rect, NULL);
1624 rect); 566
1625 // we want to read back from the scratch's origin 567 // we want to read back from the scratch's origin
1626 left = 0; 568 left = 0;
1627 top = 0; 569 top = 0;
1628 target = tempTexture->asRenderTarget(); 570 target = tempTexture->asRenderTarget();
1629 } 571 }
1630 this->flushSurfaceWrites(target); 572 this->flushSurfaceWrites(target);
1631 } 573 }
1632 } 574 }
1633 } 575 }
1634 576
(...skipping 29 matching lines...) Expand all
1664 ASSERT_OWNED_RESOURCE(surface); 606 ASSERT_OWNED_RESOURCE(surface);
1665 if (surface->surfacePriv().hasPendingIO()) { 607 if (surface->surfacePriv().hasPendingIO()) {
1666 this->flush(); 608 this->flush();
1667 } 609 }
1668 GrRenderTarget* rt = surface->asRenderTarget(); 610 GrRenderTarget* rt = surface->asRenderTarget();
1669 if (fGpu && rt) { 611 if (fGpu && rt) {
1670 fGpu->resolveRenderTarget(rt); 612 fGpu->resolveRenderTarget(rt);
1671 } 613 }
1672 } 614 }
1673 615
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, 616 void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRe ct,
1687 const SkIPoint& dstPoint, uint32_t pixelOpsFlags) { 617 const SkIPoint& dstPoint, uint32_t pixelOpsFlags) {
1688 RETURN_IF_ABANDONED 618 RETURN_IF_ABANDONED
1689 if (NULL == src || NULL == dst) { 619 if (!src || !dst) {
1690 return; 620 return;
1691 } 621 }
1692 ASSERT_OWNED_RESOURCE(src); 622 ASSERT_OWNED_RESOURCE(src);
1693 ASSERT_OWNED_RESOURCE(dst); 623 ASSERT_OWNED_RESOURCE(dst);
1694 624
1695 // Since we're going to the draw target and not GPU, no need to check kNoFlu sh 625 // Since we're going to the draw target and not GPU, no need to check kNoFlu sh
1696 // here. 626 // here.
1697 627 if (!dst->asRenderTarget()) {
1698 GrDrawTarget* target = this->prepareToDraw();
1699 if (NULL == target) {
1700 return; 628 return;
1701 } 629 }
1702 target->copySurface(dst, src, srcRect, dstPoint); 630
631 GrDrawContext* drawContext = this->drawContext();
632 if (!drawContext) {
633 return;
634 }
635
636 drawContext->copySurface(dst->asRenderTarget(), src, srcRect, dstPoint);
1703 637
1704 if (kFlushWrites_PixelOp & pixelOpsFlags) { 638 if (kFlushWrites_PixelOp & pixelOpsFlags) {
1705 this->flush(); 639 this->flush();
1706 } 640 }
1707 } 641 }
1708 642
1709 void GrContext::flushSurfaceWrites(GrSurface* surface) { 643 void GrContext::flushSurfaceWrites(GrSurface* surface) {
1710 RETURN_IF_ABANDONED 644 RETURN_IF_ABANDONED
1711 if (surface->surfacePriv().hasPendingWrite()) { 645 if (surface->surfacePriv().hasPendingWrite()) {
1712 this->flush(); 646 this->flush();
1713 } 647 }
1714 } 648 }
1715 649
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 /* 650 /*
1739 * This method finds a path renderer that can draw the specified path on 651 * This method finds a path renderer that can draw the specified path on
1740 * the provided target. 652 * the provided target.
1741 * Due to its expense, the software path renderer has split out so it can 653 * Due to its expense, the software path renderer has split out so it can
1742 * can be individually allowed/disallowed via the "allowSW" boolean. 654 * can be individually allowed/disallowed via the "allowSW" boolean.
1743 */ 655 */
1744 GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, 656 GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
1745 const GrPipelineBuilder* pipelineBuil der, 657 const GrPipelineBuilder* pipelineBuil der,
1746 const SkMatrix& viewMatrix, 658 const SkMatrix& viewMatrix,
1747 const SkPath& path, 659 const SkPath& path,
1748 const GrStrokeInfo& stroke, 660 const GrStrokeInfo& stroke,
1749 bool allowSW, 661 bool allowSW,
1750 GrPathRendererChain::DrawType drawTyp e, 662 GrPathRendererChain::DrawType drawTyp e,
1751 GrPathRendererChain::StencilSupport* stencilSupport) { 663 GrPathRendererChain::StencilSupport* stencilSupport) {
1752 664
1753 if (NULL == fPathRendererChain) { 665 if (!fPathRendererChain) {
1754 fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this)); 666 fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
1755 } 667 }
1756 668
1757 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target, 669 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target,
1758 pipelineBuilder, 670 pipelineBuilder,
1759 viewMatrix, 671 viewMatrix,
1760 path, 672 path,
1761 stroke, 673 stroke,
1762 drawType, 674 drawType,
1763 stencilSupport); 675 stencilSupport);
1764 676
1765 if (NULL == pr && allowSW) { 677 if (!pr && allowSW) {
1766 if (NULL == fSoftwarePathRenderer) { 678 if (!fSoftwarePathRenderer) {
1767 fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this)); 679 fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
1768 } 680 }
1769 pr = fSoftwarePathRenderer; 681 pr = fSoftwarePathRenderer;
1770 } 682 }
1771 683
1772 return pr; 684 return pr;
1773 } 685 }
1774 686
1775 //////////////////////////////////////////////////////////////////////////////// 687 ////////////////////////////////////////////////////////////////////////////////
1776 bool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const { 688 bool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
(...skipping 10 matching lines...) Expand all
1787 if (dpi >= 250.0f) { 699 if (dpi >= 250.0f) {
1788 chosenSampleCount = 4; 700 chosenSampleCount = 4;
1789 } else { 701 } else {
1790 chosenSampleCount = 16; 702 chosenSampleCount = 16;
1791 } 703 }
1792 } 704 }
1793 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? 705 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ?
1794 chosenSampleCount : 0; 706 chosenSampleCount : 0;
1795 } 707 }
1796 708
1797 GrDrawTarget* GrContext::getTextTarget() {
1798 return this->prepareToDraw();
1799 }
1800
1801 namespace { 709 namespace {
1802 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) { 710 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
1803 GrConfigConversionEffect::PMConversion pmToUPM; 711 GrConfigConversionEffect::PMConversion pmToUPM;
1804 GrConfigConversionEffect::PMConversion upmToPM; 712 GrConfigConversionEffect::PMConversion upmToPM;
1805 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upm ToPM); 713 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upm ToPM);
1806 *pmToUPMValue = pmToUPM; 714 *pmToUPMValue = pmToUPM;
1807 *upmToPMValue = upmToPM; 715 *upmToPMValue = upmToPM;
1808 } 716 }
1809 } 717 }
1810 718
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 } 760 }
1853 761
1854 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { 762 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
1855 fResourceCache->setLimits(maxTextures, maxTextureBytes); 763 fResourceCache->setLimits(maxTextures, maxTextureBytes);
1856 } 764 }
1857 765
1858 ////////////////////////////////////////////////////////////////////////////// 766 //////////////////////////////////////////////////////////////////////////////
1859 767
1860 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { 768 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
1861 fGpu->addGpuTraceMarker(marker); 769 fGpu->addGpuTraceMarker(marker);
1862 if (fDrawBuffer) {
1863 fDrawBuffer->addGpuTraceMarker(marker);
1864 }
1865 } 770 }
1866 771
1867 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { 772 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
1868 fGpu->removeGpuTraceMarker(marker); 773 fGpu->removeGpuTraceMarker(marker);
1869 if (fDrawBuffer) {
1870 fDrawBuffer->removeGpuTraceMarker(marker);
1871 }
1872 } 774 }
1873 775
1874 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1875
1876 #ifdef GR_TEST_UTILS
1877
1878 BATCH_TEST_DEFINE(StrokeRectBatch) {
1879 StrokeRectBatch::Geometry geometry;
1880 geometry.fViewMatrix = GrTest::TestMatrix(random);
1881 geometry.fColor = GrRandomColor(random);
1882 geometry.fRect = GrTest::TestRect(random);
1883 geometry.fStrokeWidth = random->nextBool() ? 0.0f : 1.0f;
1884
1885 return StrokeRectBatch::Create(geometry, random->nextBool());
1886 }
1887
1888 static uint32_t seed_vertices(GrPrimitiveType type) {
1889 switch (type) {
1890 case kTriangles_GrPrimitiveType:
1891 case kTriangleStrip_GrPrimitiveType:
1892 case kTriangleFan_GrPrimitiveType:
1893 return 3;
1894 case kPoints_GrPrimitiveType:
1895 return 1;
1896 case kLines_GrPrimitiveType:
1897 case kLineStrip_GrPrimitiveType:
1898 return 2;
1899 }
1900 SkFAIL("Incomplete switch\n");
1901 return 0;
1902 }
1903
1904 static uint32_t primitive_vertices(GrPrimitiveType type) {
1905 switch (type) {
1906 case kTriangles_GrPrimitiveType:
1907 return 3;
1908 case kLines_GrPrimitiveType:
1909 return 2;
1910 case kTriangleStrip_GrPrimitiveType:
1911 case kTriangleFan_GrPrimitiveType:
1912 case kPoints_GrPrimitiveType:
1913 case kLineStrip_GrPrimitiveType:
1914 return 1;
1915 }
1916 SkFAIL("Incomplete switch\n");
1917 return 0;
1918 }
1919
1920 static SkPoint random_point(SkRandom* random, SkScalar min, SkScalar max) {
1921 SkPoint p;
1922 p.fX = random->nextRangeScalar(min, max);
1923 p.fY = random->nextRangeScalar(min, max);
1924 return p;
1925 }
1926
1927 static void randomize_params(size_t count, size_t maxVertex, SkScalar min, SkSca lar max,
1928 SkRandom* random,
1929 SkTArray<SkPoint>* positions,
1930 SkTArray<SkPoint>* texCoords, bool hasTexCoords,
1931 SkTArray<GrColor>* colors, bool hasColors,
1932 SkTArray<uint16_t>* indices, bool hasIndices) {
1933 for (uint32_t v = 0; v < count; v++) {
1934 positions->push_back(random_point(random, min, max));
1935 if (hasTexCoords) {
1936 texCoords->push_back(random_point(random, min, max));
1937 }
1938 if (hasColors) {
1939 colors->push_back(GrRandomColor(random));
1940 }
1941 if (hasIndices) {
1942 SkASSERT(maxVertex <= SK_MaxU16);
1943 indices->push_back(random->nextULessThan((uint16_t)maxVertex));
1944 }
1945 }
1946 }
1947
1948 BATCH_TEST_DEFINE(VerticesBatch) {
1949 GrPrimitiveType type = GrPrimitiveType(random->nextULessThan(kLast_GrPrimiti veType + 1));
1950 uint32_t primitiveCount = random->nextRangeU(1, 100);
1951
1952 // TODO make 'sensible' indexbuffers
1953 SkTArray<SkPoint> positions;
1954 SkTArray<SkPoint> texCoords;
1955 SkTArray<GrColor> colors;
1956 SkTArray<uint16_t> indices;
1957
1958 bool hasTexCoords = random->nextBool();
1959 bool hasIndices = random->nextBool();
1960 bool hasColors = random->nextBool();
1961
1962 uint32_t vertexCount = seed_vertices(type) + (primitiveCount - 1) * primitiv e_vertices(type);
1963
1964 static const SkScalar kMinVertExtent = -100.f;
1965 static const SkScalar kMaxVertExtent = 100.f;
1966 randomize_params(seed_vertices(type), vertexCount, kMinVertExtent, kMaxVertE xtent,
1967 random,
1968 &positions,
1969 &texCoords, hasTexCoords,
1970 &colors, hasColors,
1971 &indices, hasIndices);
1972
1973 for (uint32_t i = 1; i < primitiveCount; i++) {
1974 randomize_params(primitive_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
1975 random,
1976 &positions,
1977 &texCoords, hasTexCoords,
1978 &colors, hasColors,
1979 &indices, hasIndices);
1980 }
1981
1982 SkMatrix viewMatrix = GrTest::TestMatrix(random);
1983 SkRect bounds;
1984 SkDEBUGCODE(bool result = ) bounds.setBoundsCheck(positions.begin(), vertexC ount);
1985 SkASSERT(result);
1986
1987 viewMatrix.mapRect(&bounds);
1988
1989 DrawVerticesBatch::Geometry geometry;
1990 geometry.fColor = GrRandomColor(random);
1991 return DrawVerticesBatch::Create(geometry, type, viewMatrix,
1992 positions.begin(), vertexCount,
1993 indices.begin(), hasIndices ? vertexCount : 0,
1994 colors.begin(),
1995 texCoords.begin(),
1996 bounds);
1997 }
1998
1999 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698