OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/snapshot/snapshot.h" | 5 #include "ui/snapshot/snapshot.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/logging.h" | |
10 #include "base/numerics/safe_conversions.h" | |
11 #include "base/task_runner_util.h" | 9 #include "base/task_runner_util.h" |
12 #include "cc/output/copy_output_request.h" | 10 #include "cc/output/copy_output_request.h" |
13 #include "cc/output/copy_output_result.h" | |
14 #include "skia/ext/image_operations.h" | |
15 #include "third_party/skia/include/core/SkBitmap.h" | 11 #include "third_party/skia/include/core/SkBitmap.h" |
16 #include "third_party/skia/include/core/SkPixelRef.h" | |
17 #include "ui/aura/window.h" | 12 #include "ui/aura/window.h" |
18 #include "ui/aura/window_event_dispatcher.h" | |
19 #include "ui/compositor/compositor.h" | 13 #include "ui/compositor/compositor.h" |
20 #include "ui/compositor/dip_util.h" | 14 #include "ui/compositor/dip_util.h" |
21 #include "ui/compositor/layer.h" | 15 #include "ui/compositor/layer.h" |
22 #include "ui/gfx/codec/png_codec.h" | 16 #include "ui/snapshot/snapshot_async.h" |
23 #include "ui/gfx/display.h" | |
24 #include "ui/gfx/image/image.h" | |
25 #include "ui/gfx/image/image_skia.h" | |
26 #include "ui/gfx/rect.h" | |
27 #include "ui/gfx/rect_conversions.h" | |
28 #include "ui/gfx/rect_f.h" | |
29 #include "ui/gfx/screen.h" | |
30 #include "ui/gfx/skbitmap_operations.h" | |
31 #include "ui/gfx/transform.h" | |
32 | 17 |
33 namespace ui { | 18 namespace ui { |
34 | 19 |
35 namespace { | |
36 | |
37 void OnFrameScalingFinished( | |
38 const GrabWindowSnapshotAsyncCallback& callback, | |
39 const SkBitmap& scaled_bitmap) { | |
40 callback.Run(gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(scaled_bitmap))); | |
41 } | |
42 | |
43 SkBitmap ScaleBitmap(const SkBitmap& input_bitmap, | |
44 const gfx::Size& target_size) { | |
45 return skia::ImageOperations::Resize( | |
46 input_bitmap, | |
47 skia::ImageOperations::RESIZE_GOOD, | |
48 target_size.width(), | |
49 target_size.height(), | |
50 static_cast<SkBitmap::Allocator*>(NULL)); | |
51 } | |
52 | |
53 scoped_refptr<base::RefCountedBytes> EncodeBitmap(const SkBitmap& bitmap) { | |
54 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); | |
55 unsigned char* pixels = | |
56 reinterpret_cast<unsigned char*>(bitmap.pixelRef()->pixels()); | |
57 if (!gfx::PNGCodec::Encode(pixels, | |
58 gfx::PNGCodec::FORMAT_BGRA, | |
59 gfx::Size(bitmap.width(), bitmap.height()), | |
60 base::checked_cast<int>(bitmap.rowBytes()), | |
61 true, | |
62 std::vector<gfx::PNGCodec::Comment>(), | |
63 &png_data->data())) { | |
64 return scoped_refptr<base::RefCountedBytes>(); | |
65 } | |
66 return png_data; | |
67 } | |
68 | |
69 void ScaleCopyOutputResult( | |
70 const GrabWindowSnapshotAsyncCallback& callback, | |
71 const gfx::Size& target_size, | |
72 scoped_refptr<base::TaskRunner> background_task_runner, | |
73 scoped_ptr<cc::CopyOutputResult> result) { | |
74 if (result->IsEmpty()) { | |
75 callback.Run(gfx::Image()); | |
76 return; | |
77 } | |
78 | |
79 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it | |
80 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't | |
81 // be used here because it's not in content/public. Move the scaling code | |
82 // somewhere so that it can be reused here. | |
83 base::PostTaskAndReplyWithResult( | |
84 background_task_runner, | |
85 FROM_HERE, | |
86 base::Bind(ScaleBitmap, *result->TakeBitmap(), target_size), | |
87 base::Bind(&OnFrameScalingFinished, callback)); | |
88 } | |
89 | |
90 void EncodeCopyOutputResult( | |
91 const GrabWindowSnapshotAsyncPNGCallback& callback, | |
92 scoped_refptr<base::TaskRunner> background_task_runner, | |
93 scoped_ptr<cc::CopyOutputResult> result) { | |
94 if (result->IsEmpty()) { | |
95 callback.Run(scoped_refptr<base::RefCountedBytes>()); | |
96 return; | |
97 } | |
98 | |
99 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it | |
100 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't | |
101 // be used here because it's not in content/public. Move the scaling code | |
102 // somewhere so that it can be reused here. | |
103 base::PostTaskAndReplyWithResult(background_task_runner, | |
104 FROM_HERE, | |
105 base::Bind(EncodeBitmap, | |
106 *result->TakeBitmap()), | |
107 callback); | |
108 } | |
109 | |
110 } // namespace | |
111 | |
112 bool GrabViewSnapshot(gfx::NativeView view, | 20 bool GrabViewSnapshot(gfx::NativeView view, |
113 std::vector<unsigned char>* png_representation, | 21 std::vector<unsigned char>* png_representation, |
114 const gfx::Rect& snapshot_bounds) { | 22 const gfx::Rect& snapshot_bounds) { |
115 return GrabWindowSnapshot(view, png_representation, snapshot_bounds); | 23 return GrabWindowSnapshot(view, png_representation, snapshot_bounds); |
116 } | 24 } |
117 | 25 |
118 bool GrabWindowSnapshot(gfx::NativeWindow window, | 26 bool GrabWindowSnapshot(gfx::NativeWindow window, |
119 std::vector<unsigned char>* png_representation, | 27 std::vector<unsigned char>* png_representation, |
120 const gfx::Rect& snapshot_bounds) { | 28 const gfx::Rect& snapshot_bounds) { |
121 // Not supported in Aura. Callers should fall back to the async version. | 29 // Not supported in Aura. Callers should fall back to the async version. |
122 return false; | 30 return false; |
123 } | 31 } |
124 | 32 |
125 void MakeAsyncCopyRequest( | 33 static void MakeAsyncCopyRequest( |
126 gfx::NativeWindow window, | 34 gfx::NativeWindow window, |
127 const gfx::Rect& source_rect, | 35 const gfx::Rect& source_rect, |
128 const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { | 36 const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { |
129 scoped_ptr<cc::CopyOutputRequest> request = | 37 scoped_ptr<cc::CopyOutputRequest> request = |
130 cc::CopyOutputRequest::CreateBitmapRequest(callback); | 38 cc::CopyOutputRequest::CreateBitmapRequest(callback); |
131 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); | 39 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); |
132 window->layer()->RequestCopyOfOutput(request.Pass()); | 40 window->layer()->RequestCopyOfOutput(request.Pass()); |
133 } | 41 } |
134 | 42 |
135 void GrabWindowSnapshotAndScaleAsync( | 43 void GrabWindowSnapshotAndScaleAsync( |
136 gfx::NativeWindow window, | 44 gfx::NativeWindow window, |
137 const gfx::Rect& source_rect, | 45 const gfx::Rect& source_rect, |
138 const gfx::Size& target_size, | 46 const gfx::Size& target_size, |
139 scoped_refptr<base::TaskRunner> background_task_runner, | 47 scoped_refptr<base::TaskRunner> background_task_runner, |
140 const GrabWindowSnapshotAsyncCallback& callback) { | 48 const GrabWindowSnapshotAsyncCallback& callback) { |
141 MakeAsyncCopyRequest(window, | 49 MakeAsyncCopyRequest(window, |
142 source_rect, | 50 source_rect, |
143 base::Bind(&ScaleCopyOutputResult, | 51 base::Bind(&SnapshotAsync::ScaleCopyOutputResult, |
144 callback, | 52 callback, |
145 target_size, | 53 target_size, |
146 background_task_runner)); | 54 background_task_runner)); |
147 } | 55 } |
148 | 56 |
149 void GrabWindowSnapshotAsync( | 57 void GrabWindowSnapshotAsync( |
150 gfx::NativeWindow window, | 58 gfx::NativeWindow window, |
151 const gfx::Rect& source_rect, | 59 const gfx::Rect& source_rect, |
152 scoped_refptr<base::TaskRunner> background_task_runner, | 60 scoped_refptr<base::TaskRunner> background_task_runner, |
153 const GrabWindowSnapshotAsyncPNGCallback& callback) { | 61 const GrabWindowSnapshotAsyncPNGCallback& callback) { |
154 MakeAsyncCopyRequest(window, | 62 MakeAsyncCopyRequest(window, |
155 source_rect, | 63 source_rect, |
156 base::Bind(&EncodeCopyOutputResult, | 64 base::Bind(&SnapshotAsync::EncodeCopyOutputResult, |
157 callback, | 65 callback, |
158 background_task_runner)); | 66 background_task_runner)); |
159 } | 67 } |
160 | 68 |
161 void GrabViewSnapshotAsync( | 69 void GrabViewSnapshotAsync( |
162 gfx::NativeView view, | 70 gfx::NativeView view, |
163 const gfx::Rect& source_rect, | 71 const gfx::Rect& source_rect, |
164 scoped_refptr<base::TaskRunner> background_task_runner, | 72 scoped_refptr<base::TaskRunner> background_task_runner, |
165 const GrabWindowSnapshotAsyncPNGCallback& callback) { | 73 const GrabWindowSnapshotAsyncPNGCallback& callback) { |
166 GrabWindowSnapshotAsync(view, source_rect, background_task_runner, callback); | 74 GrabWindowSnapshotAsync(view, source_rect, background_task_runner, callback); |
167 } | 75 } |
168 | 76 |
169 | 77 |
170 } // namespace ui | 78 } // namespace ui |
OLD | NEW |