Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / SkGpuDevice.cpp
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkGpuDevice.h"
9
10 #include "effects/GrBicubicEffect.h"
11 #include "effects/GrDashingEffect.h"
12 #include "effects/GrTextureDomain.h"
13 #include "effects/GrSimpleTextureEffect.h"
14
15 #include "GrContext.h"
16 #include "GrBitmapTextContext.h"
17 #include "GrDistanceFieldTextContext.h"
18 #include "GrLayerCache.h"
19 #include "GrPictureUtils.h"
20 #include "GrStrokeInfo.h"
21 #include "GrTracing.h"
22
23 #include "SkGrTexturePixelRef.h"
24
25 #include "SkDeviceImageFilterProxy.h"
26 #include "SkDrawProcs.h"
27 #include "SkGlyphCache.h"
28 #include "SkImageFilter.h"
29 #include "SkMaskFilter.h"
30 #include "SkPathEffect.h"
31 #include "SkPicture.h"
32 #include "SkPictureData.h"
33 #include "SkPictureRangePlayback.h"
34 #include "SkPictureReplacementPlayback.h"
35 #include "SkRRect.h"
36 #include "SkStroke.h"
37 #include "SkSurface.h"
38 #include "SkTLazy.h"
39 #include "SkUtils.h"
40 #include "SkVertState.h"
41 #include "SkXfermode.h"
42 #include "SkErrorInternals.h"
43
44 enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 };
45
46 #define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
47
48 #if 0
49     extern bool (*gShouldDrawProc)();
50     #define CHECK_SHOULD_DRAW(draw, forceI)                     \
51         do {                                                    \
52             if (gShouldDrawProc && !gShouldDrawProc()) return;  \
53             this->prepareDraw(draw, forceI);                    \
54         } while (0)
55 #else
56     #define CHECK_SHOULD_DRAW(draw, forceI) this->prepareDraw(draw, forceI)
57 #endif
58
59 // This constant represents the screen alignment criterion in texels for
60 // requiring texture domain clamping to prevent color bleeding when drawing
61 // a sub region of a larger source image.
62 #define COLOR_BLEED_TOLERANCE 0.001f
63
64 #define DO_DEFERRED_CLEAR()             \
65     do {                                \
66         if (fNeedClear) {               \
67             this->clear(SK_ColorTRANSPARENT); \
68         }                               \
69     } while (false)                     \
70
71 ///////////////////////////////////////////////////////////////////////////////
72
73 #define CHECK_FOR_ANNOTATION(paint) \
74     do { if (paint.getAnnotation()) { return; } } while (0)
75
76 ///////////////////////////////////////////////////////////////////////////////
77
78
79 class SkGpuDevice::SkAutoCachedTexture : public ::SkNoncopyable {
80 public:
81     SkAutoCachedTexture()
82         : fDevice(NULL)
83         , fTexture(NULL) {
84     }
85
86     SkAutoCachedTexture(SkGpuDevice* device,
87                         const SkBitmap& bitmap,
88                         const GrTextureParams* params,
89                         GrTexture** texture)
90         : fDevice(NULL)
91         , fTexture(NULL) {
92         SkASSERT(NULL != texture);
93         *texture = this->set(device, bitmap, params);
94     }
95
96     ~SkAutoCachedTexture() {
97         if (NULL != fTexture) {
98             GrUnlockAndUnrefCachedBitmapTexture(fTexture);
99         }
100     }
101
102     GrTexture* set(SkGpuDevice* device,
103                    const SkBitmap& bitmap,
104                    const GrTextureParams* params) {
105         if (NULL != fTexture) {
106             GrUnlockAndUnrefCachedBitmapTexture(fTexture);
107             fTexture = NULL;
108         }
109         fDevice = device;
110         GrTexture* result = (GrTexture*)bitmap.getTexture();
111         if (NULL == result) {
112             // Cannot return the native texture so look it up in our cache
113             fTexture = GrLockAndRefCachedBitmapTexture(device->context(), bitmap, params);
114             result = fTexture;
115         }
116         return result;
117     }
118
119 private:
120     SkGpuDevice* fDevice;
121     GrTexture*   fTexture;
122 };
123
124 ///////////////////////////////////////////////////////////////////////////////
125
126 struct GrSkDrawProcs : public SkDrawProcs {
127 public:
128     GrContext* fContext;
129     GrTextContext* fTextContext;
130     GrFontScaler* fFontScaler;  // cached in the skia glyphcache
131 };
132
133 ///////////////////////////////////////////////////////////////////////////////
134
135 SkGpuDevice* SkGpuDevice::Create(GrSurface* surface, unsigned flags) {
136     SkASSERT(NULL != surface);
137     if (NULL == surface->asRenderTarget() || NULL == surface->getContext()) {
138         return NULL;
139     }
140     if (surface->asTexture()) {
141         return SkNEW_ARGS(SkGpuDevice, (surface->getContext(), surface->asTexture(), flags));
142     } else {
143         return SkNEW_ARGS(SkGpuDevice, (surface->getContext(), surface->asRenderTarget(), flags));
144     }
145 }
146
147 SkGpuDevice::SkGpuDevice(GrContext* context, GrTexture* texture, unsigned flags) {
148     this->initFromRenderTarget(context, texture->asRenderTarget(), flags);
149 }
150
151 SkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget, unsigned flags) {
152     this->initFromRenderTarget(context, renderTarget, flags);
153 }
154
155 void SkGpuDevice::initFromRenderTarget(GrContext* context,
156                                        GrRenderTarget* renderTarget,
157                                        unsigned flags) {
158     fDrawProcs = NULL;
159
160     fContext = context;
161     fContext->ref();
162
163     fRenderTarget = NULL;
164     fNeedClear = flags & kNeedClear_Flag;
165
166     SkASSERT(NULL != renderTarget);
167     fRenderTarget = renderTarget;
168     fRenderTarget->ref();
169
170     // Hold onto to the texture in the pixel ref (if there is one) because the texture holds a ref
171     // on the RT but not vice-versa.
172     // TODO: Remove this trickery once we figure out how to make SkGrPixelRef do this without
173     // busting chrome (for a currently unknown reason).
174     GrSurface* surface = fRenderTarget->asTexture();
175     if (NULL == surface) {
176         surface = fRenderTarget;
177     }
178
179     SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef,
180                                 (surface->info(), surface, SkToBool(flags & kCached_Flag)));
181     fLegacyBitmap.setInfo(surface->info());
182     fLegacyBitmap.setPixelRef(pr)->unref();
183
184     bool useDFFonts = !!(flags & kDFFonts_Flag);
185     fMainTextContext = fContext->createTextContext(fRenderTarget, fLeakyProperties, useDFFonts);
186     fFallbackTextContext = SkNEW_ARGS(GrBitmapTextContext, (fContext, fLeakyProperties));
187 }
188
189 SkGpuDevice* SkGpuDevice::Create(GrContext* context, const SkImageInfo& origInfo,
190                                  int sampleCount) {
191     if (kUnknown_SkColorType == origInfo.colorType() ||
192         origInfo.width() < 0 || origInfo.height() < 0) {
193         return NULL;
194     }
195
196     SkImageInfo info = origInfo;
197     // TODO: perhas we can loosen this check now that colortype is more detailed
198     // e.g. can we support both RGBA and BGRA here?
199     if (kRGB_565_SkColorType == info.colorType()) {
200         info.fAlphaType = kOpaque_SkAlphaType;  // force this setting
201     } else {
202         info.fColorType = kN32_SkColorType;
203         if (kOpaque_SkAlphaType != info.alphaType()) {
204             info.fAlphaType = kPremul_SkAlphaType;  // force this setting
205         }
206     }
207
208     GrTextureDesc desc;
209     desc.fFlags = kRenderTarget_GrTextureFlagBit;
210     desc.fWidth = info.width();
211     desc.fHeight = info.height();
212     desc.fConfig = SkImageInfo2GrPixelConfig(info);
213     desc.fSampleCnt = sampleCount;
214
215     SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0));
216     if (!texture.get()) {
217         return NULL;
218     }
219
220     return SkNEW_ARGS(SkGpuDevice, (context, texture.get()));
221 }
222
223 SkGpuDevice::~SkGpuDevice() {
224     if (fDrawProcs) {
225         delete fDrawProcs;
226     }
227
228     delete fMainTextContext;
229     delete fFallbackTextContext;
230
231     // The GrContext takes a ref on the target. We don't want to cause the render
232     // target to be unnecessarily kept alive.
233     if (fContext->getRenderTarget() == fRenderTarget) {
234         fContext->setRenderTarget(NULL);
235     }
236
237     if (fContext->getClip() == &fClipData) {
238         fContext->setClip(NULL);
239     }
240
241     SkSafeUnref(fRenderTarget);
242     fContext->unref();
243 }
244
245 ///////////////////////////////////////////////////////////////////////////////
246
247 void SkGpuDevice::makeRenderTargetCurrent() {
248     DO_DEFERRED_CLEAR();
249     fContext->setRenderTarget(fRenderTarget);
250 }
251
252 ///////////////////////////////////////////////////////////////////////////////
253
254 bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
255                                int x, int y) {
256     DO_DEFERRED_CLEAR();
257
258     // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
259     GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo);
260     if (kUnknown_GrPixelConfig == config) {
261         return false;
262     }
263
264     uint32_t flags = 0;
265     if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
266         flags = GrContext::kUnpremul_PixelOpsFlag;
267     }
268     return fContext->readRenderTargetPixels(fRenderTarget, x, y, dstInfo.width(), dstInfo.height(),
269                                             config, dstPixels, dstRowBytes, flags);
270 }
271
272 bool SkGpuDevice::onWritePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
273                                 int x, int y) {
274     // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
275     GrPixelConfig config = SkImageInfo2GrPixelConfig(info);
276     if (kUnknown_GrPixelConfig == config) {
277         return false;
278     }
279     uint32_t flags = 0;
280     if (kUnpremul_SkAlphaType == info.alphaType()) {
281         flags = GrContext::kUnpremul_PixelOpsFlag;
282     }
283     fRenderTarget->writePixels(x, y, info.width(), info.height(), config, pixels, rowBytes, flags);
284
285     // need to bump our genID for compatibility with clients that "know" we have a bitmap
286     fLegacyBitmap.notifyPixelsChanged();
287
288     return true;
289 }
290
291 const SkBitmap& SkGpuDevice::onAccessBitmap() {
292     DO_DEFERRED_CLEAR();
293     return fLegacyBitmap;
294 }
295
296 void SkGpuDevice::onAttachToCanvas(SkCanvas* canvas) {
297     INHERITED::onAttachToCanvas(canvas);
298
299     // Canvas promises that this ptr is valid until onDetachFromCanvas is called
300     fClipData.fClipStack = canvas->getClipStack();
301 }
302
303 void SkGpuDevice::onDetachFromCanvas() {
304     INHERITED::onDetachFromCanvas();
305     fClipData.fClipStack = NULL;
306 }
307
308 // call this every draw call, to ensure that the context reflects our state,
309 // and not the state from some other canvas/device
310 void SkGpuDevice::prepareDraw(const SkDraw& draw, bool forceIdentity) {
311     SkASSERT(NULL != fClipData.fClipStack);
312
313     fContext->setRenderTarget(fRenderTarget);
314
315     SkASSERT(draw.fClipStack && draw.fClipStack == fClipData.fClipStack);
316
317     if (forceIdentity) {
318         fContext->setIdentityMatrix();
319     } else {
320         fContext->setMatrix(*draw.fMatrix);
321     }
322     fClipData.fOrigin = this->getOrigin();
323
324     fContext->setClip(&fClipData);
325
326     DO_DEFERRED_CLEAR();
327 }
328
329 GrRenderTarget* SkGpuDevice::accessRenderTarget() {
330     DO_DEFERRED_CLEAR();
331     return fRenderTarget;
332 }
333
334 ///////////////////////////////////////////////////////////////////////////////
335
336 SK_COMPILE_ASSERT(SkShader::kNone_BitmapType == 0, shader_type_mismatch);
337 SK_COMPILE_ASSERT(SkShader::kDefault_BitmapType == 1, shader_type_mismatch);
338 SK_COMPILE_ASSERT(SkShader::kRadial_BitmapType == 2, shader_type_mismatch);
339 SK_COMPILE_ASSERT(SkShader::kSweep_BitmapType == 3, shader_type_mismatch);
340 SK_COMPILE_ASSERT(SkShader::kTwoPointRadial_BitmapType == 4,
341                   shader_type_mismatch);
342 SK_COMPILE_ASSERT(SkShader::kTwoPointConical_BitmapType == 5,
343                   shader_type_mismatch);
344 SK_COMPILE_ASSERT(SkShader::kLinear_BitmapType == 6, shader_type_mismatch);
345 SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 6, shader_type_mismatch);
346
347 ///////////////////////////////////////////////////////////////////////////////
348
349 void SkGpuDevice::clear(SkColor color) {
350     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::clear", fContext);
351     SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
352     fContext->clear(&rect, SkColor2GrColor(color), true, fRenderTarget);
353     fNeedClear = false;
354 }
355
356 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
357     CHECK_SHOULD_DRAW(draw, false);
358     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPaint", fContext);
359
360     GrPaint grPaint;
361     SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
362
363     fContext->drawPaint(grPaint);
364 }
365
366 // must be in SkCanvas::PointMode order
367 static const GrPrimitiveType gPointMode2PrimtiveType[] = {
368     kPoints_GrPrimitiveType,
369     kLines_GrPrimitiveType,
370     kLineStrip_GrPrimitiveType
371 };
372
373 void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
374                              size_t count, const SkPoint pts[], const SkPaint& paint) {
375     CHECK_FOR_ANNOTATION(paint);
376     CHECK_SHOULD_DRAW(draw, false);
377
378     SkScalar width = paint.getStrokeWidth();
379     if (width < 0) {
380         return;
381     }
382
383     if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
384         GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style);
385         GrPaint grPaint;
386         SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
387         SkPath path;
388         path.moveTo(pts[0]);
389         path.lineTo(pts[1]);
390         fContext->drawPath(grPaint, path, strokeInfo);
391         return;
392     }
393
394     // we only handle hairlines and paints without path effects or mask filters,
395     // else we let the SkDraw call our drawPath()
396     if (width > 0 || paint.getPathEffect() || paint.getMaskFilter()) {
397         draw.drawPoints(mode, count, pts, paint, true);
398         return;
399     }
400
401     GrPaint grPaint;
402     SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
403
404     fContext->drawVertices(grPaint,
405                            gPointMode2PrimtiveType[mode],
406                            SkToS32(count),
407                            (SkPoint*)pts,
408                            NULL,
409                            NULL,
410                            NULL,
411                            0);
412 }
413
414 ///////////////////////////////////////////////////////////////////////////////
415
416 void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
417                            const SkPaint& paint) {
418     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRect", fContext);
419
420     CHECK_FOR_ANNOTATION(paint);
421     CHECK_SHOULD_DRAW(draw, false);
422
423     bool doStroke = paint.getStyle() != SkPaint::kFill_Style;
424     SkScalar width = paint.getStrokeWidth();
425
426     /*
427         We have special code for hairline strokes, miter-strokes, bevel-stroke
428         and fills. Anything else we just call our path code.
429      */
430     bool usePath = doStroke && width > 0 &&
431                    (paint.getStrokeJoin() == SkPaint::kRound_Join ||
432                     (paint.getStrokeJoin() == SkPaint::kBevel_Join && rect.isEmpty()));
433     // another two reasons we might need to call drawPath...
434
435     if (paint.getMaskFilter()) {
436         usePath = true;
437     }
438
439     if (!usePath && paint.isAntiAlias() && !fContext->getMatrix().rectStaysRect()) {
440 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
441         if (doStroke) {
442 #endif
443             usePath = true;
444 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
445         } else {
446             usePath = !fContext->getMatrix().preservesRightAngles();
447         }
448 #endif
449     }
450     // until we can both stroke and fill rectangles
451     if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) {
452         usePath = true;
453     }
454
455     GrStrokeInfo strokeInfo(paint);
456
457     const SkPathEffect* pe = paint.getPathEffect();
458     if (!usePath && NULL != pe && !strokeInfo.isDashed()) {
459         usePath = true;
460     }
461
462     if (usePath) {
463         SkPath path;
464         path.addRect(rect);
465         this->drawPath(draw, path, paint, NULL, true);
466         return;
467     }
468
469     GrPaint grPaint;
470     SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
471
472     fContext->drawRect(grPaint, rect, &strokeInfo);
473 }
474
475 ///////////////////////////////////////////////////////////////////////////////
476
477 void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
478                            const SkPaint& paint) {
479     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRRect", fContext);
480     CHECK_FOR_ANNOTATION(paint);
481     CHECK_SHOULD_DRAW(draw, false);
482
483     GrPaint grPaint;
484     SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
485
486     GrStrokeInfo strokeInfo(paint);
487     if (paint.getMaskFilter()) {
488         // try to hit the fast path for drawing filtered round rects
489
490         SkRRect devRRect;
491         if (rect.transform(fContext->getMatrix(), &devRRect)) {
492             if (devRRect.allCornersCircular()) {
493                 SkRect maskRect;
494                 if (paint.getMaskFilter()->canFilterMaskGPU(devRRect.rect(),
495                                             draw.fClip->getBounds(),
496                                             fContext->getMatrix(),
497                                             &maskRect)) {
498                     SkIRect finalIRect;
499                     maskRect.roundOut(&finalIRect);
500                     if (draw.fClip->quickReject(finalIRect)) {
501                         // clipped out
502                         return;
503                     }
504                     if (paint.getMaskFilter()->directFilterRRectMaskGPU(fContext, &grPaint,
505                                                                         strokeInfo.getStrokeRec(),
506                                                                         devRRect)) {
507                         return;
508                     }
509                 }
510
511             }
512         }
513
514     }
515
516     bool usePath = false;
517
518     if (paint.getMaskFilter()) {
519         usePath = true;
520     } else {
521         const SkPathEffect* pe = paint.getPathEffect();
522         if (NULL != pe && !strokeInfo.isDashed()) {
523             usePath = true;
524         }
525     }
526
527
528     if (usePath) {
529         SkPath path;
530         path.addRRect(rect);
531         this->drawPath(draw, path, paint, NULL, true);
532         return;
533     }
534
535     fContext->drawRRect(grPaint, rect, strokeInfo);
536 }
537
538 void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
539                               const SkRRect& inner, const SkPaint& paint) {
540     SkStrokeRec stroke(paint);
541     if (stroke.isFillStyle()) {
542
543         CHECK_FOR_ANNOTATION(paint);
544         CHECK_SHOULD_DRAW(draw, false);
545
546         GrPaint grPaint;
547         SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
548
549         if (NULL == paint.getMaskFilter() && NULL == paint.getPathEffect()) {
550             fContext->drawDRRect(grPaint, outer, inner);
551             return;
552         }
553     }
554
555     SkPath path;
556     path.addRRect(outer);
557     path.addRRect(inner);
558     path.setFillType(SkPath::kEvenOdd_FillType);
559
560     this->drawPath(draw, path, paint, NULL, true);
561 }
562
563
564 /////////////////////////////////////////////////////////////////////////////
565
566 void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
567                            const SkPaint& paint) {
568     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawOval", fContext);
569     CHECK_FOR_ANNOTATION(paint);
570     CHECK_SHOULD_DRAW(draw, false);
571
572     GrStrokeInfo strokeInfo(paint);
573
574     bool usePath = false;
575     // some basic reasons we might need to call drawPath...
576     if (paint.getMaskFilter()) {
577         usePath = true;
578     } else {
579         const SkPathEffect* pe = paint.getPathEffect();
580         if (NULL != pe && !strokeInfo.isDashed()) {
581             usePath = true;
582         }
583     }
584
585     if (usePath) {
586         SkPath path;
587         path.addOval(oval);
588         this->drawPath(draw, path, paint, NULL, true);
589         return;
590     }
591
592     GrPaint grPaint;
593     SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
594
595     fContext->drawOval(grPaint, oval, strokeInfo);
596 }
597
598 #include "SkMaskFilter.h"
599
600 ///////////////////////////////////////////////////////////////////////////////
601
602 // helpers for applying mask filters
603 namespace {
604
605 // Draw a mask using the supplied paint. Since the coverage/geometry
606 // is already burnt into the mask this boils down to a rect draw.
607 // Return true if the mask was successfully drawn.
608 bool draw_mask(GrContext* context, const SkRect& maskRect,
609                GrPaint* grp, GrTexture* mask) {
610     GrContext::AutoMatrix am;
611     if (!am.setIdentity(context, grp)) {
612         return false;
613     }
614
615     SkMatrix matrix;
616     matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop);
617     matrix.postIDiv(mask->width(), mask->height());
618
619     grp->addCoverageEffect(GrSimpleTextureEffect::Create(mask, matrix))->unref();
620     context->drawRect(*grp, maskRect);
621     return true;
622 }
623
624 bool draw_with_mask_filter(GrContext* context, const SkPath& devPath,
625                            SkMaskFilter* filter, const SkRegion& clip,
626                            GrPaint* grp, SkPaint::Style style) {
627     SkMask  srcM, dstM;
628
629     if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), filter, &context->getMatrix(), &srcM,
630                             SkMask::kComputeBoundsAndRenderImage_CreateMode, style)) {
631         return false;
632     }
633     SkAutoMaskFreeImage autoSrc(srcM.fImage);
634
635     if (!filter->filterMask(&dstM, srcM, context->getMatrix(), NULL)) {
636         return false;
637     }
638     // this will free-up dstM when we're done (allocated in filterMask())
639     SkAutoMaskFreeImage autoDst(dstM.fImage);
640
641     if (clip.quickReject(dstM.fBounds)) {
642         return false;
643     }
644
645     // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
646     // the current clip (and identity matrix) and GrPaint settings
647     GrTextureDesc desc;
648     desc.fWidth = dstM.fBounds.width();
649     desc.fHeight = dstM.fBounds.height();
650     desc.fConfig = kAlpha_8_GrPixelConfig;
651
652     GrAutoScratchTexture ast(context, desc);
653     GrTexture* texture = ast.texture();
654
655     if (NULL == texture) {
656         return false;
657     }
658     texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
659                                dstM.fImage, dstM.fRowBytes);
660
661     SkRect maskRect = SkRect::Make(dstM.fBounds);
662
663     return draw_mask(context, maskRect, grp, texture);
664 }
665
666 // Create a mask of 'devPath' and place the result in 'mask'. Return true on
667 // success; false otherwise.
668 bool create_mask_GPU(GrContext* context,
669                      const SkRect& maskRect,
670                      const SkPath& devPath,
671                      const GrStrokeInfo& strokeInfo,
672                      bool doAA,
673                      GrAutoScratchTexture* mask) {
674     GrTextureDesc desc;
675     desc.fFlags = kRenderTarget_GrTextureFlagBit;
676     desc.fWidth = SkScalarCeilToInt(maskRect.width());
677     desc.fHeight = SkScalarCeilToInt(maskRect.height());
678     // We actually only need A8, but it often isn't supported as a
679     // render target so default to RGBA_8888
680     desc.fConfig = kRGBA_8888_GrPixelConfig;
681     if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
682         desc.fConfig = kAlpha_8_GrPixelConfig;
683     }
684
685     mask->set(context, desc);
686     if (NULL == mask->texture()) {
687         return false;
688     }
689
690     GrTexture* maskTexture = mask->texture();
691     SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());
692
693     GrContext::AutoRenderTarget art(context, maskTexture->asRenderTarget());
694     GrContext::AutoClip ac(context, clipRect);
695
696     context->clear(NULL, 0x0, true);
697
698     GrPaint tempPaint;
699     if (doAA) {
700         tempPaint.setAntiAlias(true);
701         // AA uses the "coverage" stages on GrDrawTarget. Coverage with a dst
702         // blend coeff of zero requires dual source blending support in order
703         // to properly blend partially covered pixels. This means the AA
704         // code path may not be taken. So we use a dst blend coeff of ISA. We
705         // could special case AA draws to a dst surface with known alpha=0 to
706         // use a zero dst coeff when dual source blending isn't available.
707         tempPaint.setBlendFunc(kOne_GrBlendCoeff, kISC_GrBlendCoeff);
708     }
709
710     GrContext::AutoMatrix am;
711
712     // Draw the mask into maskTexture with the path's top-left at the origin using tempPaint.
713     SkMatrix translate;
714     translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
715     am.set(context, translate);
716     context->drawPath(tempPaint, devPath, strokeInfo);
717     return true;
718 }
719
720 SkBitmap wrap_texture(GrTexture* texture) {
721     SkBitmap result;
722     result.setInfo(texture->info());
723     result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
724     return result;
725 }
726
727 };
728
729 void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
730                            const SkPaint& paint, const SkMatrix* prePathMatrix,
731                            bool pathIsMutable) {
732     CHECK_FOR_ANNOTATION(paint);
733     CHECK_SHOULD_DRAW(draw, false);
734     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPath", fContext);
735
736     GrPaint grPaint;
737     SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
738
739     // If we have a prematrix, apply it to the path, optimizing for the case
740     // where the original path can in fact be modified in place (even though
741     // its parameter type is const).
742     SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
743     SkTLazy<SkPath> tmpPath;
744     SkTLazy<SkPath> effectPath;
745
746     if (prePathMatrix) {
747         SkPath* result = pathPtr;
748
749         if (!pathIsMutable) {
750             result = tmpPath.init();
751             pathIsMutable = true;
752         }
753         // should I push prePathMatrix on our MV stack temporarily, instead
754         // of applying it here? See SkDraw.cpp
755         pathPtr->transform(*prePathMatrix, result);
756         pathPtr = result;
757     }
758     // at this point we're done with prePathMatrix
759     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
760
761     GrStrokeInfo strokeInfo(paint);
762     SkPathEffect* pathEffect = paint.getPathEffect();
763     const SkRect* cullRect = NULL;  // TODO: what is our bounds?
764     SkStrokeRec* strokePtr = strokeInfo.getStrokeRecPtr();
765     if (pathEffect && pathEffect->filterPath(effectPath.init(), *pathPtr, strokePtr,
766                                              cullRect)) {
767         pathPtr = effectPath.get();
768         pathIsMutable = true;
769         strokeInfo.removeDash();
770     }
771
772     const SkStrokeRec& stroke = strokeInfo.getStrokeRec();
773     if (paint.getMaskFilter()) {
774         if (!stroke.isHairlineStyle()) {
775             SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init();
776             if (stroke.applyToPath(strokedPath, *pathPtr)) {
777                 pathPtr = strokedPath;
778                 pathIsMutable = true;
779                 strokeInfo.setFillStyle();
780             }
781         }
782
783         // avoid possibly allocating a new path in transform if we can
784         SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init();
785
786         // transform the path into device space
787         pathPtr->transform(fContext->getMatrix(), devPathPtr);
788
789         SkRect maskRect;
790         if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(),
791                                                     draw.fClip->getBounds(),
792                                                     fContext->getMatrix(),
793                                                     &maskRect)) {
794             // The context's matrix may change while creating the mask, so save the CTM here to
795             // pass to filterMaskGPU.
796             const SkMatrix ctm = fContext->getMatrix();
797
798             SkIRect finalIRect;
799             maskRect.roundOut(&finalIRect);
800             if (draw.fClip->quickReject(finalIRect)) {
801                 // clipped out
802                 return;
803             }
804
805             if (paint.getMaskFilter()->directFilterMaskGPU(fContext, &grPaint,
806                                                            stroke, *devPathPtr)) {
807                 // the mask filter was able to draw itself directly, so there's nothing
808                 // left to do.
809                 return;
810             }
811
812             GrAutoScratchTexture mask;
813
814             if (create_mask_GPU(fContext, maskRect, *devPathPtr, strokeInfo,
815                                 grPaint.isAntiAlias(), &mask)) {
816                 GrTexture* filtered;
817
818                 if (paint.getMaskFilter()->filterMaskGPU(mask.texture(),
819                                                          ctm, maskRect, &filtered, true)) {
820                     // filterMaskGPU gives us ownership of a ref to the result
821                     SkAutoTUnref<GrTexture> atu(filtered);
822
823                     // If the scratch texture that we used as the filter src also holds the filter
824                     // result then we must detach so that this texture isn't recycled for a later
825                     // draw.
826                     if (filtered == mask.texture()) {
827                         mask.detach();
828                         filtered->unref(); // detach transfers GrAutoScratchTexture's ref to us.
829                     }
830
831                     if (draw_mask(fContext, maskRect, &grPaint, filtered)) {
832                         // This path is completely drawn
833                         return;
834                     }
835                 }
836             }
837         }
838
839         // draw the mask on the CPU - this is a fallthrough path in case the
840         // GPU path fails
841         SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style :
842                                                           SkPaint::kFill_Style;
843         draw_with_mask_filter(fContext, *devPathPtr, paint.getMaskFilter(),
844                               *draw.fClip, &grPaint, style);
845         return;
846     }
847
848     fContext->drawPath(grPaint, *pathPtr, strokeInfo);
849 }
850
851 static const int kBmpSmallTileSize = 1 << 10;
852
853 static inline int get_tile_count(const SkIRect& srcRect, int tileSize)  {
854     int tilesX = (srcRect.fRight / tileSize) - (srcRect.fLeft / tileSize) + 1;
855     int tilesY = (srcRect.fBottom / tileSize) - (srcRect.fTop / tileSize) + 1;
856     return tilesX * tilesY;
857 }
858
859 static int determine_tile_size(const SkBitmap& bitmap, const SkIRect& src, int maxTileSize) {
860     if (maxTileSize <= kBmpSmallTileSize) {
861         return maxTileSize;
862     }
863
864     size_t maxTileTotalTileSize = get_tile_count(src, maxTileSize);
865     size_t smallTotalTileSize = get_tile_count(src, kBmpSmallTileSize);
866
867     maxTileTotalTileSize *= maxTileSize * maxTileSize;
868     smallTotalTileSize *= kBmpSmallTileSize * kBmpSmallTileSize;
869
870     if (maxTileTotalTileSize > 2 * smallTotalTileSize) {
871         return kBmpSmallTileSize;
872     } else {
873         return maxTileSize;
874     }
875 }
876
877 // Given a bitmap, an optional src rect, and a context with a clip and matrix determine what
878 // pixels from the bitmap are necessary.
879 static void determine_clipped_src_rect(const GrContext* context,
880                                        const SkBitmap& bitmap,
881                                        const SkRect* srcRectPtr,
882                                        SkIRect* clippedSrcIRect) {
883     const GrClipData* clip = context->getClip();
884     clip->getConservativeBounds(context->getRenderTarget(), clippedSrcIRect, NULL);
885     SkMatrix inv;
886     if (!context->getMatrix().invert(&inv)) {
887         clippedSrcIRect->setEmpty();
888         return;
889     }
890     SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect);
891     inv.mapRect(&clippedSrcRect);
892     if (NULL != srcRectPtr) {
893         // we've setup src space 0,0 to map to the top left of the src rect.
894         clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop);
895         if (!clippedSrcRect.intersect(*srcRectPtr)) {
896             clippedSrcIRect->setEmpty();
897             return;
898         }
899     }
900     clippedSrcRect.roundOut(clippedSrcIRect);
901     SkIRect bmpBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
902     if (!clippedSrcIRect->intersect(bmpBounds)) {
903         clippedSrcIRect->setEmpty();
904     }
905 }
906
907 bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
908                                    const GrTextureParams& params,
909                                    const SkRect* srcRectPtr,
910                                    int maxTileSize,
911                                    int* tileSize,
912                                    SkIRect* clippedSrcRect) const {
913     // if bitmap is explictly texture backed then just use the texture
914     if (NULL != bitmap.getTexture()) {
915         return false;
916     }
917
918     // if it's larger than the max tile size, then we have no choice but tiling.
919     if (bitmap.width() > maxTileSize || bitmap.height() > maxTileSize) {
920         determine_clipped_src_rect(fContext, bitmap, srcRectPtr, clippedSrcRect);
921         *tileSize = determine_tile_size(bitmap, *clippedSrcRect, maxTileSize);
922         return true;
923     }
924
925     if (bitmap.width() * bitmap.height() < 4 * kBmpSmallTileSize * kBmpSmallTileSize) {
926         return false;
927     }
928
929     // if the entire texture is already in our cache then no reason to tile it
930     if (GrIsBitmapInCache(fContext, bitmap, &params)) {
931         return false;
932     }
933
934     // At this point we know we could do the draw by uploading the entire bitmap
935     // as a texture. However, if the texture would be large compared to the
936     // cache size and we don't require most of it for this draw then tile to
937     // reduce the amount of upload and cache spill.
938
939     // assumption here is that sw bitmap size is a good proxy for its size as
940     // a texture
941     size_t bmpSize = bitmap.getSize();
942     size_t cacheSize;
943     fContext->getResourceCacheLimits(NULL, &cacheSize);
944     if (bmpSize < cacheSize / 2) {
945         return false;
946     }
947
948     // Figure out how much of the src we will need based on the src rect and clipping.
949     determine_clipped_src_rect(fContext, bitmap, srcRectPtr, clippedSrcRect);
950     *tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
951     size_t usedTileBytes = get_tile_count(*clippedSrcRect, kBmpSmallTileSize) *
952                            kBmpSmallTileSize * kBmpSmallTileSize;
953
954     return usedTileBytes < 2 * bmpSize;
955 }
956
957 void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
958                              const SkBitmap& bitmap,
959                              const SkMatrix& m,
960                              const SkPaint& paint) {
961     SkMatrix concat;
962     SkTCopyOnFirstWrite<SkDraw> draw(origDraw);
963     if (!m.isIdentity()) {
964         concat.setConcat(*draw->fMatrix, m);
965         draw.writable()->fMatrix = &concat;
966     }
967     this->drawBitmapCommon(*draw, bitmap, NULL, NULL, paint, SkCanvas::kNone_DrawBitmapRectFlag);
968 }
969
970 // This method outsets 'iRect' by 'outset' all around and then clamps its extents to
971 // 'clamp'. 'offset' is adjusted to remain positioned over the top-left corner
972 // of 'iRect' for all possible outsets/clamps.
973 static inline void clamped_outset_with_offset(SkIRect* iRect,
974                                               int outset,
975                                               SkPoint* offset,
976                                               const SkIRect& clamp) {
977     iRect->outset(outset, outset);
978
979     int leftClampDelta = clamp.fLeft - iRect->fLeft;
980     if (leftClampDelta > 0) {
981         offset->fX -= outset - leftClampDelta;
982         iRect->fLeft = clamp.fLeft;
983     } else {
984         offset->fX -= outset;
985     }
986
987     int topClampDelta = clamp.fTop - iRect->fTop;
988     if (topClampDelta > 0) {
989         offset->fY -= outset - topClampDelta;
990         iRect->fTop = clamp.fTop;
991     } else {
992         offset->fY -= outset;
993     }
994
995     if (iRect->fRight > clamp.fRight) {
996         iRect->fRight = clamp.fRight;
997     }
998     if (iRect->fBottom > clamp.fBottom) {
999         iRect->fBottom = clamp.fBottom;
1000     }
1001 }
1002
1003 static bool has_aligned_samples(const SkRect& srcRect,
1004                                 const SkRect& transformedRect) {
1005     // detect pixel disalignment
1006     if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) -
1007             transformedRect.left()) < COLOR_BLEED_TOLERANCE &&
1008         SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) -
1009             transformedRect.top()) < COLOR_BLEED_TOLERANCE &&
1010         SkScalarAbs(transformedRect.width() - srcRect.width()) <
1011             COLOR_BLEED_TOLERANCE &&
1012         SkScalarAbs(transformedRect.height() - srcRect.height()) <
1013             COLOR_BLEED_TOLERANCE) {
1014         return true;
1015     }
1016     return false;
1017 }
1018
1019 static bool may_color_bleed(const SkRect& srcRect,
1020                             const SkRect& transformedRect,
1021                             const SkMatrix& m) {
1022     // Only gets called if has_aligned_samples returned false.
1023     // So we can assume that sampling is axis aligned but not texel aligned.
1024     SkASSERT(!has_aligned_samples(srcRect, transformedRect));
1025     SkRect innerSrcRect(srcRect), innerTransformedRect,
1026         outerTransformedRect(transformedRect);
1027     innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
1028     m.mapRect(&innerTransformedRect, innerSrcRect);
1029
1030     // The gap between outerTransformedRect and innerTransformedRect
1031     // represents the projection of the source border area, which is
1032     // problematic for color bleeding.  We must check whether any
1033     // destination pixels sample the border area.
1034     outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
1035     innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
1036     SkIRect outer, inner;
1037     outerTransformedRect.round(&outer);
1038     innerTransformedRect.round(&inner);
1039     // If the inner and outer rects round to the same result, it means the
1040     // border does not overlap any pixel centers. Yay!
1041     return inner != outer;
1042 }
1043
1044 static bool needs_texture_domain(const SkBitmap& bitmap,
1045                                  const SkRect& srcRect,
1046                                  GrTextureParams &params,
1047                                  const SkMatrix& contextMatrix,
1048                                  bool bicubic) {
1049     bool needsTextureDomain = false;
1050
1051     if (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode) {
1052         // Need texture domain if drawing a sub rect
1053         needsTextureDomain = srcRect.width() < bitmap.width() ||
1054                              srcRect.height() < bitmap.height();
1055         if (!bicubic && needsTextureDomain && contextMatrix.rectStaysRect()) {
1056             // sampling is axis-aligned
1057             SkRect transformedRect;
1058             contextMatrix.mapRect(&transformedRect, srcRect);
1059
1060             if (has_aligned_samples(srcRect, transformedRect)) {
1061                 params.setFilterMode(GrTextureParams::kNone_FilterMode);
1062                 needsTextureDomain = false;
1063             } else {
1064                 needsTextureDomain = may_color_bleed(srcRect, transformedRect, contextMatrix);
1065             }
1066         }
1067     }
1068     return needsTextureDomain;
1069 }
1070
1071 void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
1072                                    const SkBitmap& bitmap,
1073                                    const SkRect* srcRectPtr,
1074                                    const SkSize* dstSizePtr,
1075                                    const SkPaint& paint,
1076                                    SkCanvas::DrawBitmapRectFlags flags) {
1077     CHECK_SHOULD_DRAW(draw, false);
1078
1079     SkRect srcRect;
1080     SkSize dstSize;
1081     // If there is no src rect, or the src rect contains the entire bitmap then we're effectively
1082     // in the (easier) bleed case, so update flags.
1083     if (NULL == srcRectPtr) {
1084         SkScalar w = SkIntToScalar(bitmap.width());
1085         SkScalar h = SkIntToScalar(bitmap.height());
1086         dstSize.fWidth = w;
1087         dstSize.fHeight = h;
1088         srcRect.set(0, 0, w, h);
1089         flags = (SkCanvas::DrawBitmapRectFlags) (flags | SkCanvas::kBleed_DrawBitmapRectFlag);
1090     } else {
1091         SkASSERT(NULL != dstSizePtr);
1092         srcRect = *srcRectPtr;
1093         dstSize = *dstSizePtr;
1094         if (srcRect.fLeft <= 0 && srcRect.fTop <= 0 &&
1095             srcRect.fRight >= bitmap.width() && srcRect.fBottom >= bitmap.height()) {
1096             flags = (SkCanvas::DrawBitmapRectFlags) (flags | SkCanvas::kBleed_DrawBitmapRectFlag);
1097         }
1098     }
1099
1100     if (paint.getMaskFilter()){
1101         // Convert the bitmap to a shader so that the rect can be drawn
1102         // through drawRect, which supports mask filters.
1103         SkBitmap        tmp;    // subset of bitmap, if necessary
1104         const SkBitmap* bitmapPtr = &bitmap;
1105         SkMatrix localM;
1106         if (NULL != srcRectPtr) {
1107             localM.setTranslate(-srcRectPtr->fLeft, -srcRectPtr->fTop);
1108             localM.postScale(dstSize.fWidth / srcRectPtr->width(),
1109                              dstSize.fHeight / srcRectPtr->height());
1110             // In bleed mode we position and trim the bitmap based on the src rect which is
1111             // already accounted for in 'm' and 'srcRect'. In clamp mode we need to chop out
1112             // the desired portion of the bitmap and then update 'm' and 'srcRect' to
1113             // compensate.
1114             if (!(SkCanvas::kBleed_DrawBitmapRectFlag & flags)) {
1115                 SkIRect iSrc;
1116                 srcRect.roundOut(&iSrc);
1117
1118                 SkPoint offset = SkPoint::Make(SkIntToScalar(iSrc.fLeft),
1119                                                SkIntToScalar(iSrc.fTop));
1120
1121                 if (!bitmap.extractSubset(&tmp, iSrc)) {
1122                     return;     // extraction failed
1123                 }
1124                 bitmapPtr = &tmp;
1125                 srcRect.offset(-offset.fX, -offset.fY);
1126
1127                 // The source rect has changed so update the matrix
1128                 localM.preTranslate(offset.fX, offset.fY);
1129             }
1130         } else {
1131             localM.reset();
1132         }
1133
1134         SkPaint paintWithShader(paint);
1135         paintWithShader.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
1136             SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &localM))->unref();
1137         SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
1138         this->drawRect(draw, dstRect, paintWithShader);
1139
1140         return;
1141     }
1142
1143     // If there is no mask filter than it is OK to handle the src rect -> dst rect scaling using
1144     // the view matrix rather than a local matrix.
1145     SkMatrix m;
1146     m.setScale(dstSize.fWidth / srcRect.width(),
1147                dstSize.fHeight / srcRect.height());
1148     fContext->concatMatrix(m);
1149
1150     GrTextureParams params;
1151     SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel();
1152     GrTextureParams::FilterMode textureFilterMode;
1153
1154     bool doBicubic = false;
1155
1156     switch(paintFilterLevel) {
1157         case SkPaint::kNone_FilterLevel:
1158             textureFilterMode = GrTextureParams::kNone_FilterMode;
1159             break;
1160         case SkPaint::kLow_FilterLevel:
1161             textureFilterMode = GrTextureParams::kBilerp_FilterMode;
1162             break;
1163         case SkPaint::kMedium_FilterLevel:
1164             if (fContext->getMatrix().getMinScale() < SK_Scalar1) {
1165                 textureFilterMode = GrTextureParams::kMipMap_FilterMode;
1166             } else {
1167                 // Don't trigger MIP level generation unnecessarily.
1168                 textureFilterMode = GrTextureParams::kBilerp_FilterMode;
1169             }
1170             break;
1171         case SkPaint::kHigh_FilterLevel:
1172             // Minification can look bad with the bicubic effect.
1173             doBicubic =
1174                 GrBicubicEffect::ShouldUseBicubic(fContext->getMatrix(), &textureFilterMode);
1175             break;
1176         default:
1177             SkErrorInternals::SetError( kInvalidPaint_SkError,
1178                                         "Sorry, I don't understand the filtering "
1179                                         "mode you asked for.  Falling back to "
1180                                         "MIPMaps.");
1181             textureFilterMode = GrTextureParams::kMipMap_FilterMode;
1182             break;
1183     }
1184
1185     int tileFilterPad;
1186     if (doBicubic) {
1187         tileFilterPad = GrBicubicEffect::kFilterTexelPad;
1188     } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
1189         tileFilterPad = 0;
1190     } else {
1191         tileFilterPad = 1;
1192     }
1193     params.setFilterMode(textureFilterMode);
1194
1195     int maxTileSize = fContext->getMaxTextureSize() - 2 * tileFilterPad;
1196     int tileSize;
1197
1198     SkIRect clippedSrcRect;
1199     if (this->shouldTileBitmap(bitmap, params, srcRectPtr, maxTileSize, &tileSize,
1200                                &clippedSrcRect)) {
1201         this->drawTiledBitmap(bitmap, srcRect, clippedSrcRect, params, paint, flags, tileSize,
1202                               doBicubic);
1203     } else {
1204         // take the simple case
1205         bool needsTextureDomain = needs_texture_domain(bitmap,
1206                                                        srcRect,
1207                                                        params,
1208                                                        fContext->getMatrix(),
1209                                                        doBicubic);
1210         this->internalDrawBitmap(bitmap,
1211                                  srcRect,
1212                                  params,
1213                                  paint,
1214                                  flags,
1215                                  doBicubic,
1216                                  needsTextureDomain);
1217     }
1218 }
1219
1220 // Break 'bitmap' into several tiles to draw it since it has already
1221 // been determined to be too large to fit in VRAM
1222 void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
1223                                   const SkRect& srcRect,
1224                                   const SkIRect& clippedSrcIRect,
1225                                   const GrTextureParams& params,
1226                                   const SkPaint& paint,
1227                                   SkCanvas::DrawBitmapRectFlags flags,
1228                                   int tileSize,
1229                                   bool bicubic) {
1230     // The following pixel lock is technically redundant, but it is desirable
1231     // to lock outside of the tile loop to prevent redecoding the whole image
1232     // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that
1233     // is larger than the limit of the discardable memory pool.
1234     SkAutoLockPixels alp(bitmap);
1235     SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
1236
1237     int nx = bitmap.width() / tileSize;
1238     int ny = bitmap.height() / tileSize;
1239     for (int x = 0; x <= nx; x++) {
1240         for (int y = 0; y <= ny; y++) {
1241             SkRect tileR;
1242             tileR.set(SkIntToScalar(x * tileSize),
1243                       SkIntToScalar(y * tileSize),
1244                       SkIntToScalar((x + 1) * tileSize),
1245                       SkIntToScalar((y + 1) * tileSize));
1246
1247             if (!SkRect::Intersects(tileR, clippedSrcRect)) {
1248                 continue;
1249             }
1250
1251             if (!tileR.intersect(srcRect)) {
1252                 continue;
1253             }
1254
1255             SkBitmap tmpB;
1256             SkIRect iTileR;
1257             tileR.roundOut(&iTileR);
1258             SkPoint offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft),
1259                                            SkIntToScalar(iTileR.fTop));
1260
1261             // Adjust the context matrix to draw at the right x,y in device space
1262             SkMatrix tmpM;
1263             GrContext::AutoMatrix am;
1264             tmpM.setTranslate(offset.fX - srcRect.fLeft, offset.fY - srcRect.fTop);
1265             am.setPreConcat(fContext, tmpM);
1266
1267             if (SkPaint::kNone_FilterLevel != paint.getFilterLevel() || bicubic) {
1268                 SkIRect iClampRect;
1269
1270                 if (SkCanvas::kBleed_DrawBitmapRectFlag & flags) {
1271                     // In bleed mode we want to always expand the tile on all edges
1272                     // but stay within the bitmap bounds
1273                     iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1274                 } else {
1275                     // In texture-domain/clamp mode we only want to expand the
1276                     // tile on edges interior to "srcRect" (i.e., we want to
1277                     // not bleed across the original clamped edges)
1278                     srcRect.roundOut(&iClampRect);
1279                 }
1280                 int outset = bicubic ? GrBicubicEffect::kFilterTexelPad : 1;
1281                 clamped_outset_with_offset(&iTileR, outset, &offset, iClampRect);
1282             }
1283
1284             if (bitmap.extractSubset(&tmpB, iTileR)) {
1285                 // now offset it to make it "local" to our tmp bitmap
1286                 tileR.offset(-offset.fX, -offset.fY);
1287                 GrTextureParams paramsTemp = params;
1288                 bool needsTextureDomain = needs_texture_domain(bitmap,
1289                                                                srcRect,
1290                                                                paramsTemp,
1291                                                                fContext->getMatrix(),
1292                                                                bicubic);
1293                 this->internalDrawBitmap(tmpB,
1294                                          tileR,
1295                                          paramsTemp,
1296                                          paint,
1297                                          flags,
1298                                          bicubic,
1299                                          needsTextureDomain);
1300             }
1301         }
1302     }
1303 }
1304
1305
1306 /*
1307  *  This is called by drawBitmap(), which has to handle images that may be too
1308  *  large to be represented by a single texture.
1309  *
1310  *  internalDrawBitmap assumes that the specified bitmap will fit in a texture
1311  *  and that non-texture portion of the GrPaint has already been setup.
1312  */
1313 void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
1314                                      const SkRect& srcRect,
1315                                      const GrTextureParams& params,
1316                                      const SkPaint& paint,
1317                                      SkCanvas::DrawBitmapRectFlags flags,
1318                                      bool bicubic,
1319                                      bool needsTextureDomain) {
1320     SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
1321              bitmap.height() <= fContext->getMaxTextureSize());
1322
1323     GrTexture* texture;
1324     SkAutoCachedTexture act(this, bitmap, &params, &texture);
1325     if (NULL == texture) {
1326         return;
1327     }
1328
1329     SkRect dstRect = {0, 0, srcRect.width(), srcRect.height() };
1330     SkRect paintRect;
1331     SkScalar wInv = SkScalarInvert(SkIntToScalar(texture->width()));
1332     SkScalar hInv = SkScalarInvert(SkIntToScalar(texture->height()));
1333     paintRect.setLTRB(SkScalarMul(srcRect.fLeft,   wInv),
1334                       SkScalarMul(srcRect.fTop,    hInv),
1335                       SkScalarMul(srcRect.fRight,  wInv),
1336                       SkScalarMul(srcRect.fBottom, hInv));
1337
1338     SkRect textureDomain = SkRect::MakeEmpty();
1339     SkAutoTUnref<GrEffect> effect;
1340     if (needsTextureDomain && !(flags & SkCanvas::kBleed_DrawBitmapRectFlag)) {
1341         // Use a constrained texture domain to avoid color bleeding
1342         SkScalar left, top, right, bottom;
1343         if (srcRect.width() > SK_Scalar1) {
1344             SkScalar border = SK_ScalarHalf / texture->width();
1345             left = paintRect.left() + border;
1346             right = paintRect.right() - border;
1347         } else {
1348             left = right = SkScalarHalf(paintRect.left() + paintRect.right());
1349         }
1350         if (srcRect.height() > SK_Scalar1) {
1351             SkScalar border = SK_ScalarHalf / texture->height();
1352             top = paintRect.top() + border;
1353             bottom = paintRect.bottom() - border;
1354         } else {
1355             top = bottom = SkScalarHalf(paintRect.top() + paintRect.bottom());
1356         }
1357         textureDomain.setLTRB(left, top, right, bottom);
1358         if (bicubic) {
1359             effect.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), textureDomain));
1360         } else {
1361             effect.reset(GrTextureDomainEffect::Create(texture,
1362                                                        SkMatrix::I(),
1363                                                        textureDomain,
1364                                                        GrTextureDomain::kClamp_Mode,
1365                                                        params.filterMode()));
1366         }
1367     } else if (bicubic) {
1368         SkASSERT(GrTextureParams::kNone_FilterMode == params.filterMode());
1369         SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTileModeY() };
1370         effect.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), tileModes));
1371     } else {
1372         effect.reset(GrSimpleTextureEffect::Create(texture, SkMatrix::I(), params));
1373     }
1374
1375     // Construct a GrPaint by setting the bitmap texture as the first effect and then configuring
1376     // the rest from the SkPaint.
1377     GrPaint grPaint;
1378     grPaint.addColorEffect(effect);
1379     bool alphaOnly = !(kAlpha_8_SkColorType == bitmap.colorType());
1380     GrColor paintColor = (alphaOnly) ? SkColor2GrColorJustAlpha(paint.getColor()) :
1381                                        SkColor2GrColor(paint.getColor());
1382     SkPaint2GrPaintNoShader(this->context(), paint, paintColor, false, &grPaint);
1383
1384     fContext->drawRectToRect(grPaint, dstRect, paintRect);
1385 }
1386
1387 static bool filter_texture(SkBaseDevice* device, GrContext* context,
1388                            GrTexture* texture, const SkImageFilter* filter,
1389                            int w, int h, const SkImageFilter::Context& ctx,
1390                            SkBitmap* result, SkIPoint* offset) {
1391     SkASSERT(filter);
1392     SkDeviceImageFilterProxy proxy(device);
1393
1394     if (filter->canFilterImageGPU()) {
1395         // Save the render target and set it to NULL, so we don't accidentally draw to it in the
1396         // filter.  Also set the clip wide open and the matrix to identity.
1397         GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
1398         return filter->filterImageGPU(&proxy, wrap_texture(texture), ctx, result, offset);
1399     } else {
1400         return false;
1401     }
1402 }
1403
1404 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
1405                              int left, int top, const SkPaint& paint) {
1406     // drawSprite is defined to be in device coords.
1407     CHECK_SHOULD_DRAW(draw, true);
1408
1409     SkAutoLockPixels alp(bitmap, !bitmap.getTexture());
1410     if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
1411         return;
1412     }
1413
1414     int w = bitmap.width();
1415     int h = bitmap.height();
1416
1417     GrTexture* texture;
1418     // draw sprite uses the default texture params
1419     SkAutoCachedTexture act(this, bitmap, NULL, &texture);
1420
1421     SkImageFilter* filter = paint.getImageFilter();
1422     // This bitmap will own the filtered result as a texture.
1423     SkBitmap filteredBitmap;
1424
1425     if (NULL != filter) {
1426         SkIPoint offset = SkIPoint::Make(0, 0);
1427         SkMatrix matrix(*draw.fMatrix);
1428         matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top));
1429         SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1430         SkAutoTUnref<SkImageFilter::Cache> cache(getImageFilterCache());
1431         // This cache is transient, and is freed (along with all its contained
1432         // textures) when it goes out of scope.
1433         SkImageFilter::Context ctx(matrix, clipBounds, cache);
1434         if (filter_texture(this, fContext, texture, filter, w, h, ctx, &filteredBitmap,
1435                            &offset)) {
1436             texture = (GrTexture*) filteredBitmap.getTexture();
1437             w = filteredBitmap.width();
1438             h = filteredBitmap.height();
1439             left += offset.x();
1440             top += offset.y();
1441         } else {
1442             return;
1443         }
1444     }
1445
1446     GrPaint grPaint;
1447     grPaint.addColorTextureEffect(texture, SkMatrix::I());
1448
1449     SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColorJustAlpha(paint.getColor()),
1450                             false, &grPaint);
1451
1452     fContext->drawRectToRect(grPaint,
1453                              SkRect::MakeXYWH(SkIntToScalar(left),
1454                                               SkIntToScalar(top),
1455                                               SkIntToScalar(w),
1456                                               SkIntToScalar(h)),
1457                              SkRect::MakeXYWH(0,
1458                                               0,
1459                                               SK_Scalar1 * w / texture->width(),
1460                                               SK_Scalar1 * h / texture->height()));
1461 }
1462
1463 void SkGpuDevice::drawBitmapRect(const SkDraw& origDraw, const SkBitmap& bitmap,
1464                                  const SkRect* src, const SkRect& dst,
1465                                  const SkPaint& paint,
1466                                  SkCanvas::DrawBitmapRectFlags flags) {
1467     SkMatrix    matrix;
1468     SkRect      bitmapBounds, tmpSrc;
1469
1470     bitmapBounds.set(0, 0,
1471                      SkIntToScalar(bitmap.width()),
1472                      SkIntToScalar(bitmap.height()));
1473
1474     // Compute matrix from the two rectangles
1475     if (NULL != src) {
1476         tmpSrc = *src;
1477     } else {
1478         tmpSrc = bitmapBounds;
1479     }
1480
1481     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
1482
1483     // clip the tmpSrc to the bounds of the bitmap. No check needed if src==null.
1484     if (NULL != src) {
1485         if (!bitmapBounds.contains(tmpSrc)) {
1486             if (!tmpSrc.intersect(bitmapBounds)) {
1487                 return; // nothing to draw
1488             }
1489         }
1490     }
1491
1492     SkRect tmpDst;
1493     matrix.mapRect(&tmpDst, tmpSrc);
1494
1495     SkTCopyOnFirstWrite<SkDraw> draw(origDraw);
1496     if (0 != tmpDst.fLeft || 0 != tmpDst.fTop) {
1497         // Translate so that tempDst's top left is at the origin.
1498         matrix = *origDraw.fMatrix;
1499         matrix.preTranslate(tmpDst.fLeft, tmpDst.fTop);
1500         draw.writable()->fMatrix = &matrix;
1501     }
1502     SkSize dstSize;
1503     dstSize.fWidth = tmpDst.width();
1504     dstSize.fHeight = tmpDst.height();
1505
1506     this->drawBitmapCommon(*draw, bitmap, &tmpSrc, &dstSize, paint, flags);
1507 }
1508
1509 void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
1510                              int x, int y, const SkPaint& paint) {
1511     // clear of the source device must occur before CHECK_SHOULD_DRAW
1512     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawDevice", fContext);
1513     SkGpuDevice* dev = static_cast<SkGpuDevice*>(device);
1514     if (dev->fNeedClear) {
1515         // TODO: could check here whether we really need to draw at all
1516         dev->clear(0x0);
1517     }
1518
1519     // drawDevice is defined to be in device coords.
1520     CHECK_SHOULD_DRAW(draw, true);
1521
1522     GrRenderTarget* devRT = dev->accessRenderTarget();
1523     GrTexture* devTex;
1524     if (NULL == (devTex = devRT->asTexture())) {
1525         return;
1526     }
1527
1528     const SkBitmap& bm = dev->accessBitmap(false);
1529     int w = bm.width();
1530     int h = bm.height();
1531
1532     SkImageFilter* filter = paint.getImageFilter();
1533     // This bitmap will own the filtered result as a texture.
1534     SkBitmap filteredBitmap;
1535
1536     if (NULL != filter) {
1537         SkIPoint offset = SkIPoint::Make(0, 0);
1538         SkMatrix matrix(*draw.fMatrix);
1539         matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
1540         SkIRect clipBounds = SkIRect::MakeWH(devTex->width(), devTex->height());
1541         // This cache is transient, and is freed (along with all its contained
1542         // textures) when it goes out of scope.
1543         SkAutoTUnref<SkImageFilter::Cache> cache(getImageFilterCache());
1544         SkImageFilter::Context ctx(matrix, clipBounds, cache);
1545         if (filter_texture(this, fContext, devTex, filter, w, h, ctx, &filteredBitmap,
1546                            &offset)) {
1547             devTex = filteredBitmap.getTexture();
1548             w = filteredBitmap.width();
1549             h = filteredBitmap.height();
1550             x += offset.fX;
1551             y += offset.fY;
1552         } else {
1553             return;
1554         }
1555     }
1556
1557     GrPaint grPaint;
1558     grPaint.addColorTextureEffect(devTex, SkMatrix::I());
1559
1560     SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColorJustAlpha(paint.getColor()),
1561                             false, &grPaint);
1562
1563     SkRect dstRect = SkRect::MakeXYWH(SkIntToScalar(x),
1564                                       SkIntToScalar(y),
1565                                       SkIntToScalar(w),
1566                                       SkIntToScalar(h));
1567
1568     // The device being drawn may not fill up its texture (e.g. saveLayer uses approximate
1569     // scratch texture).
1570     SkRect srcRect = SkRect::MakeWH(SK_Scalar1 * w / devTex->width(),
1571                                     SK_Scalar1 * h / devTex->height());
1572
1573     fContext->drawRectToRect(grPaint, dstRect, srcRect);
1574 }
1575
1576 bool SkGpuDevice::canHandleImageFilter(const SkImageFilter* filter) {
1577     return filter->canFilterImageGPU();
1578 }
1579
1580 bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
1581                               const SkImageFilter::Context& ctx,
1582                               SkBitmap* result, SkIPoint* offset) {
1583     // want explicitly our impl, so guard against a subclass of us overriding it
1584     if (!this->SkGpuDevice::canHandleImageFilter(filter)) {
1585         return false;
1586     }
1587
1588     SkAutoLockPixels alp(src, !src.getTexture());
1589     if (!src.getTexture() && !src.readyToDraw()) {
1590         return false;
1591     }
1592
1593     GrTexture* texture;
1594     // We assume here that the filter will not attempt to tile the src. Otherwise, this cache lookup
1595     // must be pushed upstack.
1596     SkAutoCachedTexture act(this, src, NULL, &texture);
1597
1598     return filter_texture(this, fContext, texture, filter, src.width(), src.height(), ctx,
1599                           result, offset);
1600 }
1601
1602 ///////////////////////////////////////////////////////////////////////////////
1603
1604 // must be in SkCanvas::VertexMode order
1605 static const GrPrimitiveType gVertexMode2PrimitiveType[] = {
1606     kTriangles_GrPrimitiveType,
1607     kTriangleStrip_GrPrimitiveType,
1608     kTriangleFan_GrPrimitiveType,
1609 };
1610
1611 void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
1612                               int vertexCount, const SkPoint vertices[],
1613                               const SkPoint texs[], const SkColor colors[],
1614                               SkXfermode* xmode,
1615                               const uint16_t indices[], int indexCount,
1616                               const SkPaint& paint) {
1617     CHECK_SHOULD_DRAW(draw, false);
1618
1619     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawVertices", fContext);
1620     
1621     const uint16_t* outIndices;
1622     SkAutoTDeleteArray<uint16_t> outAlloc(NULL);
1623     GrPrimitiveType primType;
1624     GrPaint grPaint;
1625
1626     // If both textures and vertex-colors are NULL, strokes hairlines with the paint's color.
1627     if ((NULL == texs || NULL == paint.getShader()) && NULL == colors) {
1628         
1629         texs = NULL;
1630         
1631         SkPaint copy(paint);
1632         copy.setStyle(SkPaint::kStroke_Style);
1633         copy.setStrokeWidth(0);
1634         
1635         // we ignore the shader if texs is null.
1636         SkPaint2GrPaintNoShader(this->context(), copy, SkColor2GrColor(copy.getColor()),
1637                                 NULL == colors, &grPaint);
1638
1639         primType = kLines_GrPrimitiveType;
1640         int triangleCount = 0;
1641         int n = (NULL == indices) ? vertexCount : indexCount;
1642         switch (vmode) {
1643             case SkCanvas::kTriangles_VertexMode:
1644                 triangleCount = n / 3;
1645                 break;
1646             case SkCanvas::kTriangleStrip_VertexMode:
1647             case SkCanvas::kTriangleFan_VertexMode:
1648                 triangleCount = n - 2;
1649                 break;
1650         }
1651         
1652         VertState       state(vertexCount, indices, indexCount);
1653         VertState::Proc vertProc = state.chooseProc(vmode);
1654         
1655         //number of indices for lines per triangle with kLines
1656         indexCount = triangleCount * 6;
1657         
1658         outAlloc.reset(SkNEW_ARRAY(uint16_t, indexCount));
1659         outIndices = outAlloc.get();
1660         uint16_t* auxIndices = outAlloc.get();
1661         int i = 0;
1662         while (vertProc(&state)) {
1663             auxIndices[i]     = state.f0;
1664             auxIndices[i + 1] = state.f1;
1665             auxIndices[i + 2] = state.f1;
1666             auxIndices[i + 3] = state.f2;
1667             auxIndices[i + 4] = state.f2;
1668             auxIndices[i + 5] = state.f0;
1669             i += 6;
1670         }
1671     } else {
1672         outIndices = indices;
1673         primType = gVertexMode2PrimitiveType[vmode];
1674         
1675         if (NULL == texs || NULL == paint.getShader()) {
1676             SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColor(paint.getColor()),
1677                                     NULL == colors, &grPaint);
1678         } else {
1679             SkPaint2GrPaintShader(this->context(), paint, NULL == colors, &grPaint);
1680         }
1681     }
1682
1683 #if 0
1684     if (NULL != xmode && NULL != texs && NULL != colors) {
1685         if (!SkXfermode::IsMode(xmode, SkXfermode::kModulate_Mode)) {
1686             SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
1687             return;
1688         }
1689     }
1690 #endif
1691
1692     SkAutoSTMalloc<128, GrColor> convertedColors(0);
1693     if (NULL != colors) {
1694         // need to convert byte order and from non-PM to PM
1695         convertedColors.reset(vertexCount);
1696         SkColor color;
1697         for (int i = 0; i < vertexCount; ++i) {
1698             color = colors[i];
1699             if (paint.getAlpha() != 255) {
1700                 color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paint.getAlpha()));
1701             }
1702             convertedColors[i] = SkColor2GrColor(color);
1703         }
1704         colors = convertedColors.get();
1705     }
1706     fContext->drawVertices(grPaint,
1707                            primType,
1708                            vertexCount,
1709                            vertices,
1710                            texs,
1711                            colors,
1712                            outIndices,
1713                            indexCount);
1714 }
1715
1716 ///////////////////////////////////////////////////////////////////////////////
1717
1718 void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
1719                           size_t byteLength, SkScalar x, SkScalar y,
1720                           const SkPaint& paint) {
1721     CHECK_SHOULD_DRAW(draw, false);
1722     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawText", fContext);
1723
1724     if (fMainTextContext->canDraw(paint)) {
1725         GrPaint grPaint;
1726         SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
1727
1728         SkDEBUGCODE(this->validate();)
1729
1730         fMainTextContext->drawText(grPaint, paint, (const char *)text, byteLength, x, y);
1731     } else if (fFallbackTextContext && fFallbackTextContext->canDraw(paint)) {
1732         GrPaint grPaint;
1733         SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
1734
1735         SkDEBUGCODE(this->validate();)
1736
1737         fFallbackTextContext->drawText(grPaint, paint, (const char *)text, byteLength, x, y);
1738     } else {
1739         // this guy will just call our drawPath()
1740         draw.drawText_asPaths((const char*)text, byteLength, x, y, paint);
1741     }
1742 }
1743
1744 void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
1745                              size_t byteLength, const SkScalar pos[],
1746                              SkScalar constY, int scalarsPerPos,
1747                              const SkPaint& paint) {
1748     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPosText", fContext);
1749     CHECK_SHOULD_DRAW(draw, false);
1750
1751     if (fMainTextContext->canDraw(paint)) {
1752         GrPaint grPaint;
1753         SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
1754
1755         SkDEBUGCODE(this->validate();)
1756
1757         fMainTextContext->drawPosText(grPaint, paint, (const char *)text, byteLength, pos,
1758                                       constY, scalarsPerPos);
1759     } else if (fFallbackTextContext && fFallbackTextContext->canDraw(paint)) {
1760         GrPaint grPaint;
1761         SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
1762
1763         SkDEBUGCODE(this->validate();)
1764
1765         fFallbackTextContext->drawPosText(grPaint, paint, (const char *)text, byteLength, pos,
1766                                           constY, scalarsPerPos);
1767     } else {
1768         draw.drawPosText_asPaths((const char*)text, byteLength, pos, constY,
1769                                  scalarsPerPos, paint);
1770     }
1771 }
1772
1773 void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
1774                                 size_t len, const SkPath& path,
1775                                 const SkMatrix* m, const SkPaint& paint) {
1776     CHECK_SHOULD_DRAW(draw, false);
1777
1778     SkASSERT(draw.fDevice == this);
1779     draw.drawTextOnPath((const char*)text, len, path, m, paint);
1780 }
1781
1782 ///////////////////////////////////////////////////////////////////////////////
1783
1784 bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
1785     if (!paint.isLCDRenderText()) {
1786         // we're cool with the paint as is
1787         return false;
1788     }
1789
1790     if (paint.getShader() ||
1791         paint.getXfermode() || // unless its srcover
1792         paint.getMaskFilter() ||
1793         paint.getRasterizer() ||
1794         paint.getColorFilter() ||
1795         paint.getPathEffect() ||
1796         paint.isFakeBoldText() ||
1797         paint.getStyle() != SkPaint::kFill_Style) {
1798         // turn off lcd
1799         flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
1800         flags->fHinting = paint.getHinting();
1801         return true;
1802     }
1803     // we're cool with the paint as is
1804     return false;
1805 }
1806
1807 void SkGpuDevice::flush() {
1808     DO_DEFERRED_CLEAR();
1809     fContext->resolveRenderTarget(fRenderTarget);
1810 }
1811
1812 ///////////////////////////////////////////////////////////////////////////////
1813
1814 SkBaseDevice* SkGpuDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
1815     GrTextureDesc desc;
1816     desc.fConfig = fRenderTarget->config();
1817     desc.fFlags = kRenderTarget_GrTextureFlagBit;
1818     desc.fWidth = info.width();
1819     desc.fHeight = info.height();
1820     desc.fSampleCnt = fRenderTarget->numSamples();
1821
1822     SkAutoTUnref<GrTexture> texture;
1823     // Skia's convention is to only clear a device if it is non-opaque.
1824     unsigned flags = info.isOpaque() ? 0 : kNeedClear_Flag;
1825
1826 #if CACHE_COMPATIBLE_DEVICE_TEXTURES
1827     // layers are never draw in repeat modes, so we can request an approx
1828     // match and ignore any padding.
1829     flags |= kCached_Flag;
1830     const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == usage) ?
1831                                                 GrContext::kApprox_ScratchTexMatch :
1832                                                 GrContext::kExact_ScratchTexMatch;
1833     texture.reset(fContext->lockAndRefScratchTexture(desc, match));
1834 #else
1835     texture.reset(fContext->createUncachedTexture(desc, NULL, 0));
1836 #endif
1837     if (NULL != texture.get()) {
1838         return SkGpuDevice::Create(texture, flags);
1839     } else {
1840         GrPrintf("---- failed to create compatible device texture [%d %d]\n",
1841                  info.width(), info.height());
1842         return NULL;
1843     }
1844 }
1845
1846 SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info) {
1847     return SkSurface::NewRenderTarget(fContext, info, fRenderTarget->numSamples());
1848 }
1849
1850 void SkGpuDevice::EXPERIMENTAL_optimize(const SkPicture* picture) {
1851     fContext->getLayerCache()->processDeletedPictures();
1852
1853     if (NULL != picture->fData.get() && !picture->fData->suitableForLayerOptimization()) {
1854         return;
1855     }
1856
1857     SkPicture::AccelData::Key key = GPUAccelData::ComputeAccelDataKey();
1858
1859     const SkPicture::AccelData* existing = picture->EXPERIMENTAL_getAccelData(key);
1860     if (NULL != existing) {
1861         return;
1862     }
1863
1864     SkAutoTUnref<GPUAccelData> data(SkNEW_ARGS(GPUAccelData, (key)));
1865
1866     picture->EXPERIMENTAL_addAccelData(data);
1867
1868     GatherGPUInfo(picture, data);
1869
1870     fContext->getLayerCache()->trackPicture(picture);
1871 }
1872
1873 static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
1874     SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1875     result->setInfo(info);
1876     result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
1877 }
1878
1879 bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture* picture,
1880                                            const SkMatrix* matrix, const SkPaint* paint) {
1881     // todo: should handle these natively
1882     if (matrix || paint) {
1883         return false;
1884     }
1885
1886     fContext->getLayerCache()->processDeletedPictures();
1887
1888     SkPicture::AccelData::Key key = GPUAccelData::ComputeAccelDataKey();
1889
1890     const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
1891     if (NULL == data) {
1892         return false;
1893     }
1894
1895     const GPUAccelData *gpuData = static_cast<const GPUAccelData*>(data);
1896
1897     if (0 == gpuData->numSaveLayers()) {
1898         return false;
1899     }
1900
1901     SkAutoTArray<bool> pullForward(gpuData->numSaveLayers());
1902     for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
1903         pullForward[i] = false;
1904     }
1905
1906     SkRect clipBounds;
1907     if (!mainCanvas->getClipBounds(&clipBounds)) {
1908         return true;
1909     }
1910     SkIRect query;
1911     clipBounds.roundOut(&query);
1912
1913     SkAutoTDelete<const SkPicture::OperationList> ops(picture->EXPERIMENTAL_getActiveOps(query));
1914
1915     // This code pre-renders the entire layer since it will be cached and potentially
1916     // reused with different clips (e.g., in different tiles). Because of this the
1917     // clip will not be limiting the size of the pre-rendered layer. kSaveLayerMaxSize
1918     // is used to limit which clips are pre-rendered.
1919     static const int kSaveLayerMaxSize = 256;
1920
1921     if (NULL != ops.get()) {
1922         // In this case the picture has been generated with a BBH so we use
1923         // the BBH to limit the pre-rendering to just the layers needed to cover
1924         // the region being drawn
1925         for (int i = 0; i < ops->numOps(); ++i) {
1926             uint32_t offset = ops->offset(i);
1927
1928             // For now we're saving all the layers in the GPUAccelData so they
1929             // can be nested. Additionally, the nested layers appear before
1930             // their parent in the list.
1931             for (int j = 0 ; j < gpuData->numSaveLayers(); ++j) {
1932                 const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
1933
1934                 if (pullForward[j]) {
1935                     continue;            // already pulling forward
1936                 }
1937
1938                 if (offset < info.fSaveLayerOpID || offset > info.fRestoreOpID) {
1939                     continue;            // the op isn't in this range
1940                 }
1941
1942                 // TODO: once this code is more stable unsuitable layers can
1943                 // just be omitted during the optimization stage
1944                 if (!info.fValid ||
1945                     kSaveLayerMaxSize < info.fSize.fWidth ||
1946                     kSaveLayerMaxSize < info.fSize.fHeight ||
1947                     info.fIsNested) {
1948                     continue;            // this layer is unsuitable
1949                 }
1950
1951                 pullForward[j] = true;
1952             }
1953         }
1954     } else {
1955         // In this case there is no BBH associated with the picture. Pre-render
1956         // all the layers that intersect the drawn region
1957         for (int j = 0; j < gpuData->numSaveLayers(); ++j) {
1958             const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
1959
1960             SkIRect layerRect = SkIRect::MakeXYWH(info.fOffset.fX,
1961                                                   info.fOffset.fY,
1962                                                   info.fSize.fWidth,
1963                                                   info.fSize.fHeight);
1964
1965             if (!SkIRect::Intersects(query, layerRect)) {
1966                 continue;
1967             }
1968
1969             // TODO: once this code is more stable unsuitable layers can
1970             // just be omitted during the optimization stage
1971             if (!info.fValid ||
1972                 kSaveLayerMaxSize < info.fSize.fWidth ||
1973                 kSaveLayerMaxSize < info.fSize.fHeight ||
1974                 info.fIsNested) {
1975                 continue;
1976             }
1977
1978             pullForward[j] = true;
1979         }
1980     }
1981
1982     SkPictureReplacementPlayback::PlaybackReplacements replacements;
1983
1984     SkTDArray<GrCachedLayer*> atlased, nonAtlased;
1985     atlased.setReserve(gpuData->numSaveLayers());
1986
1987     // Generate the layer and/or ensure it is locked
1988     for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
1989         if (pullForward[i]) {
1990             const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
1991
1992             GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, 
1993                                                                                 info.fSaveLayerOpID, 
1994                                                                                 info.fRestoreOpID, 
1995                                                                                 info.fCTM);
1996
1997             SkPictureReplacementPlayback::PlaybackReplacements::ReplacementInfo* layerInfo =
1998                                                                         replacements.push();
1999             layerInfo->fStart = info.fSaveLayerOpID;
2000             layerInfo->fStop = info.fRestoreOpID;
2001             layerInfo->fPos = info.fOffset;
2002
2003             GrTextureDesc desc;
2004             desc.fFlags = kRenderTarget_GrTextureFlagBit;
2005             desc.fWidth = info.fSize.fWidth;
2006             desc.fHeight = info.fSize.fHeight;
2007             desc.fConfig = kSkia8888_GrPixelConfig;
2008             // TODO: need to deal with sample count
2009
2010             bool needsRendering = !fContext->getLayerCache()->lock(layer, desc);
2011             if (NULL == layer->texture()) {
2012                 continue;
2013             }
2014
2015             layerInfo->fBM = SkNEW(SkBitmap);  // fBM is allocated so ReplacementInfo can be POD
2016             wrap_texture(layer->texture(), 
2017                          !layer->isAtlased() ? desc.fWidth : layer->texture()->width(),
2018                          !layer->isAtlased() ? desc.fHeight : layer->texture()->height(),
2019                          layerInfo->fBM);
2020
2021             SkASSERT(info.fPaint);
2022             layerInfo->fPaint = info.fPaint;
2023
2024             layerInfo->fSrcRect = SkIRect::MakeXYWH(layer->rect().fLeft,
2025                                                     layer->rect().fTop,
2026                                                     layer->rect().width(),
2027                                                     layer->rect().height());
2028
2029             if (needsRendering) {
2030                 if (layer->isAtlased()) {
2031                     *atlased.append() = layer;
2032                 } else {
2033                     *nonAtlased.append() = layer;
2034                 }
2035             }
2036         }
2037     }
2038
2039     // Render the atlased layers that require it
2040     if (atlased.count() > 0) {
2041         // All the atlased layers are rendered into the same GrTexture
2042         SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
2043                                         atlased[0]->texture()->asRenderTarget(),
2044                                         SkSurface::kStandard_TextRenderMode,
2045                                         SkSurface::kDontClear_RenderTargetFlag));
2046
2047         SkCanvas* atlasCanvas = surface->getCanvas();
2048
2049         SkPaint paint;
2050         paint.setColor(SK_ColorTRANSPARENT);
2051         paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();
2052
2053         for (int i = 0; i < atlased.count(); ++i) {
2054             GrCachedLayer* layer = atlased[i];
2055
2056             atlasCanvas->save();
2057
2058             // Add a rect clip to make sure the rendering doesn't
2059             // extend beyond the boundaries of the atlased sub-rect
2060             SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
2061                                             SkIntToScalar(layer->rect().fTop),
2062                                             SkIntToScalar(layer->rect().width()),
2063                                             SkIntToScalar(layer->rect().height()));
2064             atlasCanvas->clipRect(bound);
2065
2066             // Since 'clear' doesn't respect the clip we need to draw a rect
2067             // TODO: ensure none of the atlased layers contain a clear call!
2068             atlasCanvas->drawRect(bound, paint);
2069
2070             // info.fCTM maps the layer's top/left to the origin.
2071             // Since this layer is atlased, the top/left corner needs
2072             // to be offset to the correct location in the backing texture.
2073             atlasCanvas->translate(bound.fLeft, bound.fTop);
2074             atlasCanvas->concat(layer->ctm());
2075
2076             SkPictureRangePlayback rangePlayback(picture,
2077                                                  layer->start(),
2078                                                  layer->stop());
2079             rangePlayback.draw(atlasCanvas, NULL);
2080
2081             atlasCanvas->restore();
2082         }
2083
2084         atlasCanvas->flush();
2085     }
2086
2087     // Render the non-atlased layers that require it
2088     for (int i = 0; i < nonAtlased.count(); ++i) {
2089         GrCachedLayer* layer = nonAtlased[i];
2090
2091         // Each non-atlased layer has its own GrTexture
2092         SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
2093                                         layer->texture()->asRenderTarget(),
2094                                         SkSurface::kStandard_TextRenderMode,
2095                                         SkSurface::kDontClear_RenderTargetFlag));
2096
2097         SkCanvas* layerCanvas = surface->getCanvas();
2098
2099         // Add a rect clip to make sure the rendering doesn't
2100         // extend beyond the boundaries of the atlased sub-rect
2101         SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
2102                                         SkIntToScalar(layer->rect().fTop),
2103                                         SkIntToScalar(layer->rect().width()),
2104                                         SkIntToScalar(layer->rect().height()));
2105
2106         layerCanvas->clipRect(bound); // TODO: still useful?
2107
2108         layerCanvas->clear(SK_ColorTRANSPARENT);
2109
2110         layerCanvas->concat(layer->ctm());
2111
2112         SkPictureRangePlayback rangePlayback(picture,
2113                                              layer->start(),
2114                                              layer->stop());
2115         rangePlayback.draw(layerCanvas, NULL);
2116
2117         layerCanvas->flush();
2118     }
2119
2120     // Render the entire picture using new layers
2121     SkPictureReplacementPlayback playback(picture, &replacements, ops.get());
2122
2123     playback.draw(mainCanvas, NULL);
2124
2125     // unlock the layers
2126     for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
2127         const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
2128
2129         GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture, 
2130                                                                     info.fSaveLayerOpID,
2131                                                                     info.fRestoreOpID,
2132                                                                     info.fCTM);
2133         fContext->getLayerCache()->unlock(layer);
2134     }
2135
2136     return true;
2137 }
2138
2139 SkImageFilter::Cache* SkGpuDevice::getImageFilterCache() {
2140     // We always return a transient cache, so it is freed after each
2141     // filter traversal.
2142     return SkImageFilter::Cache::Create(kDefaultImageFilterCacheSize);
2143 }