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

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

Powered by Google App Engine
This is Rietveld 408576698