| 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" | 9 #include "base/logging.h" |
| 10 #include "base/safe_numerics.h" | 10 #include "base/safe_numerics.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 bitmap = | 66 bitmap = |
| 67 skia::ImageOperations::Resize(input_bitmap, | 67 skia::ImageOperations::Resize(input_bitmap, |
| 68 skia::ImageOperations::RESIZE_GOOD, | 68 skia::ImageOperations::RESIZE_GOOD, |
| 69 target_size_pre_rotation.width(), | 69 target_size_pre_rotation.width(), |
| 70 target_size_pre_rotation.height(), | 70 target_size_pre_rotation.height(), |
| 71 static_cast<SkBitmap::Allocator*>(NULL)); | 71 static_cast<SkBitmap::Allocator*>(NULL)); |
| 72 RotateBitmap(&bitmap, rotation); | 72 RotateBitmap(&bitmap, rotation); |
| 73 return bitmap; | 73 return bitmap; |
| 74 } | 74 } |
| 75 | 75 |
| 76 scoped_refptr<base::RefCountedBytes> ScaleRotateAndEncodeBitmap( |
| 77 const SkBitmap& input_bitmap, |
| 78 gfx::Size target_size_pre_rotation, |
| 79 gfx::Display::Rotation rotation) { |
| 80 SkBitmap bitmap = |
| 81 ScaleAndRotateBitmap(input_bitmap, target_size_pre_rotation, rotation); |
| 82 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); |
| 83 unsigned char* pixels = |
| 84 reinterpret_cast<unsigned char*>(bitmap.pixelRef()->pixels()); |
| 85 if (!gfx::PNGCodec::Encode(pixels, |
| 86 gfx::PNGCodec::FORMAT_BGRA, |
| 87 gfx::Size(bitmap.width(), bitmap.height()), |
| 88 base::checked_numeric_cast<int>(bitmap.rowBytes()), |
| 89 true, |
| 90 std::vector<gfx::PNGCodec::Comment>(), |
| 91 &png_data->data())) { |
| 92 return scoped_refptr<base::RefCountedBytes>(); |
| 93 } |
| 94 return png_data; |
| 95 } |
| 96 |
| 76 void ScaleAndRotateCopyOutputResult( | 97 void ScaleAndRotateCopyOutputResult( |
| 77 const GrabWindowSnapshotAsyncCallback& callback, | 98 const GrabWindowSnapshotAsyncCallback& callback, |
| 78 const gfx::Size& target_size, | 99 const gfx::Size& target_size, |
| 79 gfx::Display::Rotation rotation, | 100 gfx::Display::Rotation rotation, |
| 80 scoped_refptr<base::TaskRunner> background_task_runner, | 101 scoped_refptr<base::TaskRunner> background_task_runner, |
| 81 scoped_ptr<cc::CopyOutputResult> result) { | 102 scoped_ptr<cc::CopyOutputResult> result) { |
| 82 if (result->IsEmpty()) { | 103 if (result->IsEmpty()) { |
| 83 callback.Run(gfx::Image()); | 104 callback.Run(gfx::Image()); |
| 84 return; | 105 return; |
| 85 } | 106 } |
| 86 | 107 |
| 87 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it | 108 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it |
| 88 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't | 109 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't |
| 89 // be used here because it's not in content/public. Move the scaling code | 110 // be used here because it's not in content/public. Move the scaling code |
| 90 // somewhere so that it can be reused here. | 111 // somewhere so that it can be reused here. |
| 91 base::PostTaskAndReplyWithResult( | 112 base::PostTaskAndReplyWithResult( |
| 92 background_task_runner, | 113 background_task_runner, |
| 93 FROM_HERE, | 114 FROM_HERE, |
| 94 base::Bind( | 115 base::Bind( |
| 95 ScaleAndRotateBitmap, *result->TakeBitmap(), target_size, rotation), | 116 ScaleAndRotateBitmap, *result->TakeBitmap(), target_size, rotation), |
| 96 base::Bind(&OnFrameScalingFinished, callback)); | 117 base::Bind(&OnFrameScalingFinished, callback)); |
| 97 } | 118 } |
| 98 | 119 |
| 120 void ScaleRotateAndEncodeCopyOutputResult( |
| 121 const GrabWindowSnapshotAsyncPNGCallback& callback, |
| 122 const gfx::Size& target_size, |
| 123 gfx::Display::Rotation rotation, |
| 124 scoped_refptr<base::TaskRunner> background_task_runner, |
| 125 scoped_ptr<cc::CopyOutputResult> result) { |
| 126 if (result->IsEmpty()) { |
| 127 callback.Run(scoped_refptr<base::RefCountedBytes>()); |
| 128 return; |
| 129 } |
| 130 |
| 131 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it |
| 132 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't |
| 133 // be used here because it's not in content/public. Move the scaling code |
| 134 // somewhere so that it can be reused here. |
| 135 base::PostTaskAndReplyWithResult(background_task_runner, |
| 136 FROM_HERE, |
| 137 base::Bind(ScaleRotateAndEncodeBitmap, |
| 138 *result->TakeBitmap(), |
| 139 target_size, |
| 140 rotation), |
| 141 callback); |
| 142 } |
| 143 |
| 99 gfx::Rect GetTargetBoundsFromWindow(gfx::NativeWindow window, | 144 gfx::Rect GetTargetBoundsFromWindow(gfx::NativeWindow window, |
| 100 gfx::Rect snapshot_bounds) { | 145 gfx::Rect snapshot_bounds) { |
| 101 gfx::RectF read_pixels_bounds = snapshot_bounds; | 146 gfx::RectF read_pixels_bounds = snapshot_bounds; |
| 102 | 147 |
| 103 // We must take into account the window's position on the desktop. | 148 // We must take into account the window's position on the desktop. |
| 104 read_pixels_bounds.Offset( | 149 read_pixels_bounds.Offset( |
| 105 window->GetBoundsInRootWindow().origin().OffsetFromOrigin()); | 150 window->GetBoundsInRootWindow().origin().OffsetFromOrigin()); |
| 106 aura::WindowEventDispatcher* dispatcher = window->GetDispatcher(); | 151 aura::WindowEventDispatcher* dispatcher = window->GetDispatcher(); |
| 107 if (dispatcher) | 152 if (dispatcher) |
| 108 dispatcher->host()->GetRootTransform().TransformRect(&read_pixels_bounds); | 153 dispatcher->host()->GetRootTransform().TransformRect(&read_pixels_bounds); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 pixels, gfx::PNGCodec::FORMAT_BGRA, | 195 pixels, gfx::PNGCodec::FORMAT_BGRA, |
| 151 gfx::Size(bitmap.width(), bitmap.height()), | 196 gfx::Size(bitmap.width(), bitmap.height()), |
| 152 base::checked_numeric_cast<int>(bitmap.rowBytes()), | 197 base::checked_numeric_cast<int>(bitmap.rowBytes()), |
| 153 true, std::vector<gfx::PNGCodec::Comment>(), | 198 true, std::vector<gfx::PNGCodec::Comment>(), |
| 154 png_representation); | 199 png_representation); |
| 155 } | 200 } |
| 156 | 201 |
| 157 void MakeAsyncCopyRequest( | 202 void MakeAsyncCopyRequest( |
| 158 gfx::NativeWindow window, | 203 gfx::NativeWindow window, |
| 159 const gfx::Rect& source_rect, | 204 const gfx::Rect& source_rect, |
| 160 const gfx::Size& target_size, | 205 const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { |
| 161 scoped_refptr<base::TaskRunner> background_task_runner, | |
| 162 const GrabWindowSnapshotAsyncCallback& callback) { | |
| 163 gfx::Display::Rotation rotation = gfx::Screen::GetScreenFor(window) | |
| 164 ->GetDisplayNearestWindow(window) | |
| 165 .rotation(); | |
| 166 scoped_ptr<cc::CopyOutputRequest> request = | 206 scoped_ptr<cc::CopyOutputRequest> request = |
| 167 cc::CopyOutputRequest::CreateBitmapRequest( | 207 cc::CopyOutputRequest::CreateBitmapRequest(callback); |
| 168 base::Bind(&ScaleAndRotateCopyOutputResult, | |
| 169 callback, | |
| 170 target_size, | |
| 171 rotation, | |
| 172 background_task_runner)); | |
| 173 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); | 208 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); |
| 174 window->layer()->RequestCopyOfOutput(request.Pass()); | 209 window->layer()->RequestCopyOfOutput(request.Pass()); |
| 175 } | 210 } |
| 176 | 211 |
| 177 void GrabWindowSnapshotAndScaleAsync( | 212 void GrabWindowSnapshotAndScaleAsync( |
| 178 gfx::NativeWindow window, | 213 gfx::NativeWindow window, |
| 179 const gfx::Rect& source_rect, | 214 const gfx::Rect& source_rect, |
| 180 const gfx::Size& target_size, | 215 const gfx::Size& target_size, |
| 181 scoped_refptr<base::TaskRunner> background_task_runner, | 216 scoped_refptr<base::TaskRunner> background_task_runner, |
| 182 const GrabWindowSnapshotAsyncCallback& callback) { | 217 const GrabWindowSnapshotAsyncCallback& callback) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 194 break; | 229 break; |
| 195 case gfx::Display::ROTATE_90: | 230 case gfx::Display::ROTATE_90: |
| 196 case gfx::Display::ROTATE_270: | 231 case gfx::Display::ROTATE_270: |
| 197 rotated_target_size = | 232 rotated_target_size = |
| 198 gfx::Size(target_size.height(), target_size.width()); | 233 gfx::Size(target_size.height(), target_size.width()); |
| 199 break; | 234 break; |
| 200 }; | 235 }; |
| 201 | 236 |
| 202 MakeAsyncCopyRequest(window, | 237 MakeAsyncCopyRequest(window, |
| 203 source_rect, | 238 source_rect, |
| 204 rotated_target_size, | 239 base::Bind(&ScaleAndRotateCopyOutputResult, |
| 205 background_task_runner, | 240 callback, |
| 206 callback); | 241 rotated_target_size, |
| 242 rotation, |
| 243 background_task_runner)); |
| 207 } | 244 } |
| 208 | 245 |
| 209 void GrabWindowSnapshotAsync( | 246 void GrabWindowSnapshotAsync( |
| 210 gfx::NativeWindow window, | 247 gfx::NativeWindow window, |
| 211 const gfx::Rect& source_rect, | 248 const gfx::Rect& source_rect, |
| 212 scoped_refptr<base::TaskRunner> background_task_runner, | 249 scoped_refptr<base::TaskRunner> background_task_runner, |
| 213 const GrabWindowSnapshotAsyncCallback& callback) { | 250 const GrabWindowSnapshotAsyncPNGCallback& callback) { |
| 214 gfx::Size target_size = GetTargetBoundsFromWindow(window, source_rect).size(); | 251 gfx::Size target_size = GetTargetBoundsFromWindow(window, source_rect).size(); |
| 215 MakeAsyncCopyRequest( | 252 gfx::Display::Rotation rotation = gfx::Screen::GetScreenFor(window) |
| 216 window, source_rect, target_size, background_task_runner, callback); | 253 ->GetDisplayNearestWindow(window) |
| 254 .rotation(); |
| 255 MakeAsyncCopyRequest(window, |
| 256 source_rect, |
| 257 base::Bind(&ScaleRotateAndEncodeCopyOutputResult, |
| 258 callback, |
| 259 target_size, |
| 260 rotation, |
| 261 background_task_runner)); |
| 217 } | 262 } |
| 218 | 263 |
| 219 } // namespace ui | 264 } // namespace ui |
| OLD | NEW |