Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / GraphicsContextRecorder.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "platform/graphics/GraphicsContextRecorder.h"
33
34 #include "platform/graphics/ImageBuffer.h"
35 #include "platform/graphics/ImageSource.h"
36 #include "platform/image-decoders/ImageDecoder.h"
37 #include "platform/image-decoders/ImageFrame.h"
38 #include "third_party/skia/include/core/SkBitmapDevice.h"
39 #include "third_party/skia/include/core/SkPictureRecorder.h"
40 #include "third_party/skia/include/core/SkStream.h"
41
42 namespace WebCore {
43
44 GraphicsContext* GraphicsContextRecorder::record(const IntSize& size, bool isCertainlyOpaque)
45 {
46     ASSERT(!m_picture);
47     ASSERT(!m_recorder);
48     ASSERT(!m_context);
49     m_isCertainlyOpaque = isCertainlyOpaque;
50     m_recorder = adoptPtr(new SkPictureRecorder);
51     SkCanvas* canvas = m_recorder->beginRecording(size.width(), size.height(), 0, 0);
52     m_context = adoptPtr(new GraphicsContext(canvas));
53     m_context->setTrackOpaqueRegion(isCertainlyOpaque);
54     m_context->setCertainlyOpaque(isCertainlyOpaque);
55     return m_context.get();
56 }
57
58 PassRefPtr<GraphicsContextSnapshot> GraphicsContextRecorder::stop()
59 {
60     m_context.clear();
61     m_picture = adoptRef(m_recorder->endRecording());
62     m_recorder.clear();
63     return adoptRef(new GraphicsContextSnapshot(m_picture.release(), m_isCertainlyOpaque));
64 }
65
66 GraphicsContextSnapshot::GraphicsContextSnapshot(PassRefPtr<SkPicture> picture, bool isCertainlyOpaque)
67     : m_picture(picture)
68     , m_isCertainlyOpaque(isCertainlyOpaque)
69 {
70 }
71
72
73 class SnapshotPlayer : public SkDrawPictureCallback {
74     WTF_MAKE_NONCOPYABLE(SnapshotPlayer);
75 public:
76     explicit SnapshotPlayer(PassRefPtr<SkPicture> picture, SkCanvas* canvas)
77         : m_picture(picture)
78         , m_canvas(canvas)
79     {
80     }
81
82     SkCanvas* canvas() { return m_canvas; }
83
84     void play()
85     {
86         m_picture->draw(m_canvas, this);
87     }
88
89 private:
90     RefPtr<SkPicture> m_picture;
91     SkCanvas* m_canvas;
92 };
93
94 class FragmentSnapshotPlayer : public SnapshotPlayer {
95 public:
96     FragmentSnapshotPlayer(PassRefPtr<SkPicture> picture, SkCanvas* canvas)
97         : SnapshotPlayer(picture, canvas)
98     {
99     }
100
101     void play(unsigned fromStep, unsigned toStep)
102     {
103         m_fromStep = fromStep;
104         m_toStep = toStep;
105         m_stepCount = 0;
106         SnapshotPlayer::play();
107     }
108
109     virtual bool abortDrawing() OVERRIDE
110     {
111         ++m_stepCount;
112         if (m_stepCount == m_fromStep) {
113             const SkBitmap& bitmap = canvas()->getDevice()->accessBitmap(true);
114             bitmap.eraseARGB(0, 0, 0, 0); // FIXME: get layers background color, it might make resulting image a bit more plausable.
115         }
116         return m_toStep && m_stepCount > m_toStep;
117     }
118
119 private:
120     unsigned m_fromStep;
121     unsigned m_toStep;
122     unsigned m_stepCount;
123 };
124
125 class ProfilingSnapshotPlayer : public SnapshotPlayer {
126 public:
127     ProfilingSnapshotPlayer(PassRefPtr<SkPicture> picture, SkCanvas* canvas)
128         : SnapshotPlayer(picture, canvas)
129     {
130     }
131
132     void play(GraphicsContextSnapshot::Timings* timingsVector, unsigned minRepeatCount, double minDuration)
133     {
134         m_timingsVector = timingsVector;
135         m_timingsVector->reserveCapacity(minRepeatCount);
136
137         double now = WTF::monotonicallyIncreasingTime();
138         double stopTime = now + minDuration;
139         for (unsigned step = 0; step < minRepeatCount || now < stopTime; ++step) {
140             m_timingsVector->append(Vector<double>());
141             m_currentTimings = &m_timingsVector->last();
142             if (m_timingsVector->size() > 1)
143                 m_currentTimings->reserveCapacity(m_timingsVector->begin()->size());
144             SnapshotPlayer::play();
145             now = WTF::monotonicallyIncreasingTime();
146             m_currentTimings->append(now);
147         }
148     }
149
150     virtual bool abortDrawing() OVERRIDE
151     {
152         m_currentTimings->append(WTF::monotonicallyIncreasingTime());
153         return false;
154     }
155
156     const GraphicsContextSnapshot::Timings& timingsVector() const { return *m_timingsVector; }
157
158 private:
159     GraphicsContextSnapshot::Timings* m_timingsVector;
160     Vector<double>* m_currentTimings;
161 };
162
163 class LoggingSnapshotPlayer : public SnapshotPlayer {
164 public:
165     LoggingSnapshotPlayer(PassRefPtr<SkPicture> picture, SkCanvas* canvas)
166         : SnapshotPlayer(picture, canvas)
167     {
168     }
169
170     virtual bool abortDrawing() OVERRIDE
171     {
172         return false;
173     }
174 };
175
176 class LoggingCanvas : public SkCanvas {
177 public:
178     LoggingCanvas()
179     {
180         m_log = JSONArray::create();
181     }
182
183     void clear(SkColor) OVERRIDE
184     {
185         addItem("clear");
186     }
187
188     void drawPaint(const SkPaint& paint) OVERRIDE
189     {
190         addItem("drawPaint");
191     }
192
193     void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint&) OVERRIDE
194     {
195         addItem("drawPoints");
196     }
197
198     void drawPicture(SkPicture&) OVERRIDE
199     {
200         addItem("drawPicture");
201     }
202
203     void drawRect(const SkRect& rect, const SkPaint& paint) OVERRIDE
204     {
205         addItem("drawRect");
206     }
207
208     void drawOval(const SkRect&, const SkPaint&) OVERRIDE
209     {
210         addItem("drawOval");
211     }
212
213     void drawRRect(const SkRRect&, const SkPaint&) OVERRIDE
214     {
215         addItem("drawRRect");
216     }
217
218     void drawPath(const SkPath& path, const SkPaint&) OVERRIDE
219     {
220         addItem("drawPath");
221     }
222
223     void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint*) OVERRIDE
224     {
225         addItem("drawBitmap");
226     }
227
228     void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, const SkPaint* paint, DrawBitmapRectFlags flags) OVERRIDE
229     {
230         addItem("drawBitmapRectToRect");
231     }
232
233     void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint*) OVERRIDE
234     {
235         addItem("drawBitmapMatrix");
236     }
237
238     void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint = 0) OVERRIDE
239     {
240         addItem("drawBitmapNine");
241     }
242
243     void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint*) OVERRIDE
244     {
245         addItem("drawSprite");
246     }
247
248     void drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
249         const uint16_t indices[], int indexCount, const SkPaint&) OVERRIDE
250     {
251         addItem("drawVertices");
252     }
253
254     void drawData(const void* data, size_t length) OVERRIDE
255     {
256         addItem("drawData");
257     }
258
259     PassRefPtr<JSONArray> log()
260     {
261         return m_log;
262     }
263
264 private:
265     RefPtr<JSONArray> m_log;
266
267     void addItem(const String& name)
268     {
269         RefPtr<JSONObject> item = JSONObject::create();
270         item->setString("name", name);
271         m_log->pushObject(item.release());
272     }
273 };
274
275 static bool decodeBitmap(const void* data, size_t length, SkBitmap* result)
276 {
277     RefPtr<SharedBuffer> buffer = SharedBuffer::create(static_cast<const char*>(data), length);
278     OwnPtr<ImageDecoder> imageDecoder = ImageDecoder::create(*buffer, ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileIgnored);
279     if (!imageDecoder)
280         return false;
281     imageDecoder->setData(buffer.get(), true);
282     ImageFrame* frame = imageDecoder->frameBufferAtIndex(0);
283     if (!frame)
284         return true;
285     *result = frame->getSkBitmap();
286     return true;
287 }
288
289 PassRefPtr<GraphicsContextSnapshot> GraphicsContextSnapshot::load(const char* data, size_t size)
290 {
291     SkMemoryStream stream(data, size);
292     RefPtr<SkPicture> picture = adoptRef(SkPicture::CreateFromStream(&stream, decodeBitmap));
293     if (!picture)
294         return nullptr;
295     return adoptRef(new GraphicsContextSnapshot(picture, false));
296 }
297
298 PassOwnPtr<ImageBuffer> GraphicsContextSnapshot::replay(unsigned fromStep, unsigned toStep) const
299 {
300     OwnPtr<ImageBuffer> imageBuffer = createImageBuffer();
301     FragmentSnapshotPlayer player(m_picture, imageBuffer->context()->canvas());
302     player.play(fromStep, toStep);
303     return imageBuffer.release();
304 }
305
306 PassOwnPtr<GraphicsContextSnapshot::Timings> GraphicsContextSnapshot::profile(unsigned minRepeatCount, double minDuration) const
307 {
308     OwnPtr<GraphicsContextSnapshot::Timings> timings = adoptPtr(new GraphicsContextSnapshot::Timings());
309     OwnPtr<ImageBuffer> imageBuffer = createImageBuffer();
310     ProfilingSnapshotPlayer player(m_picture, imageBuffer->context()->canvas());
311     player.play(timings.get(), minRepeatCount, minDuration);
312     return timings.release();
313 }
314
315 PassOwnPtr<ImageBuffer> GraphicsContextSnapshot::createImageBuffer() const
316 {
317     return ImageBuffer::create(IntSize(m_picture->width(), m_picture->height()), m_isCertainlyOpaque ? Opaque : NonOpaque);
318 }
319
320 PassRefPtr<JSONArray> GraphicsContextSnapshot::snapshotCommandLog() const
321 {
322     LoggingCanvas canvas;
323     FragmentSnapshotPlayer player(m_picture, &canvas);
324     player.play(0, 0);
325     return canvas.log();
326 }
327
328 }