| 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 |