OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "platform/graphics/RecordingImageBufferSurface.h" | 5 #include "platform/graphics/RecordingImageBufferSurface.h" |
6 | 6 |
7 #include "platform/graphics/CanvasMetrics.h" | 7 #include "platform/graphics/CanvasMetrics.h" |
8 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" | 8 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" |
9 #include "platform/graphics/GraphicsContext.h" | 9 #include "platform/graphics/GraphicsContext.h" |
10 #include "platform/graphics/ImageBuffer.h" | 10 #include "platform/graphics/ImageBuffer.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 , m_currentFrameHasExpensiveOp(false) | 26 , m_currentFrameHasExpensiveOp(false) |
27 , m_previousFrameHasExpensiveOp(false) | 27 , m_previousFrameHasExpensiveOp(false) |
28 , m_fallbackFactory(std::move(fallbackFactory)) | 28 , m_fallbackFactory(std::move(fallbackFactory)) |
29 { | 29 { |
30 initializeCurrentFrame(); | 30 initializeCurrentFrame(); |
31 } | 31 } |
32 | 32 |
33 RecordingImageBufferSurface::~RecordingImageBufferSurface() | 33 RecordingImageBufferSurface::~RecordingImageBufferSurface() |
34 { } | 34 { } |
35 | 35 |
36 bool RecordingImageBufferSurface::initializeCurrentFrame() | 36 void RecordingImageBufferSurface::initializeCurrentFrame() |
37 { | 37 { |
38 static SkRTreeFactory rTreeFactory; | 38 static SkRTreeFactory rTreeFactory; |
39 m_currentFrame = adoptPtr(new SkPictureRecorder); | 39 m_currentFrame = adoptPtr(new SkPictureRecorder); |
40 m_currentFrame->beginRecording(size().width(), size().height(), &rTreeFactor
y); | 40 m_currentFrame->beginRecording(size().width(), size().height(), &rTreeFactor
y); |
41 if (m_imageBuffer) { | 41 if (m_imageBuffer) { |
42 m_imageBuffer->resetCanvas(m_currentFrame->getRecordingCanvas()); | 42 m_imageBuffer->resetCanvas(m_currentFrame->getRecordingCanvas()); |
43 } | 43 } |
44 m_didRecordDrawCommandsInCurrentFrame = false; | 44 m_didRecordDrawCommandsInCurrentFrame = false; |
45 m_currentFrameHasExpensiveOp = false; | 45 m_currentFrameHasExpensiveOp = false; |
46 m_currentFramePixelCount = 0; | 46 m_currentFramePixelCount = 0; |
47 return true; | |
48 } | 47 } |
49 | 48 |
50 void RecordingImageBufferSurface::setImageBuffer(ImageBuffer* imageBuffer) | 49 void RecordingImageBufferSurface::setImageBuffer(ImageBuffer* imageBuffer) |
51 { | 50 { |
52 m_imageBuffer = imageBuffer; | 51 m_imageBuffer = imageBuffer; |
53 if (m_currentFrame && m_imageBuffer) { | 52 if (m_currentFrame && m_imageBuffer) { |
54 m_imageBuffer->resetCanvas(m_currentFrame->getRecordingCanvas()); | 53 m_imageBuffer->resetCanvas(m_currentFrame->getRecordingCanvas()); |
55 } | 54 } |
56 if (m_fallbackSurface) { | 55 if (m_fallbackSurface) { |
57 m_fallbackSurface->setImageBuffer(imageBuffer); | 56 m_fallbackSurface->setImageBuffer(imageBuffer); |
58 } | 57 } |
59 } | 58 } |
60 | 59 |
61 bool RecordingImageBufferSurface::writePixels(const SkImageInfo& origInfo, const
void* pixels, size_t rowBytes, int x, int y) | 60 bool RecordingImageBufferSurface::writePixels(const SkImageInfo& origInfo, const
void* pixels, size_t rowBytes, int x, int y) |
62 { | 61 { |
63 if (!m_fallbackSurface) { | 62 if (!m_fallbackSurface) { |
64 if (x <= 0 && y <= 0 && x + origInfo.width() >= size().width() && y + or
igInfo.height() >= size().height()) { | 63 if (x <= 0 && y <= 0 && x + origInfo.width() >= size().width() && y + or
igInfo.height() >= size().height()) { |
65 willOverwriteCanvas(); | 64 willOverwriteCanvas(); |
66 } | 65 } |
67 fallBackToRasterCanvas(); | 66 fallBackToRasterCanvas(FallbackReasonWritePixels); |
68 } | 67 } |
69 return m_fallbackSurface->writePixels(origInfo, pixels, rowBytes, x, y); | 68 return m_fallbackSurface->writePixels(origInfo, pixels, rowBytes, x, y); |
70 } | 69 } |
71 | 70 |
72 void RecordingImageBufferSurface::fallBackToRasterCanvas() | 71 void RecordingImageBufferSurface::fallBackToRasterCanvas(FallbackReason reason) |
73 { | 72 { |
74 if (m_fallbackSurface) { | 73 if (m_fallbackSurface) { |
75 ASSERT(!m_currentFrame); | 74 ASSERT(!m_currentFrame); |
76 return; | 75 return; |
77 } | 76 } |
78 | 77 |
| 78 Platform::current()->histogramEnumeration("Canvas.DisplayListFallbackReason"
, reason, FallbackReasonCount); |
| 79 |
79 m_fallbackSurface = m_fallbackFactory->createSurface(size(), opacityMode()); | 80 m_fallbackSurface = m_fallbackFactory->createSurface(size(), opacityMode()); |
80 m_fallbackSurface->setImageBuffer(m_imageBuffer); | 81 m_fallbackSurface->setImageBuffer(m_imageBuffer); |
81 | 82 |
82 if (m_previousFrame) { | 83 if (m_previousFrame) { |
83 m_previousFrame->playback(m_fallbackSurface->canvas()); | 84 m_previousFrame->playback(m_fallbackSurface->canvas()); |
84 m_previousFrame.clear(); | 85 m_previousFrame.clear(); |
85 } | 86 } |
86 | 87 |
87 if (m_currentFrame) { | 88 if (m_currentFrame) { |
88 RefPtr<SkPicture> currentPicture = adoptRef(m_currentFrame->endRecording
()); | 89 RefPtr<SkPicture> currentPicture = adoptRef(m_currentFrame->endRecording
()); |
89 currentPicture->playback(m_fallbackSurface->canvas()); | 90 currentPicture->playback(m_fallbackSurface->canvas()); |
90 m_currentFrame.clear(); | 91 m_currentFrame.clear(); |
91 } | 92 } |
92 | 93 |
93 if (m_imageBuffer) { | 94 if (m_imageBuffer) { |
94 m_imageBuffer->resetCanvas(m_fallbackSurface->canvas()); | 95 m_imageBuffer->resetCanvas(m_fallbackSurface->canvas()); |
95 } | 96 } |
96 | 97 |
97 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::DisplayList2DCanvasFal
lbackToRaster); | 98 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::DisplayList2DCanvasFal
lbackToRaster); |
98 } | 99 } |
99 | 100 |
100 PassRefPtr<SkImage> RecordingImageBufferSurface::newImageSnapshot(AccelerationHi
nt hint) | 101 static RecordingImageBufferSurface::FallbackReason snapshotReasonToFallbackReaso
n(SnapshotReason reason) |
| 102 { |
| 103 switch (reason) { |
| 104 case SnapshotReasonUnknown: |
| 105 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 106 case SnapshotReasonGetImageData: |
| 107 return RecordingImageBufferSurface::FallbackReasonSnapshotForGetImageDat
a; |
| 108 case SnapshotReasonCopyToWebGLTexture: |
| 109 return RecordingImageBufferSurface::FallbackReasonSnapshotForCopyToWebGL
Texture; |
| 110 case SnapshotReasonPaint: |
| 111 return RecordingImageBufferSurface::FallbackReasonSnapshotForPaint; |
| 112 case SnapshotReasonToDataURL: |
| 113 return RecordingImageBufferSurface::FallbackReasonSnapshotForToDataURL; |
| 114 case SnapshotReasonToBlob: |
| 115 return RecordingImageBufferSurface::FallbackReasonSnapshotForToBlob; |
| 116 case SnapshotReasonCanvasListenerCapture: |
| 117 return RecordingImageBufferSurface::FallbackReasonSnapshotForCanvasListe
nerCapture; |
| 118 case SnapshotReasonDrawImage: |
| 119 return RecordingImageBufferSurface::FallbackReasonSnapshotForDrawImage; |
| 120 case SnapshotReasonCreatePattern: |
| 121 return RecordingImageBufferSurface::FallbackReasonSnapshotForCreatePatte
rn; |
| 122 } |
| 123 ASSERT_NOT_REACHED(); |
| 124 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 125 } |
| 126 |
| 127 PassRefPtr<SkImage> RecordingImageBufferSurface::newImageSnapshot(AccelerationHi
nt hint, SnapshotReason reason) |
101 { | 128 { |
102 if (!m_fallbackSurface) | 129 if (!m_fallbackSurface) |
103 fallBackToRasterCanvas(); | 130 fallBackToRasterCanvas(snapshotReasonToFallbackReason(reason)); |
104 return m_fallbackSurface->newImageSnapshot(hint); | 131 return m_fallbackSurface->newImageSnapshot(hint, reason); |
105 } | 132 } |
106 | 133 |
107 SkCanvas* RecordingImageBufferSurface::canvas() | 134 SkCanvas* RecordingImageBufferSurface::canvas() |
108 { | 135 { |
109 if (m_fallbackSurface) | 136 if (m_fallbackSurface) |
110 return m_fallbackSurface->canvas(); | 137 return m_fallbackSurface->canvas(); |
111 | 138 |
112 ASSERT(m_currentFrame->getRecordingCanvas()); | 139 ASSERT(m_currentFrame->getRecordingCanvas()); |
113 return m_currentFrame->getRecordingCanvas(); | 140 return m_currentFrame->getRecordingCanvas(); |
114 } | 141 } |
115 | 142 |
116 void RecordingImageBufferSurface::disableDeferral() | 143 static RecordingImageBufferSurface::FallbackReason disableDeferralReasonToFallba
ckReason(DisableDeferralReason reason) |
| 144 { |
| 145 switch (reason) { |
| 146 case DisableDeferralReasonUnknown: |
| 147 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 148 case DisableDeferralReasonExpensiveOverdrawHeuristic: |
| 149 return RecordingImageBufferSurface::FallbackReasonExpensiveOverdrawHeuri
stic; |
| 150 case DisableDeferralReasonUsingTextureBackedPattern: |
| 151 return RecordingImageBufferSurface::FallbackReasonTextureBackedPattern; |
| 152 case DisableDeferralReasonDrawImageOfVideo: |
| 153 return RecordingImageBufferSurface::FallbackReasonDrawImageOfVideo; |
| 154 case DisableDeferralReasonDrawImageOfAnimated2dCanvas: |
| 155 return RecordingImageBufferSurface::FallbackReasonDrawImageOfAnimated2dC
anvas; |
| 156 case DisableDeferralReasonSubPixelTextAntiAliasingSupport: |
| 157 return RecordingImageBufferSurface::FallbackReasonSubPixelTextAntiAliasi
ngSupport; |
| 158 case DisableDeferralReasonCount: |
| 159 ASSERT_NOT_REACHED(); |
| 160 break; |
| 161 } |
| 162 ASSERT_NOT_REACHED(); |
| 163 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 164 } |
| 165 |
| 166 void RecordingImageBufferSurface::disableDeferral(DisableDeferralReason reason) |
117 { | 167 { |
118 if (!m_fallbackSurface) | 168 if (!m_fallbackSurface) |
119 fallBackToRasterCanvas(); | 169 fallBackToRasterCanvas(disableDeferralReasonToFallbackReason(reason)); |
120 } | 170 } |
121 | 171 |
122 PassRefPtr<SkPicture> RecordingImageBufferSurface::getPicture() | 172 PassRefPtr<SkPicture> RecordingImageBufferSurface::getPicture() |
123 { | 173 { |
124 if (m_fallbackSurface) | 174 if (m_fallbackSurface) |
125 return nullptr; | 175 return nullptr; |
126 | 176 |
127 bool canUsePicture = finalizeFrameInternal(); | 177 FallbackReason fallbackReason = FallbackReasonUnknown; |
| 178 bool canUsePicture = finalizeFrameInternal(&fallbackReason); |
128 m_imageBuffer->didFinalizeFrame(); | 179 m_imageBuffer->didFinalizeFrame(); |
129 | 180 |
130 if (canUsePicture) { | 181 if (canUsePicture) { |
131 return m_previousFrame; | 182 return m_previousFrame; |
132 } | 183 } |
133 | 184 |
134 if (!m_fallbackSurface) | 185 if (!m_fallbackSurface) |
135 fallBackToRasterCanvas(); | 186 fallBackToRasterCanvas(fallbackReason); |
136 return nullptr; | 187 return nullptr; |
137 } | 188 } |
138 | 189 |
139 void RecordingImageBufferSurface::finalizeFrame(const FloatRect &dirtyRect) | 190 void RecordingImageBufferSurface::finalizeFrame(const FloatRect &dirtyRect) |
140 { | 191 { |
141 if (m_fallbackSurface) { | 192 if (m_fallbackSurface) { |
142 m_fallbackSurface->finalizeFrame(dirtyRect); | 193 m_fallbackSurface->finalizeFrame(dirtyRect); |
143 return; | 194 return; |
144 } | 195 } |
145 | 196 |
146 if (!finalizeFrameInternal()) | 197 FallbackReason fallbackReason = FallbackReasonUnknown; |
147 fallBackToRasterCanvas(); | 198 if (!finalizeFrameInternal(&fallbackReason)) |
| 199 fallBackToRasterCanvas(fallbackReason); |
148 } | 200 } |
149 | 201 |
150 void RecordingImageBufferSurface::flush() | 202 static RecordingImageBufferSurface::FallbackReason flushReasonToFallbackReason(F
lushReason reason) |
| 203 { |
| 204 switch (reason) { |
| 205 case FlushReasonUnknown: |
| 206 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 207 case FlushReasonInitialClear: |
| 208 return RecordingImageBufferSurface::FallbackReasonFlushInitialClear; |
| 209 case FlushReasonDrawImageOfWebGL: |
| 210 return RecordingImageBufferSurface::FallbackReasonFlushForDrawImageOfWeb
GL; |
| 211 } |
| 212 ASSERT_NOT_REACHED(); |
| 213 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 214 } |
| 215 |
| 216 void RecordingImageBufferSurface::flush(FlushReason reason) |
151 { | 217 { |
152 if (!m_fallbackSurface) | 218 if (!m_fallbackSurface) |
153 fallBackToRasterCanvas(); | 219 fallBackToRasterCanvas(flushReasonToFallbackReason(reason)); |
154 m_fallbackSurface->flush(); | 220 m_fallbackSurface->flush(reason); |
155 } | 221 } |
156 | 222 |
157 void RecordingImageBufferSurface::willOverwriteCanvas() | 223 void RecordingImageBufferSurface::willOverwriteCanvas() |
158 { | 224 { |
159 m_frameWasCleared = true; | 225 m_frameWasCleared = true; |
160 m_previousFrame.clear(); | 226 m_previousFrame.clear(); |
161 m_previousFrameHasExpensiveOp = false; | 227 m_previousFrameHasExpensiveOp = false; |
162 m_previousFramePixelCount = 0; | 228 m_previousFramePixelCount = 0; |
163 if (m_didRecordDrawCommandsInCurrentFrame) { | 229 if (m_didRecordDrawCommandsInCurrentFrame) { |
164 // Discard previous draw commands | 230 // Discard previous draw commands |
165 adoptRef(m_currentFrame->endRecording()); | 231 adoptRef(m_currentFrame->endRecording()); |
166 initializeCurrentFrame(); | 232 initializeCurrentFrame(); |
167 } | 233 } |
168 } | 234 } |
169 | 235 |
170 void RecordingImageBufferSurface::didDraw(const FloatRect& rect) | 236 void RecordingImageBufferSurface::didDraw(const FloatRect& rect) |
171 { | 237 { |
172 m_didRecordDrawCommandsInCurrentFrame = true; | 238 m_didRecordDrawCommandsInCurrentFrame = true; |
173 IntRect pixelBounds = enclosingIntRect(rect); | 239 IntRect pixelBounds = enclosingIntRect(rect); |
174 m_currentFramePixelCount += pixelBounds.width() * pixelBounds.height(); | 240 m_currentFramePixelCount += pixelBounds.width() * pixelBounds.height(); |
175 } | 241 } |
176 | 242 |
177 bool RecordingImageBufferSurface::finalizeFrameInternal() | 243 bool RecordingImageBufferSurface::finalizeFrameInternal(FallbackReason* fallback
Reason) |
178 { | 244 { |
179 ASSERT(!m_fallbackSurface); | 245 ASSERT(!m_fallbackSurface); |
180 ASSERT(m_currentFrame); | 246 ASSERT(m_currentFrame); |
181 ASSERT(m_currentFrame->getRecordingCanvas()); | 247 ASSERT(m_currentFrame->getRecordingCanvas()); |
| 248 ASSERT(fallbackReason); |
| 249 ASSERT(*fallbackReason == FallbackReasonUnknown); |
182 | 250 |
183 if (!m_imageBuffer->isDirty()) { | 251 if (!m_imageBuffer->isDirty()) { |
184 if (!m_previousFrame) { | 252 if (!m_previousFrame) { |
185 // Create an initial blank frame | 253 // Create an initial blank frame |
186 m_previousFrame = adoptRef(m_currentFrame->endRecording()); | 254 m_previousFrame = adoptRef(m_currentFrame->endRecording()); |
187 initializeCurrentFrame(); | 255 initializeCurrentFrame(); |
188 } | 256 } |
189 return m_currentFrame; | 257 return m_currentFrame; |
190 } | 258 } |
191 | 259 |
192 if (!m_frameWasCleared || m_currentFrame->getRecordingCanvas()->getSaveCount
() > ExpensiveCanvasHeuristicParameters::ExpensiveRecordingStackDepth) { | 260 if (!m_frameWasCleared) { |
| 261 *fallbackReason = FallbackReasonCanvasNotClearedBetweenFrames; |
| 262 return false; |
| 263 } |
| 264 |
| 265 if (m_currentFrame->getRecordingCanvas()->getSaveCount() > ExpensiveCanvasHe
uristicParameters::ExpensiveRecordingStackDepth) { |
| 266 *fallbackReason = FallbackReasonRunawayStateStack; |
193 return false; | 267 return false; |
194 } | 268 } |
195 | 269 |
196 m_previousFrame = adoptRef(m_currentFrame->endRecording()); | 270 m_previousFrame = adoptRef(m_currentFrame->endRecording()); |
197 m_previousFrameHasExpensiveOp = m_currentFrameHasExpensiveOp; | 271 m_previousFrameHasExpensiveOp = m_currentFrameHasExpensiveOp; |
198 m_previousFramePixelCount = m_currentFramePixelCount; | 272 m_previousFramePixelCount = m_currentFramePixelCount; |
199 if (!initializeCurrentFrame()) | 273 initializeCurrentFrame(); |
200 return false; | |
201 | 274 |
202 m_frameWasCleared = false; | 275 m_frameWasCleared = false; |
203 return true; | 276 return true; |
204 } | 277 } |
205 | 278 |
206 void RecordingImageBufferSurface::draw(GraphicsContext& context, const FloatRect
& destRect, const FloatRect& srcRect, SkXfermode::Mode op) | 279 void RecordingImageBufferSurface::draw(GraphicsContext& context, const FloatRect
& destRect, const FloatRect& srcRect, SkXfermode::Mode op) |
207 { | 280 { |
208 if (m_fallbackSurface) { | 281 if (m_fallbackSurface) { |
209 m_fallbackSurface->draw(context, destRect, srcRect, op); | 282 m_fallbackSurface->draw(context, destRect, srcRect, op); |
210 return; | 283 return; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 | 343 |
271 void RecordingImageBufferSurface::setIsHidden(bool hidden) | 344 void RecordingImageBufferSurface::setIsHidden(bool hidden) |
272 { | 345 { |
273 if (m_fallbackSurface) | 346 if (m_fallbackSurface) |
274 m_fallbackSurface->setIsHidden(hidden); | 347 m_fallbackSurface->setIsHidden(hidden); |
275 else | 348 else |
276 ImageBufferSurface::setIsHidden(hidden); | 349 ImageBufferSurface::setIsHidden(hidden); |
277 } | 350 } |
278 | 351 |
279 } // namespace blink | 352 } // namespace blink |
OLD | NEW |