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 | |
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
-rw-r--r-- | cc/output/copy_output_request.cc | 1 | ||||
-rw-r--r-- | cc/output/copy_output_request.h | 2 | ||||
-rw-r--r-- | cc/output/copy_output_result.cc | 1 | ||||
-rw-r--r-- | cc/output/copy_output_result.h | 2 | ||||
-rw-r--r-- | content/browser/android/content_view_render_view.cc | 9 | ||||
-rw-r--r-- | content/browser/android/content_view_render_view.h | 1 | ||||
-rw-r--r-- | content/browser/renderer_host/compositor_impl_android.cc | 10 | ||||
-rw-r--r-- | content/browser/renderer_host/compositor_impl_android.h | 2 | ||||
-rw-r--r-- | content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java | 16 | ||||
-rw-r--r-- | content/test/gpu/gpu_tests/pixel_expectations.py | 4 | ||||
-rw-r--r-- | content/test/gpu/page_sets/pixel_tests.py | 12 | ||||
-rw-r--r-- | ui/base/DEPS | 1 | ||||
-rw-r--r-- | ui/base/android/window_android_compositor.h | 3 | ||||
-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 |
18 files changed, 225 insertions, 159 deletions
diff --git a/cc/output/copy_output_request.cc b/cc/output/copy_output_request.cc index 0e84011..2d42fa9 100644 --- a/cc/output/copy_output_request.cc +++ b/cc/output/copy_output_request.cc @@ -9,7 +9,6 @@ #include "base/debug/trace_event.h" #include "base/logging.h" #include "cc/output/copy_output_result.h" -#include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "third_party/skia/include/core/SkBitmap.h" diff --git a/cc/output/copy_output_request.h b/cc/output/copy_output_request.h index dcb2fe2..60a5f11 100644 --- a/cc/output/copy_output_request.h +++ b/cc/output/copy_output_request.h @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" +#include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "ui/gfx/rect.h" @@ -15,7 +16,6 @@ class SkBitmap; namespace cc { class CopyOutputResult; -class SingleReleaseCallback; class CC_EXPORT CopyOutputRequest { public: diff --git a/cc/output/copy_output_result.cc b/cc/output/copy_output_result.cc index adbb8de..8dee046 100644 --- a/cc/output/copy_output_result.cc +++ b/cc/output/copy_output_result.cc @@ -5,7 +5,6 @@ #include "cc/output/copy_output_result.h" #include "base/logging.h" -#include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "third_party/skia/include/core/SkBitmap.h" diff --git a/cc/output/copy_output_result.h b/cc/output/copy_output_result.h index b4806581..8529e3f 100644 --- a/cc/output/copy_output_result.h +++ b/cc/output/copy_output_result.h @@ -7,13 +7,13 @@ #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" +#include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" #include "ui/gfx/size.h" class SkBitmap; namespace cc { -class SingleReleaseCallback; class TextureMailbox; class CC_EXPORT CopyOutputResult { diff --git a/content/browser/android/content_view_render_view.cc b/content/browser/android/content_view_render_view.cc index 4a39885..06590fa 100644 --- a/content/browser/android/content_view_render_view.cc +++ b/content/browser/android/content_view_render_view.cc @@ -117,15 +117,6 @@ void ContentViewRenderView::SurfaceChanged(JNIEnv* env, jobject obj, compositor_->SetWindowBounds(gfx::Size(width, height)); } -jboolean ContentViewRenderView::CompositeToBitmap(JNIEnv* env, jobject obj, - jobject java_bitmap) { - gfx::JavaBitmap bitmap(java_bitmap); - if (!compositor_ || bitmap.format() != ANDROID_BITMAP_FORMAT_RGBA_8888) - return false; - return compositor_->CompositeAndReadback(bitmap.pixels(), - gfx::Rect(bitmap.size())); -} - void ContentViewRenderView::SetOverlayVideoMode( JNIEnv* env, jobject obj, bool enabled) { compositor_->SetHasTransparentBackground(enabled); diff --git a/content/browser/android/content_view_render_view.h b/content/browser/android/content_view_render_view.h index cbdb1f1..2f1bcc1 100644 --- a/content/browser/android/content_view_render_view.h +++ b/content/browser/android/content_view_render_view.h @@ -40,7 +40,6 @@ class ContentViewRenderView : public CompositorClient { void SurfaceChanged(JNIEnv* env, jobject obj, jint format, jint width, jint height, jobject surface); jboolean Composite(JNIEnv* env, jobject obj); - jboolean CompositeToBitmap(JNIEnv* env, jobject obj, jobject java_bitmap); void SetOverlayVideoMode(JNIEnv* env, jobject obj, bool enabled); // CompositorClient implementation diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index c8a803c..2deb358 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -439,10 +439,7 @@ void CompositorImpl::SetHasTransparentBackground(bool flag) { } bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { - if (host_) - return host_->CompositeAndReadback(pixels, rect); - else - return false; + return false; } void CompositorImpl::SetNeedsComposite() { @@ -623,6 +620,11 @@ void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { root_layer_->AddChild(layer); } +void CompositorImpl::RequestCopyOfOutputOnRootLayer( + scoped_ptr<cc::CopyOutputRequest> request) { + root_layer_->RequestCopyOfOutput(request.Pass()); +} + void CompositorImpl::OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period) { vsync_period_ = vsync_period; diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h index 8fd65ad..91de0ae 100644 --- a/content/browser/renderer_host/compositor_impl_android.h +++ b/content/browser/renderer_host/compositor_impl_android.h @@ -100,6 +100,8 @@ class CONTENT_EXPORT CompositorImpl // WindowAndroidCompositor implementation. virtual void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) OVERRIDE; + virtual void RequestCopyOfOutputOnRootLayer( + scoped_ptr<cc::CopyOutputRequest> request) OVERRIDE; virtual void OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period) OVERRIDE; diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java index 709d574..d869ab0 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java @@ -5,8 +5,6 @@ package org.chromium.content.browser; import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Color; import android.graphics.PixelFormat; import android.view.Surface; @@ -150,18 +148,7 @@ public class ContentViewRenderView extends FrameLayout { * @return The created SurfaceView object. */ protected SurfaceView createSurfaceView(Context context) { - return new SurfaceView(context) { - @Override - public void onDraw(Canvas canvas) { - // We only need to draw to software canvases, which are used for taking screenshots. - if (canvas.isHardwareAccelerated()) return; - Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), - Bitmap.Config.ARGB_8888); - if (nativeCompositeToBitmap(mNativeContentViewRenderView, bitmap)) { - canvas.drawBitmap(bitmap, 0, 0, null); - } - } - }; + return new SurfaceView(context); } /** @@ -214,7 +201,6 @@ public class ContentViewRenderView extends FrameLayout { private native void nativeSurfaceDestroyed(long nativeContentViewRenderView); private native void nativeSurfaceChanged(long nativeContentViewRenderView, int format, int width, int height, Surface surface); - private native boolean nativeCompositeToBitmap(long nativeContentViewRenderView, Bitmap bitmap); private native void nativeSetOverlayVideoMode(long nativeContentViewRenderView, boolean enabled); } diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index 1d9594a..8f89792 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py @@ -24,4 +24,8 @@ class PixelExpectations(test_expectations.TestExpectations): # self.Fail('Pixel.Canvas2DRedBox', # ['mac', 'amd', ('nvidia', 0x1234)], bug=123) + self.Fail('Pixel.Canvas2DRedBox', bug=371592) + self.Fail('Pixel.CSS3DBlueBox', bug=371592) + self.Fail('Pixel.WebGLGreenTriangle', bug=371592) + pass diff --git a/content/test/gpu/page_sets/pixel_tests.py b/content/test/gpu/page_sets/pixel_tests.py index 897893a..254e047 100644 --- a/content/test/gpu/page_sets/pixel_tests.py +++ b/content/test/gpu/page_sets/pixel_tests.py @@ -34,20 +34,20 @@ class PixelTestsPageSet(page_set_module.PageSet): self.AddPage(PixelTestsPage( url='file://../../data/gpu/pixel_canvas2d.html', name='Pixel.Canvas2DRedBox', - test_rect=[0, 0, 400, 300], - revision=2, + test_rect=[0, 0, 300, 300], + revision=3, page_set=self)) self.AddPage(PixelTestsPage( url='file://../../data/gpu/pixel_css3d.html', name='Pixel.CSS3DBlueBox', - test_rect=[0, 0, 400, 300], - revision=5, + test_rect=[0, 0, 300, 300], + revision=6, page_set=self)) self.AddPage(PixelTestsPage( url='file://../../data/gpu/pixel_webgl.html', name='Pixel.WebGLGreenTriangle', - test_rect=[0, 0, 400, 300], - revision=6, + test_rect=[0, 0, 300, 300], + revision=7, page_set=self)) diff --git a/ui/base/DEPS b/ui/base/DEPS index 99ec151..dd9bbe8 100644 --- a/ui/base/DEPS +++ b/ui/base/DEPS @@ -1,4 +1,5 @@ include_rules = [ + "+cc", "+grit/app_locale_settings.h", "+grit/ui_resources.h", "+grit/ui_strings.h", diff --git a/ui/base/android/window_android_compositor.h b/ui/base/android/window_android_compositor.h index 1c2fefc..3f4a2ef 100644 --- a/ui/base/android/window_android_compositor.h +++ b/ui/base/android/window_android_compositor.h @@ -5,6 +5,7 @@ #ifndef UI_BASE_ANDROID_WINDOW_ANDROID_COMPOSITOR_H_ #define UI_BASE_ANDROID_WINDOW_ANDROID_COMPOSITOR_H_ +#include "cc/output/copy_output_request.h" #include "ui/base/ui_base_export.h" namespace cc { @@ -19,6 +20,8 @@ class UI_BASE_EXPORT WindowAndroidCompositor { virtual ~WindowAndroidCompositor() {} virtual void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) = 0; + virtual void RequestCopyOfOutputOnRootLayer( + scoped_ptr<cc::CopyOutputRequest> request) = 0; virtual void OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period) = 0; }; 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)); } |