OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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 "content/browser/devtools/devtools_frame_trace_recorder.h" | 5 #include "content/browser/devtools/devtools_frame_trace_recorder.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "ui/gfx/geometry/size_conversions.h" | 22 #include "ui/gfx/geometry/size_conversions.h" |
23 | 23 |
24 namespace content { | 24 namespace content { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 static base::subtle::Atomic32 frame_data_count = 0; | 28 static base::subtle::Atomic32 frame_data_count = 0; |
29 static int kMaximumFrameDataCount = 150; | 29 static int kMaximumFrameDataCount = 150; |
30 static size_t kFrameAreaLimit = 256000; | 30 static size_t kFrameAreaLimit = 256000; |
31 | 31 |
| 32 class TraceableDevToolsScreenshot |
| 33 : public base::trace_event::ConvertableToTraceFormat { |
| 34 public: |
| 35 TraceableDevToolsScreenshot(const SkBitmap& bitmap) : frame_(bitmap) {} |
| 36 |
| 37 void AppendAsTraceFormat(std::string* out) const override { |
| 38 out->append("\""); |
| 39 if (!frame_.drawsNothing()) { |
| 40 std::vector<unsigned char> data; |
| 41 SkAutoLockPixels lock_image(frame_); |
| 42 bool encoded = gfx::PNGCodec::Encode( |
| 43 reinterpret_cast<unsigned char*>(frame_.getAddr32(0, 0)), |
| 44 gfx::PNGCodec::FORMAT_SkBitmap, |
| 45 gfx::Size(frame_.width(), frame_.height()), |
| 46 frame_.width() * frame_.bytesPerPixel(), false, |
| 47 std::vector<gfx::PNGCodec::Comment>(), &data); |
| 48 if (encoded) { |
| 49 std::string encoded_data; |
| 50 base::Base64Encode( |
| 51 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), |
| 52 &encoded_data); |
| 53 out->append(encoded_data); |
| 54 } |
| 55 } |
| 56 out->append("\""); |
| 57 } |
| 58 |
| 59 private: |
| 60 ~TraceableDevToolsScreenshot() override { |
| 61 base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, -1); |
| 62 } |
| 63 |
| 64 SkBitmap frame_; |
| 65 }; |
| 66 |
32 } // namespace | 67 } // namespace |
33 | 68 |
34 class DevToolsFrameTraceRecorderData | 69 class DevToolsFrameTraceRecorderData |
35 : public base::trace_event::ConvertableToTraceFormat { | 70 : public base::RefCounted<DevToolsFrameTraceRecorderData> { |
36 public: | 71 public: |
37 DevToolsFrameTraceRecorderData(const cc::CompositorFrameMetadata& metadata) | 72 DevToolsFrameTraceRecorderData(const cc::CompositorFrameMetadata& metadata) |
38 : metadata_(metadata), | 73 : metadata_(metadata), timestamp_(base::TraceTicks::Now()) {} |
39 weak_factory_(this) { | |
40 } | |
41 | |
42 base::WeakPtr<DevToolsFrameTraceRecorderData> GetWeakPtr() { | |
43 return weak_factory_.GetWeakPtr(); | |
44 } | |
45 | 74 |
46 void FrameCaptured(const SkBitmap& bitmap, ReadbackResponse response) { | 75 void FrameCaptured(const SkBitmap& bitmap, ReadbackResponse response) { |
47 if (response != READBACK_SUCCESS) | 76 if (response != READBACK_SUCCESS) |
48 return; | 77 return; |
49 int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); | 78 int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); |
50 if (current_frame_count >= kMaximumFrameDataCount) | 79 if (current_frame_count >= kMaximumFrameDataCount) |
51 return; | 80 return; |
52 frame_ = bitmap; | 81 if (bitmap.drawsNothing()) |
53 if (!frame_.drawsNothing()) | 82 return; |
54 base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, 1); | 83 base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, 1); |
| 84 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP( |
| 85 TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), "Screenshot", 1, |
| 86 timestamp_.ToInternalValue(), |
| 87 scoped_refptr<base::trace_event::ConvertableToTraceFormat>( |
| 88 new TraceableDevToolsScreenshot(bitmap))); |
55 } | 89 } |
56 | 90 |
57 void CaptureFrame(RenderFrameHostImpl* host) { | 91 void CaptureFrame(RenderFrameHostImpl* host) { |
58 RenderWidgetHostViewBase* view = | 92 RenderWidgetHostViewBase* view = |
59 static_cast<RenderWidgetHostViewBase*>(host->GetView()); | 93 static_cast<RenderWidgetHostViewBase*>(host->GetView()); |
60 if (!view) | 94 if (!view) |
61 return; | 95 return; |
62 int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); | 96 int current_frame_count = base::subtle::NoBarrier_Load(&frame_data_count); |
63 if (current_frame_count >= kMaximumFrameDataCount) | 97 if (current_frame_count >= kMaximumFrameDataCount) |
64 return; | 98 return; |
65 float scale = metadata_.page_scale_factor; | 99 float scale = metadata_.page_scale_factor; |
66 float area = metadata_.scrollable_viewport_size.GetArea(); | 100 float area = metadata_.scrollable_viewport_size.GetArea(); |
67 if (area * scale * scale > kFrameAreaLimit) | 101 if (area * scale * scale > kFrameAreaLimit) |
68 scale = sqrt(kFrameAreaLimit / area); | 102 scale = sqrt(kFrameAreaLimit / area); |
69 gfx::Size snapshot_size(gfx::ToRoundedSize(gfx::ScaleSize( | 103 gfx::Size snapshot_size(gfx::ToRoundedSize(gfx::ScaleSize( |
70 metadata_.scrollable_viewport_size, scale))); | 104 metadata_.scrollable_viewport_size, scale))); |
71 view->CopyFromCompositingSurface(gfx::Rect(), snapshot_size, | 105 view->CopyFromCompositingSurface( |
72 base::Bind( | 106 gfx::Rect(), snapshot_size, |
73 &DevToolsFrameTraceRecorderData::FrameCaptured, | 107 base::Bind(&DevToolsFrameTraceRecorderData::FrameCaptured, this), |
74 GetWeakPtr()), | |
75 kN32_SkColorType); | 108 kN32_SkColorType); |
76 } | 109 } |
77 | 110 |
78 void AppendAsTraceFormat(std::string* out) const override { | |
79 out->append("\""); | |
80 if (!frame_.drawsNothing()) { | |
81 std::vector<unsigned char> data; | |
82 SkAutoLockPixels lock_image(frame_); | |
83 bool encoded = gfx::PNGCodec::Encode( | |
84 reinterpret_cast<unsigned char*>(frame_.getAddr32(0, 0)), | |
85 gfx::PNGCodec::FORMAT_SkBitmap, | |
86 gfx::Size(frame_.width(), frame_.height()), | |
87 frame_.width() * frame_.bytesPerPixel(), | |
88 false, std::vector<gfx::PNGCodec::Comment>(), &data); | |
89 if (encoded) { | |
90 std::string encoded_data; | |
91 base::Base64Encode( | |
92 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), | |
93 &encoded_data); | |
94 out->append(encoded_data); | |
95 } | |
96 } | |
97 out->append("\""); | |
98 } | |
99 | |
100 private: | 111 private: |
101 ~DevToolsFrameTraceRecorderData() override { | 112 friend class base::RefCounted<DevToolsFrameTraceRecorderData>; |
102 if (!frame_.drawsNothing()) | 113 ~DevToolsFrameTraceRecorderData() {} |
103 base::subtle::NoBarrier_AtomicIncrement(&frame_data_count, -1); | |
104 } | |
105 | 114 |
106 cc::CompositorFrameMetadata metadata_; | 115 cc::CompositorFrameMetadata metadata_; |
107 SkBitmap frame_; | 116 base::TraceTicks timestamp_; |
108 base::WeakPtrFactory<DevToolsFrameTraceRecorderData> weak_factory_; | |
109 | 117 |
110 DISALLOW_COPY_AND_ASSIGN(DevToolsFrameTraceRecorderData); | 118 DISALLOW_COPY_AND_ASSIGN(DevToolsFrameTraceRecorderData); |
111 }; | 119 }; |
112 | 120 |
113 DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() { } | 121 DevToolsFrameTraceRecorder::DevToolsFrameTraceRecorder() { } |
114 | 122 |
115 DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { } | 123 DevToolsFrameTraceRecorder::~DevToolsFrameTraceRecorder() { } |
116 | 124 |
117 void DevToolsFrameTraceRecorder::OnSwapCompositorFrame( | 125 void DevToolsFrameTraceRecorder::OnSwapCompositorFrame( |
118 RenderFrameHostImpl* host, | 126 RenderFrameHostImpl* host, |
119 const cc::CompositorFrameMetadata& frame_metadata) { | 127 const cc::CompositorFrameMetadata& frame_metadata) { |
120 if (!host) | 128 if (!host) |
121 return; | 129 return; |
122 | 130 |
123 bool enabled; | 131 bool enabled; |
124 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 132 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
125 TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), &enabled); | 133 TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), &enabled); |
126 if (!enabled) | 134 if (!enabled) { |
| 135 pending_frame_data_ = nullptr; |
127 return; | 136 return; |
128 | 137 } |
129 if (last_event_data_.get()) | 138 if (pending_frame_data_.get()) |
130 last_event_data_->CaptureFrame(host); | 139 pending_frame_data_->CaptureFrame(host); |
131 | 140 pending_frame_data_ = new DevToolsFrameTraceRecorderData(frame_metadata); |
132 scoped_refptr<DevToolsFrameTraceRecorderData> data( | |
133 new DevToolsFrameTraceRecorderData(frame_metadata)); | |
134 last_event_data_ = data->GetWeakPtr(); | |
135 TRACE_EVENT_INSTANT1( | |
136 TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), | |
137 "CaptureFrame", | |
138 TRACE_EVENT_SCOPE_THREAD, | |
139 "data", | |
140 scoped_refptr<base::trace_event::ConvertableToTraceFormat>(data)); | |
141 } | 141 } |
142 | 142 |
143 } // namespace content | 143 } // namespace content |
OLD | NEW |