1// Copyright (c) 2013 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.
4
5'use strict';
6
7base.require('base.guid');
8base.require('base.rect');
9base.require('base.raf');
10base.require('tracing.trace_model.object_instance');
11base.require('cc.picture_as_canvas');
12base.require('cc.util');
13
14base.exportTo('cc', function() {
15
16  var ObjectSnapshot = tracing.trace_model.ObjectSnapshot;
17
18  // Number of pictures created. Used as an uniqueId because we are immutable.
19  var PictureCount = 0;
20
21  /**
22   * @constructor
23   */
24  function PictureSnapshot() {
25    ObjectSnapshot.apply(this, arguments);
26    this.guid_ = base.GUID.allocate();
27  }
28
29  PictureSnapshot.CanRasterize = function() {
30    if (!window.chrome)
31      return false;
32    if (!window.chrome.skiaBenchmarking)
33      return false;
34    if (!window.chrome.skiaBenchmarking.rasterize)
35      return false;
36    return true;
37  }
38
39  PictureSnapshot.CanGetOps = function() {
40    if (!window.chrome)
41      return false;
42    if (!window.chrome.skiaBenchmarking)
43      return false;
44    if (!window.chrome.skiaBenchmarking.getOps)
45      return false;
46    return true;
47  }
48
49  PictureSnapshot.HowToEnablePictureDebugging = function() {
50    var usualReason = [
51      'For pictures to show up, you need to have Chrome running with ',
52      '--enable-skia-benchmarking. Please restart chrome with this flag ',
53      'and try again.'
54    ].join('');
55
56    if (!window.chrome)
57      return usualReason;
58    if (!window.chrome.skiaBenchmarking)
59      return usualReason;
60    if (!window.chrome.skiaBenchmarking.rasterize)
61      return 'Your chrome is old';
62    if (!window.chrome.skiaBenchmarking.getOps)
63      return 'Your chrome is old, skiaBenchmarking.getOps not found';
64    return 'Rasterizing is on';
65  }
66
67  PictureSnapshot.prototype = {
68    __proto__: ObjectSnapshot.prototype,
69
70    preInitialize: function() {
71      cc.preInitializeObject(this);
72      this.rasterResult_ = undefined;
73    },
74
75    initialize: function() {
76      if (!this.args.params.layerRect)
77        throw new Error('Missing layer rect');
78      this.layerRect_ = this.args.params.layerRect;
79      this.layerRect_ = base.Rect.FromArray(this.layerRect_);
80    },
81
82    get layerRect() {
83      return this.layerRect_;
84    },
85
86    get guid() {
87      return this.guid_;
88    },
89
90    getBase64SkpData: function() {
91      return this.args.skp64;
92    },
93
94    getOps: function() {
95      if (!PictureSnapshot.CanGetOps()) {
96        console.error(PictureSnapshot.HowToEnablePictureDebugging());
97        return undefined;
98      }
99
100      var ops = window.chrome.skiaBenchmarking.getOps({
101        skp64: this.args.skp64,
102        params: {
103          layer_rect: this.args.params.layerRect,
104          opaque_rect: this.args.params.opaqueRect
105        }
106      });
107
108      if (!ops)
109        console.error('Failed to get picture ops.');
110
111      return ops;
112    },
113
114    /**
115     * Rasterize the picture.
116     *
117     * @param {{opt_stopIndex: number, params}} The SkPicture operation to
118     *     rasterize up to. If not defined, the entire SkPicture is rasterized.
119     * @param {function(cc.PictureAsCanvas)} The callback function that is
120     *     called after rasterization is complete or fails.
121     */
122    rasterize: function(params, rasterCompleteCallback) {
123      if (!PictureSnapshot.CanRasterize() || !PictureSnapshot.CanGetOps()) {
124        rasterCompleteCallback(new cc.PictureAsCanvas(
125            this, cc.PictureSnapshot.HowToEnablePictureDebugging()));
126        return;
127      }
128
129      var raster = window.chrome.skiaBenchmarking.rasterize(
130          {
131            skp64: this.args.skp64,
132            params: {
133              layer_rect: this.args.params.layerRect,
134              opaque_rect: this.args.params.opaqueRect
135            }
136          },
137          {
138            stop: params.stopIndex === undefined ? -1 : params.stopIndex,
139            params: { }
140          });
141
142      if (raster) {
143        var canvas = document.createElement('canvas');
144        var ctx = canvas.getContext('2d');
145        canvas.width = raster.width;
146        canvas.height = raster.height;
147        var imageData = ctx.createImageData(raster.width, raster.height);
148        imageData.data.set(new Uint8ClampedArray(raster.data));
149        ctx.putImageData(imageData, 0, 0);
150        rasterCompleteCallback(new cc.PictureAsCanvas(this, canvas));
151      } else {
152        var error = 'Failed to rasterize picture. ' +
153                'Your recording may be from an old Chrome version. ' +
154                'The SkPicture format is not backward compatible.';
155        rasterCompleteCallback(new cc.PictureAsCanvas(this, error));
156      }
157    }
158  };
159
160  ObjectSnapshot.register('cc::Picture', PictureSnapshot);
161
162  return {
163    PictureSnapshot: PictureSnapshot
164  };
165});
166