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

Side by Side Diff: src/core/SkCanvas.cpp

Issue 1236023004: have canvas send discard instead of retain if the draw would overwrite everything (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: wip Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/core/SkCanvas.h ('k') | src/image/SkSurface.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * 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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « include/core/SkCanvas.h ('k') | src/image/SkSurface.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698