diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-15 19:36:36 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-15 19:36:36 +0000 |
commit | 2e6f39e1739c4e408a6f635e31678376187c232e (patch) | |
tree | 96869e634bb6d0c521579bb82927a6d45de48405 /ui/snapshot | |
parent | c276c7a47a7777522eac0d2675d8cba3d32e56dd (diff) | |
download | chromium_src-2e6f39e1739c4e408a6f635e31678376187c232e.zip chromium_src-2e6f39e1739c4e408a6f635e31678376187c232e.tar.gz chromium_src-2e6f39e1739c4e408a6f635e31678376187c232e.tar.bz2 |
Make ui::Snapshot asynchronous on Android, remove CompositeAndReadback.
The android pixel tests use the ui::Snapshot code to get a pixel copy
of the content_shell's output. Make this behaviour match the aura
implementation of ui::Snapshot by returning false in the synchronous
verion, causing callsites to fall back to the async one.
This implements the async snapshots by moving the aura implementation
out into snapshot_async.cc and reusing that code (with one #if for
RGBA vs BGRA ordering).
After this, the pixel tests get a bitmap from cc instead of creating
their own bitmap. The result is that the bitmap has a slightly
different size (384x528) which is the size of the root layer. The
pixel tests were previously trying to crop to 400x300, which is
outside the bounds of this bitmap, so change them to crop to 300x300
instead, and increment their versions to pick up the new pngs.
BUG=252046, 371592
Review URL: https://codereview.chromium.org/281003002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270778 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/snapshot')
-rw-r--r-- | ui/snapshot/snapshot.gyp | 17 | ||||
-rw-r--r-- | ui/snapshot/snapshot_android.cc | 58 | ||||
-rw-r--r-- | ui/snapshot/snapshot_async.cc | 103 | ||||
-rw-r--r-- | ui/snapshot/snapshot_async.h | 42 | ||||
-rw-r--r-- | ui/snapshot/snapshot_aura.cc | 100 |
5 files changed, 200 insertions, 120 deletions
diff --git a/ui/snapshot/snapshot.gyp b/ui/snapshot/snapshot.gyp index a6a997e..3aa1fca 100644 --- a/ui/snapshot/snapshot.gyp +++ b/ui/snapshot/snapshot.gyp @@ -11,8 +11,8 @@ 'target_name': 'snapshot', 'type': '<(component)', 'dependencies': [ - '../../skia/skia.gyp:skia', '../../base/base.gyp:base', + '../../skia/skia.gyp:skia', '../base/ui_base.gyp:ui_base', '../gfx/gfx.gyp:gfx', '../gfx/gfx.gyp:gfx_geometry', @@ -23,6 +23,8 @@ 'sources': [ 'snapshot.h', 'snapshot_android.cc', + 'snapshot_async.cc', + 'snapshot_async.h', 'snapshot_aura.cc', 'snapshot_export.h', 'snapshot_ios.mm', @@ -34,9 +36,20 @@ '..', ], 'conditions': [ - ['use_aura==1', { + ['use_aura==1 or OS=="android"', { 'dependencies': [ '../../cc/cc.gyp:cc', + '../../gpu/gpu.gyp:command_buffer_common', + ], + }], + ['use_aura!=1 and OS!="android"', { + 'sources!': [ + 'snapshot_async.cc', + 'snapshot_async.h', + ], + }], + ['use_aura==1', { + 'dependencies': [ '../aura/aura.gyp:aura', '../compositor/compositor.gyp:compositor', ], diff --git a/ui/snapshot/snapshot_android.cc b/ui/snapshot/snapshot_android.cc index 837c13c..49e276c 100644 --- a/ui/snapshot/snapshot_android.cc +++ b/ui/snapshot/snapshot_android.cc @@ -4,13 +4,13 @@ #include "ui/snapshot/snapshot.h" -#include "base/callback.h" +#include "base/bind.h" +#include "cc/output/copy_output_request.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/android/view_android.h" #include "ui/base/android/window_android.h" -#include "ui/gfx/display.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/screen.h" +#include "ui/base/android/window_android_compositor.h" +#include "ui/snapshot/snapshot_async.h" namespace ui { @@ -24,39 +24,53 @@ bool GrabViewSnapshot(gfx::NativeView view, bool GrabWindowSnapshot(gfx::NativeWindow window, std::vector<unsigned char>* png_representation, const gfx::Rect& snapshot_bounds) { - gfx::Display display = - gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); - gfx::Rect scaled_bounds = - gfx::ScaleToEnclosingRect(snapshot_bounds, - display.device_scale_factor()); - return window->GrabSnapshot( - scaled_bounds.x(), scaled_bounds.y(), scaled_bounds.width(), - scaled_bounds.height(), png_representation); + // Not supported in Android. Callers should fall back to the async version. + return false; +} + +static void MakeAsyncCopyRequest( + gfx::NativeWindow window, + const gfx::Rect& source_rect, + const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { + scoped_ptr<cc::CopyOutputRequest> request = + cc::CopyOutputRequest::CreateBitmapRequest(callback); + request->set_area(source_rect); + window->GetCompositor()->RequestCopyOfOutputOnRootLayer(request.Pass()); } void GrabWindowSnapshotAndScaleAsync( gfx::NativeWindow window, - const gfx::Rect& snapshot_bounds, + const gfx::Rect& source_rect, const gfx::Size& target_size, scoped_refptr<base::TaskRunner> background_task_runner, - GrabWindowSnapshotAsyncCallback callback) { - callback.Run(gfx::Image()); + const GrabWindowSnapshotAsyncCallback& callback) { + MakeAsyncCopyRequest(window, + source_rect, + base::Bind(&SnapshotAsync::ScaleCopyOutputResult, + callback, + target_size, + background_task_runner)); } -void GrabViewSnapshotAsync( - gfx::NativeView view, +void GrabWindowSnapshotAsync( + gfx::NativeWindow window, const gfx::Rect& source_rect, scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncPNGCallback& callback) { - callback.Run(scoped_refptr<base::RefCountedBytes>()); + MakeAsyncCopyRequest(window, + source_rect, + base::Bind(&SnapshotAsync::EncodeCopyOutputResult, + callback, + background_task_runner)); } -void GrabWindowSnapshotAsync( - gfx::NativeWindow window, +void GrabViewSnapshotAsync( + gfx::NativeView view, const gfx::Rect& source_rect, scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncPNGCallback& callback) { - callback.Run(scoped_refptr<base::RefCountedBytes>()); + GrabWindowSnapshotAsync( + view->GetWindowAndroid(), source_rect, background_task_runner, callback); } } // namespace ui diff --git a/ui/snapshot/snapshot_async.cc b/ui/snapshot/snapshot_async.cc new file mode 100644 index 0000000..5f18225 --- /dev/null +++ b/ui/snapshot/snapshot_async.cc @@ -0,0 +1,103 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/snapshot/snapshot_async.h" + +#include "base/location.h" +#include "base/memory/ref_counted.h" +#include "base/numerics/safe_conversions.h" +#include "base/task_runner_util.h" +#include "skia/ext/image_operations.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkPixelRef.h" +#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/skbitmap_operations.h" + +namespace ui { + +namespace { + +void OnFrameScalingFinished(const GrabWindowSnapshotAsyncCallback& callback, + const SkBitmap& scaled_bitmap) { + callback.Run(gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(scaled_bitmap))); +} + +SkBitmap ScaleBitmap(const SkBitmap& input_bitmap, + const gfx::Size& target_size) { + return skia::ImageOperations::Resize(input_bitmap, + skia::ImageOperations::RESIZE_GOOD, + target_size.width(), + target_size.height(), + static_cast<SkBitmap::Allocator*>(NULL)); +} + +scoped_refptr<base::RefCountedBytes> EncodeBitmap(const SkBitmap& bitmap) { + scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); + SkAutoLockPixels lock(bitmap); + unsigned char* pixels = reinterpret_cast<unsigned char*>(bitmap.getPixels()); +#if SK_A32_SHIFT == 24 && SK_R32_SHIFT == 16 && SK_G32_SHIFT == 8 + gfx::PNGCodec::ColorFormat kColorFormat = gfx::PNGCodec::FORMAT_BGRA; +#elif SK_A32_SHIFT == 24 && SK_B32_SHIFT == 16 && SK_G32_SHIFT == 8 + gfx::PNGCodec::ColorFormat kColorFormat = gfx::PNGCodec::FORMAT_RGBA; +#else +#error Unknown color format +#endif + if (!gfx::PNGCodec::Encode(pixels, + kColorFormat, + gfx::Size(bitmap.width(), bitmap.height()), + base::checked_cast<int>(bitmap.rowBytes()), + true, + std::vector<gfx::PNGCodec::Comment>(), + &png_data->data())) { + return scoped_refptr<base::RefCountedBytes>(); + } + return png_data; +} + +} // namespace + +void SnapshotAsync::ScaleCopyOutputResult( + const GrabWindowSnapshotAsyncCallback& callback, + const gfx::Size& target_size, + scoped_refptr<base::TaskRunner> background_task_runner, + scoped_ptr<cc::CopyOutputResult> result) { + if (result->IsEmpty()) { + callback.Run(gfx::Image()); + return; + } + + // TODO(sergeyu): Potentially images can be scaled on GPU before reading it + // from GPU. Image scaling is implemented in content::GlHelper, but it's can't + // be used here because it's not in content/public. Move the scaling code + // somewhere so that it can be reused here. + base::PostTaskAndReplyWithResult( + background_task_runner, + FROM_HERE, + base::Bind(ScaleBitmap, *result->TakeBitmap(), target_size), + base::Bind(&OnFrameScalingFinished, callback)); +} + +void SnapshotAsync::EncodeCopyOutputResult( + const GrabWindowSnapshotAsyncPNGCallback& callback, + scoped_refptr<base::TaskRunner> background_task_runner, + scoped_ptr<cc::CopyOutputResult> result) { + if (result->IsEmpty()) { + callback.Run(scoped_refptr<base::RefCountedBytes>()); + return; + } + + // TODO(sergeyu): Potentially images can be scaled on GPU before reading it + // from GPU. Image scaling is implemented in content::GlHelper, but it's can't + // be used here because it's not in content/public. Move the scaling code + // somewhere so that it can be reused here. + base::PostTaskAndReplyWithResult( + background_task_runner, + FROM_HERE, + base::Bind(EncodeBitmap, *result->TakeBitmap()), + callback); +} + +} // namespace ui diff --git a/ui/snapshot/snapshot_async.h b/ui/snapshot/snapshot_async.h new file mode 100644 index 0000000..41da62b --- /dev/null +++ b/ui/snapshot/snapshot_async.h @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_SNAPSHOT_SNAPSHOT_ASYNC_H_ +#define UI_SNAPSHOT_SNAPSHOT_ASYNC_H_ + +#include "cc/output/copy_output_result.h" +#include "ui/snapshot/snapshot.h" + +namespace base { +class TaskRunner; +} + +namespace gfx { +class Size; +} + +namespace ui { + +// Helper methods for async snapshots to convert a cc::CopyOutputResult into a +// ui::GrabWindowSnapshot callback. +class SnapshotAsync { + public: + static void ScaleCopyOutputResult( + const GrabWindowSnapshotAsyncCallback& callback, + const gfx::Size& target_size, + scoped_refptr<base::TaskRunner> background_task_runner, + scoped_ptr<cc::CopyOutputResult> result); + + static void EncodeCopyOutputResult( + const GrabWindowSnapshotAsyncPNGCallback& callback, + scoped_refptr<base::TaskRunner> background_task_runner, + scoped_ptr<cc::CopyOutputResult> result); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(SnapshotAsync); +}; + +} // namespace ui + +#endif // UI_SNAPSHOT_SNAPSHOT_ASYNC_H_ diff --git a/ui/snapshot/snapshot_aura.cc b/ui/snapshot/snapshot_aura.cc index a360b87..fc7e6e7 100644 --- a/ui/snapshot/snapshot_aura.cc +++ b/ui/snapshot/snapshot_aura.cc @@ -6,109 +6,17 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/logging.h" -#include "base/numerics/safe_conversions.h" #include "base/task_runner_util.h" #include "cc/output/copy_output_request.h" -#include "cc/output/copy_output_result.h" -#include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkPixelRef.h" #include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" #include "ui/compositor/compositor.h" #include "ui/compositor/dip_util.h" #include "ui/compositor/layer.h" -#include "ui/gfx/codec/png_codec.h" -#include "ui/gfx/display.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/rect_conversions.h" -#include "ui/gfx/rect_f.h" -#include "ui/gfx/screen.h" -#include "ui/gfx/skbitmap_operations.h" -#include "ui/gfx/transform.h" +#include "ui/snapshot/snapshot_async.h" namespace ui { -namespace { - -void OnFrameScalingFinished( - const GrabWindowSnapshotAsyncCallback& callback, - const SkBitmap& scaled_bitmap) { - callback.Run(gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(scaled_bitmap))); -} - -SkBitmap ScaleBitmap(const SkBitmap& input_bitmap, - const gfx::Size& target_size) { - return skia::ImageOperations::Resize( - input_bitmap, - skia::ImageOperations::RESIZE_GOOD, - target_size.width(), - target_size.height(), - static_cast<SkBitmap::Allocator*>(NULL)); -} - -scoped_refptr<base::RefCountedBytes> EncodeBitmap(const SkBitmap& bitmap) { - scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); - unsigned char* pixels = - reinterpret_cast<unsigned char*>(bitmap.pixelRef()->pixels()); - if (!gfx::PNGCodec::Encode(pixels, - gfx::PNGCodec::FORMAT_BGRA, - gfx::Size(bitmap.width(), bitmap.height()), - base::checked_cast<int>(bitmap.rowBytes()), - true, - std::vector<gfx::PNGCodec::Comment>(), - &png_data->data())) { - return scoped_refptr<base::RefCountedBytes>(); - } - return png_data; -} - -void ScaleCopyOutputResult( - const GrabWindowSnapshotAsyncCallback& callback, - const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, - scoped_ptr<cc::CopyOutputResult> result) { - if (result->IsEmpty()) { - callback.Run(gfx::Image()); - return; - } - - // TODO(sergeyu): Potentially images can be scaled on GPU before reading it - // from GPU. Image scaling is implemented in content::GlHelper, but it's can't - // be used here because it's not in content/public. Move the scaling code - // somewhere so that it can be reused here. - base::PostTaskAndReplyWithResult( - background_task_runner, - FROM_HERE, - base::Bind(ScaleBitmap, *result->TakeBitmap(), target_size), - base::Bind(&OnFrameScalingFinished, callback)); -} - -void EncodeCopyOutputResult( - const GrabWindowSnapshotAsyncPNGCallback& callback, - scoped_refptr<base::TaskRunner> background_task_runner, - scoped_ptr<cc::CopyOutputResult> result) { - if (result->IsEmpty()) { - callback.Run(scoped_refptr<base::RefCountedBytes>()); - return; - } - - // TODO(sergeyu): Potentially images can be scaled on GPU before reading it - // from GPU. Image scaling is implemented in content::GlHelper, but it's can't - // be used here because it's not in content/public. Move the scaling code - // somewhere so that it can be reused here. - base::PostTaskAndReplyWithResult(background_task_runner, - FROM_HERE, - base::Bind(EncodeBitmap, - *result->TakeBitmap()), - callback); -} - -} // namespace - bool GrabViewSnapshot(gfx::NativeView view, std::vector<unsigned char>* png_representation, const gfx::Rect& snapshot_bounds) { @@ -122,7 +30,7 @@ bool GrabWindowSnapshot(gfx::NativeWindow window, return false; } -void MakeAsyncCopyRequest( +static void MakeAsyncCopyRequest( gfx::NativeWindow window, const gfx::Rect& source_rect, const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { @@ -140,7 +48,7 @@ void GrabWindowSnapshotAndScaleAsync( const GrabWindowSnapshotAsyncCallback& callback) { MakeAsyncCopyRequest(window, source_rect, - base::Bind(&ScaleCopyOutputResult, + base::Bind(&SnapshotAsync::ScaleCopyOutputResult, callback, target_size, background_task_runner)); @@ -153,7 +61,7 @@ void GrabWindowSnapshotAsync( const GrabWindowSnapshotAsyncPNGCallback& callback) { MakeAsyncCopyRequest(window, source_rect, - base::Bind(&EncodeCopyOutputResult, + base::Bind(&SnapshotAsync::EncodeCopyOutputResult, callback, background_task_runner)); } |