Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / platform / graphics / RecordingImageBufferSurface.cpp
blobac85b2a307c5f9cfb9646e971b940b702cc4a459
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
3 // found in the LICENSE file.
5 #include "config.h"
7 #include "platform/graphics/RecordingImageBufferSurface.h"
9 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h"
10 #include "platform/graphics/GraphicsContext.h"
11 #include "platform/graphics/ImageBuffer.h"
12 #include "public/platform/Platform.h"
13 #include "third_party/skia/include/core/SkCanvas.h"
14 #include "third_party/skia/include/core/SkPictureRecorder.h"
15 #include "wtf/PassOwnPtr.h"
16 #include "wtf/PassRefPtr.h"
18 namespace blink {
20 RecordingImageBufferSurface::RecordingImageBufferSurface(const IntSize& size, PassOwnPtr<RecordingImageBufferFallbackSurfaceFactory> fallbackFactory, OpacityMode opacityMode)
21 : ImageBufferSurface(size, opacityMode)
22 , m_imageBuffer(0)
23 , m_currentFramePixelCount(0)
24 , m_previousFramePixelCount(0)
25 , m_frameWasCleared(true)
26 , m_didRecordDrawCommandsInCurrentFrame(false)
27 , m_currentFrameHasExpensiveOp(false)
28 , m_previousFrameHasExpensiveOp(false)
29 , m_fallbackFactory(fallbackFactory)
31 initializeCurrentFrame();
34 RecordingImageBufferSurface::~RecordingImageBufferSurface()
35 { }
37 bool RecordingImageBufferSurface::initializeCurrentFrame()
39 static SkRTreeFactory rTreeFactory;
40 m_currentFrame = adoptPtr(new SkPictureRecorder);
41 m_currentFrame->beginRecording(size().width(), size().height(), &rTreeFactory);
42 if (m_imageBuffer) {
43 m_imageBuffer->resetCanvas(m_currentFrame->getRecordingCanvas());
45 m_didRecordDrawCommandsInCurrentFrame = false;
46 m_currentFrameHasExpensiveOp = false;
47 m_currentFramePixelCount = 0;
48 return true;
51 void RecordingImageBufferSurface::setImageBuffer(ImageBuffer* imageBuffer)
53 m_imageBuffer = imageBuffer;
54 if (m_currentFrame && m_imageBuffer) {
55 m_imageBuffer->resetCanvas(m_currentFrame->getRecordingCanvas());
57 if (m_fallbackSurface) {
58 m_fallbackSurface->setImageBuffer(imageBuffer);
62 bool RecordingImageBufferSurface::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes, int x, int y)
64 if (!m_fallbackSurface) {
65 if (x <= 0 && y <= 0 && x + origInfo.width() >= size().width() && y + origInfo.height() >= size().height()) {
66 willOverwriteCanvas();
68 fallBackToRasterCanvas();
70 return m_fallbackSurface->writePixels(origInfo, pixels, rowBytes, x, y);
73 void RecordingImageBufferSurface::fallBackToRasterCanvas()
75 if (m_fallbackSurface) {
76 ASSERT(!m_currentFrame);
77 return;
80 m_fallbackSurface = m_fallbackFactory->createSurface(size(), opacityMode());
81 m_fallbackSurface->setImageBuffer(m_imageBuffer);
83 if (m_previousFrame) {
84 m_previousFrame->playback(m_fallbackSurface->canvas());
85 m_previousFrame.clear();
88 if (m_currentFrame) {
89 RefPtr<SkPicture> currentPicture = adoptRef(m_currentFrame->endRecording());
90 currentPicture->playback(m_fallbackSurface->canvas());
91 m_currentFrame.clear();
94 if (m_imageBuffer) {
95 m_imageBuffer->resetCanvas(m_fallbackSurface->canvas());
100 PassRefPtr<SkImage> RecordingImageBufferSurface::newImageSnapshot()
102 if (!m_fallbackSurface)
103 fallBackToRasterCanvas();
104 return m_fallbackSurface->newImageSnapshot();
107 SkCanvas* RecordingImageBufferSurface::canvas()
109 if (m_fallbackSurface)
110 return m_fallbackSurface->canvas();
112 ASSERT(m_currentFrame->getRecordingCanvas());
113 return m_currentFrame->getRecordingCanvas();
116 void RecordingImageBufferSurface::disableDeferral()
118 if (!m_fallbackSurface)
119 fallBackToRasterCanvas();
122 PassRefPtr<SkPicture> RecordingImageBufferSurface::getPicture()
124 if (m_fallbackSurface)
125 return nullptr;
127 bool canUsePicture = finalizeFrameInternal();
128 m_imageBuffer->didFinalizeFrame();
130 if (canUsePicture) {
131 return m_previousFrame;
134 if (!m_fallbackSurface)
135 fallBackToRasterCanvas();
136 return nullptr;
139 void RecordingImageBufferSurface::finalizeFrame(const FloatRect &dirtyRect)
141 if (m_fallbackSurface) {
142 m_fallbackSurface->finalizeFrame(dirtyRect);
143 return;
146 if (!finalizeFrameInternal())
147 fallBackToRasterCanvas();
150 void RecordingImageBufferSurface::flush()
152 if (!m_fallbackSurface)
153 fallBackToRasterCanvas();
154 m_fallbackSurface->flush();
157 void RecordingImageBufferSurface::willOverwriteCanvas()
159 m_frameWasCleared = true;
160 m_previousFrame.clear();
161 m_previousFrameHasExpensiveOp = false;
162 m_previousFramePixelCount = 0;
163 if (m_didRecordDrawCommandsInCurrentFrame) {
164 // Discard previous draw commands
165 adoptRef(m_currentFrame->endRecording());
166 initializeCurrentFrame();
170 void RecordingImageBufferSurface::didDraw(const FloatRect& rect)
172 m_didRecordDrawCommandsInCurrentFrame = true;
173 IntRect pixelBounds = enclosingIntRect(rect);
174 m_currentFramePixelCount += pixelBounds.width() * pixelBounds.height();
177 bool RecordingImageBufferSurface::finalizeFrameInternal()
179 ASSERT(!m_fallbackSurface);
180 ASSERT(m_currentFrame);
181 ASSERT(m_currentFrame->getRecordingCanvas());
183 if (!m_imageBuffer->isDirty()) {
184 if (!m_previousFrame) {
185 // Create an initial blank frame
186 m_previousFrame = adoptRef(m_currentFrame->endRecording());
187 initializeCurrentFrame();
189 return m_currentFrame;
192 if (!m_frameWasCleared || m_currentFrame->getRecordingCanvas()->getSaveCount() > ExpensiveCanvasHeuristicParameters::ExpensiveRecordingStackDepth) {
193 return false;
196 m_previousFrame = adoptRef(m_currentFrame->endRecording());
197 m_previousFrameHasExpensiveOp = m_currentFrameHasExpensiveOp;
198 m_previousFramePixelCount = m_currentFramePixelCount;
199 if (!initializeCurrentFrame())
200 return false;
202 m_frameWasCleared = false;
203 return true;
206 void RecordingImageBufferSurface::draw(GraphicsContext* context, const FloatRect& destRect, const FloatRect& srcRect, SkXfermode::Mode op)
208 if (m_fallbackSurface) {
209 m_fallbackSurface->draw(context, destRect, srcRect, op);
210 return;
213 RefPtr<SkPicture> picture = getPicture();
214 if (picture) {
215 context->compositePicture(picture.get(), destRect, srcRect, op);
216 } else {
217 ImageBufferSurface::draw(context, destRect, srcRect, op);
221 bool RecordingImageBufferSurface::isExpensiveToPaint()
223 if (m_fallbackSurface)
224 return m_fallbackSurface->isExpensiveToPaint();
226 if (m_didRecordDrawCommandsInCurrentFrame) {
227 if (m_currentFrameHasExpensiveOp)
228 return true;
230 if (m_currentFramePixelCount >= (size().width() * size().height() * ExpensiveCanvasHeuristicParameters::ExpensiveOverdrawThreshold))
231 return true;
233 if (m_frameWasCleared)
234 return false; // early exit because previous frame is overdrawn
237 if (m_previousFrame) {
238 if (m_previousFrameHasExpensiveOp)
239 return true;
241 if (m_previousFramePixelCount >= (size().width() * size().height() * ExpensiveCanvasHeuristicParameters::ExpensiveOverdrawThreshold))
242 return true;
245 return false;
248 const SkBitmap& RecordingImageBufferSurface::deprecatedBitmapForOverwrite()
250 if (!m_fallbackSurface) {
251 willOverwriteCanvas();
252 fallBackToRasterCanvas();
254 return m_fallbackSurface->deprecatedBitmapForOverwrite();
257 // Fallback passthroughs
259 bool RecordingImageBufferSurface::restore()
261 if (m_fallbackSurface)
262 return m_fallbackSurface->restore();
263 return ImageBufferSurface::restore();
266 WebLayer* RecordingImageBufferSurface::layer() const
268 if (m_fallbackSurface)
269 return m_fallbackSurface->layer();
270 return ImageBufferSurface::layer();
273 bool RecordingImageBufferSurface::isAccelerated() const
275 if (m_fallbackSurface)
276 return m_fallbackSurface->isAccelerated();
277 return ImageBufferSurface::isAccelerated();
280 void RecordingImageBufferSurface::setIsHidden(bool hidden)
282 if (m_fallbackSurface)
283 m_fallbackSurface->setIsHidden(hidden);
284 else
285 ImageBufferSurface::setIsHidden(hidden);
288 } // namespace blink