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 DisableDeferralReasonCount: |
| 157 ASSERT_NOT_REACHED(); |
| 158 break; |
| 159 } |
| 160 ASSERT_NOT_REACHED(); |
| 161 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 162 } |
| 163 |
| 164 void RecordingImageBufferSurface::disableDeferral(DisableDeferralReason reason) |
117 { | 165 { |
118 if (!m_fallbackSurface) | 166 if (!m_fallbackSurface) |
119 fallBackToRasterCanvas(); | 167 fallBackToRasterCanvas(disableDeferralReasonToFallbackReason(reason)); |
120 } | 168 } |
121 | 169 |
122 PassRefPtr<SkPicture> RecordingImageBufferSurface::getPicture() | 170 PassRefPtr<SkPicture> RecordingImageBufferSurface::getPicture() |
123 { | 171 { |
124 if (m_fallbackSurface) | 172 if (m_fallbackSurface) |
125 return nullptr; | 173 return nullptr; |
126 | 174 |
127 bool canUsePicture = finalizeFrameInternal(); | 175 FallbackReason fallbackReason = FallbackReasonUnknown; |
| 176 bool canUsePicture = finalizeFrameInternal(&fallbackReason); |
128 m_imageBuffer->didFinalizeFrame(); | 177 m_imageBuffer->didFinalizeFrame(); |
129 | 178 |
130 if (canUsePicture) { | 179 if (canUsePicture) { |
131 return m_previousFrame; | 180 return m_previousFrame; |
132 } | 181 } |
133 | 182 |
134 if (!m_fallbackSurface) | 183 if (!m_fallbackSurface) |
135 fallBackToRasterCanvas(); | 184 fallBackToRasterCanvas(fallbackReason); |
136 return nullptr; | 185 return nullptr; |
137 } | 186 } |
138 | 187 |
139 void RecordingImageBufferSurface::finalizeFrame(const FloatRect &dirtyRect) | 188 void RecordingImageBufferSurface::finalizeFrame(const FloatRect &dirtyRect) |
140 { | 189 { |
141 if (m_fallbackSurface) { | 190 if (m_fallbackSurface) { |
142 m_fallbackSurface->finalizeFrame(dirtyRect); | 191 m_fallbackSurface->finalizeFrame(dirtyRect); |
143 return; | 192 return; |
144 } | 193 } |
145 | 194 |
146 if (!finalizeFrameInternal()) | 195 FallbackReason fallbackReason = FallbackReasonUnknown; |
147 fallBackToRasterCanvas(); | 196 if (!finalizeFrameInternal(&fallbackReason)) |
| 197 fallBackToRasterCanvas(fallbackReason); |
148 } | 198 } |
149 | 199 |
150 void RecordingImageBufferSurface::flush() | 200 static RecordingImageBufferSurface::FallbackReason flushReasonToFallbackReason(F
lushReason reason) |
| 201 { |
| 202 switch (reason) { |
| 203 case FlushReasonUnknown: |
| 204 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 205 case FlushReasonInitialClear: |
| 206 return RecordingImageBufferSurface::FallbackReasonFlushInitialClear; |
| 207 case FlushReasonDrawImageOfWebGL: |
| 208 return RecordingImageBufferSurface::FallbackReasonFlushForDrawImageOfWeb
GL; |
| 209 } |
| 210 ASSERT_NOT_REACHED(); |
| 211 return RecordingImageBufferSurface::FallbackReasonUnknown; |
| 212 } |
| 213 |
| 214 void RecordingImageBufferSurface::flush(FlushReason reason) |
151 { | 215 { |
152 if (!m_fallbackSurface) | 216 if (!m_fallbackSurface) |
153 fallBackToRasterCanvas(); | 217 fallBackToRasterCanvas(flushReasonToFallbackReason(reason)); |
154 m_fallbackSurface->flush(); | 218 m_fallbackSurface->flush(reason); |
155 } | 219 } |
156 | 220 |
157 void RecordingImageBufferSurface::willOverwriteCanvas() | 221 void RecordingImageBufferSurface::willOverwriteCanvas() |
158 { | 222 { |
159 m_frameWasCleared = true; | 223 m_frameWasCleared = true; |
160 m_previousFrame.clear(); | 224 m_previousFrame.clear(); |
161 m_previousFrameHasExpensiveOp = false; | 225 m_previousFrameHasExpensiveOp = false; |
162 m_previousFramePixelCount = 0; | 226 m_previousFramePixelCount = 0; |
163 if (m_didRecordDrawCommandsInCurrentFrame) { | 227 if (m_didRecordDrawCommandsInCurrentFrame) { |
164 // Discard previous draw commands | 228 // Discard previous draw commands |
165 adoptRef(m_currentFrame->endRecording()); | 229 adoptRef(m_currentFrame->endRecording()); |
166 initializeCurrentFrame(); | 230 initializeCurrentFrame(); |
167 } | 231 } |
168 } | 232 } |
169 | 233 |
170 void RecordingImageBufferSurface::didDraw(const FloatRect& rect) | 234 void RecordingImageBufferSurface::didDraw(const FloatRect& rect) |
171 { | 235 { |
172 m_didRecordDrawCommandsInCurrentFrame = true; | 236 m_didRecordDrawCommandsInCurrentFrame = true; |
173 IntRect pixelBounds = enclosingIntRect(rect); | 237 IntRect pixelBounds = enclosingIntRect(rect); |
174 m_currentFramePixelCount += pixelBounds.width() * pixelBounds.height(); | 238 m_currentFramePixelCount += pixelBounds.width() * pixelBounds.height(); |
175 } | 239 } |
176 | 240 |
177 bool RecordingImageBufferSurface::finalizeFrameInternal() | 241 bool RecordingImageBufferSurface::finalizeFrameInternal(FallbackReason* fallback
Reason) |
178 { | 242 { |
179 ASSERT(!m_fallbackSurface); | 243 ASSERT(!m_fallbackSurface); |
180 ASSERT(m_currentFrame); | 244 ASSERT(m_currentFrame); |
181 ASSERT(m_currentFrame->getRecordingCanvas()); | 245 ASSERT(m_currentFrame->getRecordingCanvas()); |
| 246 ASSERT(fallbackReason); |
| 247 ASSERT(*fallbackReason == FallbackReasonUnknown); |
182 | 248 |
183 if (!m_imageBuffer->isDirty()) { | 249 if (!m_imageBuffer->isDirty()) { |
184 if (!m_previousFrame) { | 250 if (!m_previousFrame) { |
185 // Create an initial blank frame | 251 // Create an initial blank frame |
186 m_previousFrame = adoptRef(m_currentFrame->endRecording()); | 252 m_previousFrame = adoptRef(m_currentFrame->endRecording()); |
187 initializeCurrentFrame(); | 253 initializeCurrentFrame(); |
188 } | 254 } |
189 return m_currentFrame; | 255 return m_currentFrame; |
190 } | 256 } |
191 | 257 |
192 if (!m_frameWasCleared || m_currentFrame->getRecordingCanvas()->getSaveCount
() > ExpensiveCanvasHeuristicParameters::ExpensiveRecordingStackDepth) { | 258 if (!m_frameWasCleared) { |
| 259 *fallbackReason = FallbackReasonCanvasNotClearedBetweenFrames; |
| 260 return false; |
| 261 } |
| 262 |
| 263 if (m_currentFrame->getRecordingCanvas()->getSaveCount() > ExpensiveCanvasHe
uristicParameters::ExpensiveRecordingStackDepth) { |
| 264 *fallbackReason = FallbackReasonRunawayStateStack; |
193 return false; | 265 return false; |
194 } | 266 } |
195 | 267 |
196 m_previousFrame = adoptRef(m_currentFrame->endRecording()); | 268 m_previousFrame = adoptRef(m_currentFrame->endRecording()); |
197 m_previousFrameHasExpensiveOp = m_currentFrameHasExpensiveOp; | 269 m_previousFrameHasExpensiveOp = m_currentFrameHasExpensiveOp; |
198 m_previousFramePixelCount = m_currentFramePixelCount; | 270 m_previousFramePixelCount = m_currentFramePixelCount; |
199 if (!initializeCurrentFrame()) | 271 initializeCurrentFrame(); |
200 return false; | |
201 | 272 |
202 m_frameWasCleared = false; | 273 m_frameWasCleared = false; |
203 return true; | 274 return true; |
204 } | 275 } |
205 | 276 |
206 void RecordingImageBufferSurface::draw(GraphicsContext& context, const FloatRect
& destRect, const FloatRect& srcRect, SkXfermode::Mode op) | 277 void RecordingImageBufferSurface::draw(GraphicsContext& context, const FloatRect
& destRect, const FloatRect& srcRect, SkXfermode::Mode op) |
207 { | 278 { |
208 if (m_fallbackSurface) { | 279 if (m_fallbackSurface) { |
209 m_fallbackSurface->draw(context, destRect, srcRect, op); | 280 m_fallbackSurface->draw(context, destRect, srcRect, op); |
210 return; | 281 return; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 | 341 |
271 void RecordingImageBufferSurface::setIsHidden(bool hidden) | 342 void RecordingImageBufferSurface::setIsHidden(bool hidden) |
272 { | 343 { |
273 if (m_fallbackSurface) | 344 if (m_fallbackSurface) |
274 m_fallbackSurface->setIsHidden(hidden); | 345 m_fallbackSurface->setIsHidden(hidden); |
275 else | 346 else |
276 ImageBufferSurface::setIsHidden(hidden); | 347 ImageBufferSurface::setIsHidden(hidden); |
277 } | 348 } |
278 | 349 |
279 } // namespace blink | 350 } // namespace blink |
OLD | NEW |