OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2008 The Android Open Source Project | 2 * Copyright 2008 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCanvas.h" | 8 #include "SkCanvas.h" |
9 #include "SkCanvasPriv.h" | 9 #include "SkCanvasPriv.h" |
10 #include "SkBitmapDevice.h" | 10 #include "SkBitmapDevice.h" |
11 #include "SkColorFilter.h" | 11 #include "SkColorFilter.h" |
12 #include "SkDraw.h" | 12 #include "SkDraw.h" |
13 #include "SkDrawable.h" | 13 #include "SkDrawable.h" |
14 #include "SkDrawFilter.h" | 14 #include "SkDrawFilter.h" |
15 #include "SkDrawLooper.h" | 15 #include "SkDrawLooper.h" |
16 #include "SkErrorInternals.h" | 16 #include "SkErrorInternals.h" |
17 #include "SkImage.h" | 17 #include "SkImage.h" |
18 #include "SkMetaData.h" | 18 #include "SkMetaData.h" |
19 #include "SkNinePatchIter.h" | 19 #include "SkNinePatchIter.h" |
20 #include "SkPaintPriv.h" | |
20 #include "SkPathOps.h" | 21 #include "SkPathOps.h" |
21 #include "SkPatchUtils.h" | 22 #include "SkPatchUtils.h" |
22 #include "SkPicture.h" | 23 #include "SkPicture.h" |
23 #include "SkRasterClip.h" | 24 #include "SkRasterClip.h" |
24 #include "SkReadPixelsRec.h" | 25 #include "SkReadPixelsRec.h" |
25 #include "SkRRect.h" | 26 #include "SkRRect.h" |
26 #include "SkSmallAllocator.h" | 27 #include "SkSmallAllocator.h" |
27 #include "SkSurface_Base.h" | 28 #include "SkSurface_Base.h" |
28 #include "SkTemplates.h" | 29 #include "SkTemplates.h" |
29 #include "SkTextBlob.h" | 30 #include "SkTextBlob.h" |
30 #include "SkTextFormatParams.h" | 31 #include "SkTextFormatParams.h" |
31 #include "SkTLazy.h" | 32 #include "SkTLazy.h" |
32 #include "SkTraceEvent.h" | 33 #include "SkTraceEvent.h" |
33 #include "SkUtils.h" | 34 #include "SkUtils.h" |
34 | 35 |
35 #if SK_SUPPORT_GPU | 36 #if SK_SUPPORT_GPU |
36 #include "GrRenderTarget.h" | 37 #include "GrRenderTarget.h" |
37 #endif | 38 #endif |
38 | 39 |
40 /* | |
41 * Return true if the drawing this rect would hit every pixels in the canvas. | |
42 * | |
43 * Returns false if | |
44 * - rect does not contain the canvas' bounds | |
45 * - paint is not fill | |
46 * - paint would blur or otherwise change the coverage of the rect | |
47 */ | |
48 bool SkCanvas::willOverwriteAllPixels(const SkRect* rect, const SkPaint* paint, | |
Justin Novosad
2015/07/15 18:00:46
"will" is ambiguous and can be interpreted as a de
reed1
2015/07/15 21:41:02
Done.
| |
49 bool auxOpaque) const { | |
50 const SkISize size = this->getBaseLayerSize(); | |
51 const SkRect bounds = SkRect::MakeIWH(size.width(), size.height()); | |
52 if (!this->getClipStack()->quickContains(bounds)) { | |
53 return false; | |
54 } | |
55 | |
56 if (rect) { | |
57 if (!this->getTotalMatrix().rectStaysRect()) { | |
58 return false; // conservative | |
59 } | |
60 | |
61 SkRect devRect; | |
62 this->getTotalMatrix().mapRect(&devRect, *rect); | |
63 | |
64 if (paint) { | |
65 SkPaint::Style paintStyle = paint->getStyle(); | |
66 if (!(paintStyle == SkPaint::kFill_Style || | |
67 paintStyle == SkPaint::kStrokeAndFill_Style)) { | |
68 return false; | |
69 } | |
70 if (paint->getMaskFilter() || paint->getLooper() | |
71 || paint->getPathEffect() || paint->getImageFilter()) { | |
72 return false; // conservative | |
73 } | |
74 } | |
75 | |
76 if (devRect.contains(bounds)) { | |
77 return false; | |
78 } | |
79 } | |
80 return true; | |
81 } | |
82 | |
83 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
84 | |
39 static bool gIgnoreSaveLayerBounds; | 85 static bool gIgnoreSaveLayerBounds; |
40 void SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) { | 86 void SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) { |
41 gIgnoreSaveLayerBounds = ignore; | 87 gIgnoreSaveLayerBounds = ignore; |
42 } | 88 } |
43 bool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() { | 89 bool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() { |
44 return gIgnoreSaveLayerBounds; | 90 return gIgnoreSaveLayerBounds; |
45 } | 91 } |
46 | 92 |
47 static bool gTreatSpriteAsBitmap; | 93 static bool gTreatSpriteAsBitmap; |
48 void SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) { | 94 void SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) { |
(...skipping 24 matching lines...) Expand all Loading... | |
73 #define inc_layer() | 119 #define inc_layer() |
74 #define dec_layer() | 120 #define dec_layer() |
75 #define inc_rec() | 121 #define inc_rec() |
76 #define dec_rec() | 122 #define dec_rec() |
77 #define inc_canvas() | 123 #define inc_canvas() |
78 #define dec_canvas() | 124 #define dec_canvas() |
79 #endif | 125 #endif |
80 | 126 |
81 typedef SkTLazy<SkPaint> SkLazyPaint; | 127 typedef SkTLazy<SkPaint> SkLazyPaint; |
82 | 128 |
83 void SkCanvas::predrawNotify() { | 129 void SkCanvas::predrawNotify(bool completeOverwrite) { |
84 if (fSurfaceBase) { | 130 if (fSurfaceBase) { |
85 fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode); | 131 fSurfaceBase->aboutToDraw(completeOverwrite ? SkSurface::kDiscard_Conten tChangeMode |
132 : SkSurface::kRetain_Content ChangeMode); | |
86 } | 133 } |
87 } | 134 } |
88 | 135 |
136 void SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint, bool auxO paque) { | |
137 if (fSurfaceBase) { | |
138 SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode ; | |
139 // Since willOverwriteAllPixels() may not be complete free to call, we o nly do so if | |
140 // there is an outstanding snapshot, since w/o that, there will be no co py-on-write | |
141 // and therefore we don't care which mode we're in. | |
142 // | |
143 if (fSurfaceBase->outstandingImageSnapshot()) { | |
Justin Novosad
2015/07/15 18:00:46
+1 This is a an interesting optimization
| |
144 if (this->willOverwriteAllPixels(rect, paint, auxOpaque)) { | |
145 mode = SkSurface::kDiscard_ContentChangeMode; | |
146 } | |
147 } | |
148 fSurfaceBase->aboutToDraw(mode); | |
149 } | |
150 } | |
151 | |
89 /////////////////////////////////////////////////////////////////////////////// | 152 /////////////////////////////////////////////////////////////////////////////// |
90 | 153 |
91 static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) { | 154 static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) { |
92 const uint32_t propFlags = props.flags(); | 155 const uint32_t propFlags = props.flags(); |
93 if (propFlags & SkSurfaceProps::kDisallowDither_Flag) { | 156 if (propFlags & SkSurfaceProps::kDisallowDither_Flag) { |
94 flags &= ~SkPaint::kDither_Flag; | 157 flags &= ~SkPaint::kDither_Flag; |
95 } | 158 } |
96 if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) { | 159 if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) { |
97 flags &= ~SkPaint::kAntiAlias_Flag; | 160 flags &= ~SkPaint::kAntiAlias_Flag; |
98 } | 161 } |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
490 AutoDrawLooper looper(this, fProps, paint, true); \ | 553 AutoDrawLooper looper(this, fProps, paint, true); \ |
491 while (looper.next(type)) { \ | 554 while (looper.next(type)) { \ |
492 SkDrawIter iter(this); | 555 SkDrawIter iter(this); |
493 | 556 |
494 #define LOOPER_BEGIN(paint, type, bounds) \ | 557 #define LOOPER_BEGIN(paint, type, bounds) \ |
495 this->predrawNotify(); \ | 558 this->predrawNotify(); \ |
496 AutoDrawLooper looper(this, fProps, paint, false, bounds); \ | 559 AutoDrawLooper looper(this, fProps, paint, false, bounds); \ |
497 while (looper.next(type)) { \ | 560 while (looper.next(type)) { \ |
498 SkDrawIter iter(this); | 561 SkDrawIter iter(this); |
499 | 562 |
563 #define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque) \ | |
564 this->predrawNotify(bounds, &paint, auxOpaque); \ | |
565 AutoDrawLooper looper(this, fProps, paint, false, bounds); \ | |
566 while (looper.next(type)) { \ | |
567 SkDrawIter iter(this); | |
568 | |
500 #define LOOPER_END } | 569 #define LOOPER_END } |
501 | 570 |
502 //////////////////////////////////////////////////////////////////////////// | 571 //////////////////////////////////////////////////////////////////////////// |
503 | 572 |
504 void SkCanvas::resetForNextPicture(const SkIRect& bounds) { | 573 void SkCanvas::resetForNextPicture(const SkIRect& bounds) { |
505 this->restoreToCount(1); | 574 this->restoreToCount(1); |
506 fCachedLocalClipBounds.setEmpty(); | 575 fCachedLocalClipBounds.setEmpty(); |
507 fCachedLocalClipBoundsDirty = true; | 576 fCachedLocalClipBoundsDirty = true; |
508 fClipStack->reset(); | 577 fClipStack->reset(); |
509 fMCRec->reset(bounds); | 578 fMCRec->reset(bounds); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
808 if (x > 0) { | 877 if (x > 0) { |
809 x = 0; | 878 x = 0; |
810 } | 879 } |
811 if (y > 0) { | 880 if (y > 0) { |
812 y = 0; | 881 y = 0; |
813 } | 882 } |
814 // here x,y are either 0 or negative | 883 // here x,y are either 0 or negative |
815 pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel()); | 884 pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel()); |
816 | 885 |
817 // Tell our owning surface to bump its generation ID | 886 // Tell our owning surface to bump its generation ID |
818 this->predrawNotify(); | 887 const bool completeOverwrite = info.dimensions() == size; |
888 this->predrawNotify(completeOverwrite); | |
819 | 889 |
820 // The device can assert that the requested area is always contained in its bounds | 890 // The device can assert that the requested area is always contained in its bounds |
821 return device->writePixels(info, pixels, rowBytes, target.x(), target.y()); | 891 return device->writePixels(info, pixels, rowBytes, target.x(), target.y()); |
822 } | 892 } |
823 | 893 |
824 SkCanvas* SkCanvas::canvasForDrawIter() { | 894 SkCanvas* SkCanvas::canvasForDrawIter() { |
825 return this; | 895 return this; |
826 } | 896 } |
827 | 897 |
828 ////////////////////////////////////////////////////////////////////////////// | 898 ////////////////////////////////////////////////////////////////////////////// |
(...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1845 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); | 1915 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); |
1846 } | 1916 } |
1847 } | 1917 } |
1848 | 1918 |
1849 void SkCanvas::onDrawPaint(const SkPaint& paint) { | 1919 void SkCanvas::onDrawPaint(const SkPaint& paint) { |
1850 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); | 1920 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); |
1851 this->internalDrawPaint(paint); | 1921 this->internalDrawPaint(paint); |
1852 } | 1922 } |
1853 | 1923 |
1854 void SkCanvas::internalDrawPaint(const SkPaint& paint) { | 1924 void SkCanvas::internalDrawPaint(const SkPaint& paint) { |
1855 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) | 1925 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, NULL ) |
1856 | 1926 |
1857 while (iter.next()) { | 1927 while (iter.next()) { |
1858 iter.fDevice->drawPaint(iter, looper.paint()); | 1928 iter.fDevice->drawPaint(iter, looper.paint()); |
1859 } | 1929 } |
1860 | 1930 |
1861 LOOPER_END | 1931 LOOPER_END |
1862 } | 1932 } |
1863 | 1933 |
1864 void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], | 1934 void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], |
1865 const SkPaint& paint) { | 1935 const SkPaint& paint) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1903 // To prevent accidental rejecting at this stage, we have to sort it bef ore we check. | 1973 // To prevent accidental rejecting at this stage, we have to sort it bef ore we check. |
1904 SkRect tmp(r); | 1974 SkRect tmp(r); |
1905 tmp.sort(); | 1975 tmp.sort(); |
1906 | 1976 |
1907 bounds = &paint.computeFastBounds(tmp, &storage); | 1977 bounds = &paint.computeFastBounds(tmp, &storage); |
1908 if (this->quickReject(*bounds)) { | 1978 if (this->quickReject(*bounds)) { |
1909 return; | 1979 return; |
1910 } | 1980 } |
1911 } | 1981 } |
1912 | 1982 |
1913 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds) | 1983 LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bound s) |
1914 | 1984 |
1915 while (iter.next()) { | 1985 while (iter.next()) { |
1916 iter.fDevice->drawRect(iter, r, looper.paint()); | 1986 iter.fDevice->drawRect(iter, r, looper.paint()); |
1917 } | 1987 } |
1918 | 1988 |
1919 LOOPER_END | 1989 LOOPER_END |
1920 } | 1990 } |
1921 | 1991 |
1922 void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { | 1992 void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { |
1923 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); | 1993 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2769 } | 2839 } |
2770 | 2840 |
2771 if (matrix) { | 2841 if (matrix) { |
2772 canvas->concat(*matrix); | 2842 canvas->concat(*matrix); |
2773 } | 2843 } |
2774 } | 2844 } |
2775 | 2845 |
2776 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { | 2846 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { |
2777 fCanvas->restoreToCount(fSaveCount); | 2847 fCanvas->restoreToCount(fSaveCount); |
2778 } | 2848 } |
OLD | NEW |