Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(369)

Side by Side Diff: ui/snapshot/snapshot_aura.cc

Issue 119753007: Add GrabWindowSnapshotAsync tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add windows snapshot async too Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/snapshot/snapshot_android.cc ('k') | ui/snapshot/snapshot_aura_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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" 9 #include "base/logging.h"
10 #include "base/safe_numerics.h" 10 #include "base/safe_numerics.h"
(...skipping 22 matching lines...) Expand all
33 namespace ui { 33 namespace ui {
34 34
35 namespace { 35 namespace {
36 36
37 void OnFrameScalingFinished( 37 void OnFrameScalingFinished(
38 const GrabWindowSnapshotAsyncCallback& callback, 38 const GrabWindowSnapshotAsyncCallback& callback,
39 const SkBitmap& scaled_bitmap) { 39 const SkBitmap& scaled_bitmap) {
40 callback.Run(gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(scaled_bitmap))); 40 callback.Run(gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(scaled_bitmap)));
41 } 41 }
42 42
43 void ScaleCopyOutputResult( 43 void RotateBitmap(SkBitmap* bitmap, gfx::Display::Rotation rotation) {
44 switch (rotation) {
45 case gfx::Display::ROTATE_0:
46 break;
47 case gfx::Display::ROTATE_90:
48 *bitmap = SkBitmapOperations::Rotate(*bitmap,
49 SkBitmapOperations::ROTATION_270_CW);
50 break;
51 case gfx::Display::ROTATE_180:
52 *bitmap = SkBitmapOperations::Rotate(*bitmap,
53 SkBitmapOperations::ROTATION_180_CW);
54 break;
55 case gfx::Display::ROTATE_270:
56 *bitmap = SkBitmapOperations::Rotate(*bitmap,
57 SkBitmapOperations::ROTATION_90_CW);
58 break;
59 }
60 }
61
62 SkBitmap ScaleAndRotateBitmap(const SkBitmap& input_bitmap,
63 gfx::Size target_size_pre_rotation,
64 gfx::Display::Rotation rotation) {
65 SkBitmap bitmap;
66 bitmap =
67 skia::ImageOperations::Resize(input_bitmap,
68 skia::ImageOperations::RESIZE_GOOD,
69 target_size_pre_rotation.width(),
70 target_size_pre_rotation.height(),
71 static_cast<SkBitmap::Allocator*>(NULL));
72 RotateBitmap(&bitmap, rotation);
73 return bitmap;
74 }
75
76 void ScaleAndRotateCopyOutputResult(
44 const GrabWindowSnapshotAsyncCallback& callback, 77 const GrabWindowSnapshotAsyncCallback& callback,
45 const gfx::Size& target_size, 78 const gfx::Size& target_size,
79 gfx::Display::Rotation rotation,
46 scoped_refptr<base::TaskRunner> background_task_runner, 80 scoped_refptr<base::TaskRunner> background_task_runner,
47 scoped_ptr<cc::CopyOutputResult> result) { 81 scoped_ptr<cc::CopyOutputResult> result) {
48 if (result->IsEmpty()) { 82 if (result->IsEmpty()) {
49 callback.Run(gfx::Image()); 83 callback.Run(gfx::Image());
50 return; 84 return;
51 } 85 }
52 86
53 // There are two overrides for skia::ImageOperations::Resize(), so we need get
54 // pointer to the right override explicitly (otherwise the base::Bind() call
55 // below won't compile).
56 SkBitmap (*resize_function)(const SkBitmap&,
57 skia::ImageOperations::ResizeMethod, int, int,
58 SkBitmap::Allocator* allocator) =
59 &skia::ImageOperations::Resize;
60
61 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it 87 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it
62 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't 88 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't
63 // be used here because it's not in content/public. Move the scaling code 89 // be used here because it's not in content/public. Move the scaling code
64 // somewhere so that it can be reused here. 90 // somewhere so that it can be reused here.
65 base::PostTaskAndReplyWithResult( 91 base::PostTaskAndReplyWithResult(
66 background_task_runner, FROM_HERE, 92 background_task_runner,
67 base::Bind(resize_function, *result->TakeBitmap(), 93 FROM_HERE,
68 skia::ImageOperations::RESIZE_GOOD, 94 base::Bind(
69 target_size.width(), target_size.height(), 95 ScaleAndRotateBitmap, *result->TakeBitmap(), target_size, rotation),
70 static_cast<SkBitmap::Allocator*>(NULL)),
71 base::Bind(&OnFrameScalingFinished, callback)); 96 base::Bind(&OnFrameScalingFinished, callback));
72 } 97 }
73 98
74 } // namespace 99 gfx::Rect GetTargetBoundsFromWindow(gfx::NativeWindow window,
75 100 gfx::Rect snapshot_bounds) {
76 bool GrabViewSnapshot(gfx::NativeView view,
77 std::vector<unsigned char>* png_representation,
78 const gfx::Rect& snapshot_bounds) {
79 return GrabWindowSnapshot(view, png_representation, snapshot_bounds);
80 }
81
82 bool GrabWindowSnapshot(gfx::NativeWindow window,
83 std::vector<unsigned char>* png_representation,
84 const gfx::Rect& snapshot_bounds) {
85 ui::Compositor* compositor = window->layer()->GetCompositor();
86
87 gfx::RectF read_pixels_bounds = snapshot_bounds; 101 gfx::RectF read_pixels_bounds = snapshot_bounds;
88 102
89 // We must take into account the window's position on the desktop. 103 // We must take into account the window's position on the desktop.
90 read_pixels_bounds.Offset( 104 read_pixels_bounds.Offset(
91 window->GetBoundsInRootWindow().origin().OffsetFromOrigin()); 105 window->GetBoundsInRootWindow().origin().OffsetFromOrigin());
92 aura::WindowEventDispatcher* dispatcher = window->GetDispatcher(); 106 aura::WindowEventDispatcher* dispatcher = window->GetDispatcher();
93 if (dispatcher) 107 if (dispatcher)
94 dispatcher->host()->GetRootTransform().TransformRect(&read_pixels_bounds); 108 dispatcher->host()->GetRootTransform().TransformRect(&read_pixels_bounds);
95 109
96 gfx::Rect read_pixels_bounds_in_pixel = 110 gfx::Rect read_pixels_bounds_in_pixel =
97 gfx::ToEnclosingRect(read_pixels_bounds); 111 gfx::ToEnclosingRect(read_pixels_bounds);
98 112
99 // Sometimes (i.e. when using Aero on Windows) the compositor's size is 113 // Sometimes (i.e. when using Aero on Windows) the compositor's size is
100 // smaller than the window bounds. So trim appropriately. 114 // smaller than the window bounds. So trim appropriately.
115 ui::Compositor* compositor = window->layer()->GetCompositor();
101 read_pixels_bounds_in_pixel.Intersect(gfx::Rect(compositor->size())); 116 read_pixels_bounds_in_pixel.Intersect(gfx::Rect(compositor->size()));
102 117
103 DCHECK_LE(0, read_pixels_bounds.x()); 118 DCHECK_LE(0, read_pixels_bounds.x());
104 DCHECK_LE(0, read_pixels_bounds.y()); 119 DCHECK_LE(0, read_pixels_bounds.y());
105 120
121 return read_pixels_bounds_in_pixel;
122 }
123
124 } // namespace
125
126 bool GrabViewSnapshot(gfx::NativeView view,
127 std::vector<unsigned char>* png_representation,
128 const gfx::Rect& snapshot_bounds) {
129 return GrabWindowSnapshot(view, png_representation, snapshot_bounds);
130 }
131
132 bool GrabWindowSnapshot(gfx::NativeWindow window,
133 std::vector<unsigned char>* png_representation,
134 const gfx::Rect& snapshot_bounds) {
135 gfx::Rect read_pixels_bounds_in_pixel =
136 GetTargetBoundsFromWindow(window, snapshot_bounds);
137
138 ui::Compositor* compositor = window->layer()->GetCompositor();
106 SkBitmap bitmap; 139 SkBitmap bitmap;
107 if (!compositor->ReadPixels(&bitmap, read_pixels_bounds_in_pixel)) 140 if (!compositor->ReadPixels(&bitmap, read_pixels_bounds_in_pixel))
108 return false; 141 return false;
109 142
110 gfx::Display display = 143 gfx::Display display =
111 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window); 144 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window);
112 switch (display.rotation()) { 145 RotateBitmap(&bitmap, display.rotation());
113 case gfx::Display::ROTATE_0:
114 break;
115 case gfx::Display::ROTATE_90:
116 bitmap = SkBitmapOperations::Rotate(
117 bitmap, SkBitmapOperations::ROTATION_270_CW);
118 break;
119 case gfx::Display::ROTATE_180:
120 bitmap = SkBitmapOperations::Rotate(
121 bitmap, SkBitmapOperations::ROTATION_180_CW);
122 break;
123 case gfx::Display::ROTATE_270:
124 bitmap = SkBitmapOperations::Rotate(
125 bitmap, SkBitmapOperations::ROTATION_90_CW);
126 break;
127 }
128 146
129 unsigned char* pixels = reinterpret_cast<unsigned char*>( 147 unsigned char* pixels = reinterpret_cast<unsigned char*>(
130 bitmap.pixelRef()->pixels()); 148 bitmap.pixelRef()->pixels());
131 return gfx::PNGCodec::Encode( 149 return gfx::PNGCodec::Encode(
132 pixels, gfx::PNGCodec::FORMAT_BGRA, 150 pixels, gfx::PNGCodec::FORMAT_BGRA,
133 gfx::Size(bitmap.width(), bitmap.height()), 151 gfx::Size(bitmap.width(), bitmap.height()),
134 base::checked_numeric_cast<int>(bitmap.rowBytes()), 152 base::checked_numeric_cast<int>(bitmap.rowBytes()),
135 true, std::vector<gfx::PNGCodec::Comment>(), 153 true, std::vector<gfx::PNGCodec::Comment>(),
136 png_representation); 154 png_representation);
137 } 155 }
138 156
139 SNAPSHOT_EXPORT void GrabWindowSnapshotAsync( 157 void GrabWindowSnapshotAndScaleAsync(
140 gfx::NativeWindow window, 158 gfx::NativeWindow window,
141 const gfx::Rect& source_rect, 159 const gfx::Rect& source_rect,
142 const gfx::Size& target_size, 160 const gfx::Size& target_size,
143 scoped_refptr<base::TaskRunner> background_task_runner, 161 scoped_refptr<base::TaskRunner> background_task_runner,
144 const GrabWindowSnapshotAsyncCallback& callback) { 162 const GrabWindowSnapshotAsyncCallback& callback) {
163 // target_size is post-rotation, and so logically this is a rotate and then
164 // scale operation. However, it will usually be more efficient to scale first
165 // (given that this is mostly used for thumbnails) and then rotate.
166 gfx::Display::Rotation rotation = gfx::Screen::GetScreenFor(window)
167 ->GetDisplayNearestWindow(window)
168 .rotation();
169 gfx::Size rotated_target_size;
170 switch (rotation) {
171 case gfx::Display::ROTATE_0:
172 case gfx::Display::ROTATE_180:
173 rotated_target_size = target_size;
174 break;
175 case gfx::Display::ROTATE_90:
176 case gfx::Display::ROTATE_270:
177 rotated_target_size =
178 gfx::Size(target_size.height(), target_size.width());
179 break;
180 };
181
145 scoped_ptr<cc::CopyOutputRequest> request = 182 scoped_ptr<cc::CopyOutputRequest> request =
146 cc::CopyOutputRequest::CreateBitmapRequest( 183 cc::CopyOutputRequest::CreateBitmapRequest(
147 base::Bind(&ScaleCopyOutputResult, callback, target_size, 184 base::Bind(&ScaleAndRotateCopyOutputResult,
185 callback,
186 rotated_target_size,
187 rotation,
148 background_task_runner)); 188 background_task_runner));
149 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); 189 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect));
150 window->layer()->RequestCopyOfOutput(request.Pass()); 190 window->layer()->RequestCopyOfOutput(request.Pass());
191 }
192
193 void GrabWindowSnapshotAsync(
194 gfx::NativeWindow window,
195 const gfx::Rect& source_rect,
196 scoped_refptr<base::TaskRunner> background_task_runner,
197 const GrabWindowSnapshotAsyncCallback& callback) {
198 gfx::Size target_size = GetTargetBoundsFromWindow(window, source_rect).size();
199 gfx::Display::Rotation rotation = gfx::Screen::GetScreenFor(window)
200 ->GetDisplayNearestWindow(window)
201 .rotation();
202 scoped_ptr<cc::CopyOutputRequest> request =
Sergey Ulanov 2014/01/08 02:24:16 It looks like a lot of code in this function is du
enne (OOO) 2014/01/08 18:50:48 Done. Can't call GrabWindowSnapshotAndScaleAsync
203 cc::CopyOutputRequest::CreateBitmapRequest(
204 base::Bind(&ScaleAndRotateCopyOutputResult,
205 callback,
206 target_size,
207 rotation,
208 background_task_runner));
209 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect));
210 window->layer()->RequestCopyOfOutput(request.Pass());
151 } 211 }
152 212
153 } // namespace ui 213 } // namespace ui
OLDNEW
« no previous file with comments | « ui/snapshot/snapshot_android.cc ('k') | ui/snapshot/snapshot_aura_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698