Chromium Code Reviews| Index: content/browser/renderer_host/render_widget_host_view_android.cc |
| diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc |
| index 53a05f24fa4956bde4f2b93542a860a08a10e2d1..e740589afbc93b0b800fe526652caa2ac359e5f0 100644 |
| --- a/content/browser/renderer_host/render_widget_host_view_android.cc |
| +++ b/content/browser/renderer_host/render_widget_host_view_android.cc |
| @@ -18,6 +18,8 @@ |
| #include "cc/layers/texture_layer.h" |
| #include "cc/output/compositor_frame.h" |
| #include "cc/output/compositor_frame_ack.h" |
| +#include "cc/output/copy_output_request.h" |
| +#include "cc/output/copy_output_result.h" |
| #include "cc/trees/layer_tree_host.h" |
| #include "content/browser/accessibility/browser_accessibility_manager_android.h" |
| #include "content/browser/android/content_view_core_impl.h" |
| @@ -25,6 +27,7 @@ |
| #include "content/browser/android/overscroll_glow.h" |
| #include "content/browser/gpu/gpu_surface_tracker.h" |
| #include "content/browser/renderer_host/compositor_impl_android.h" |
| +#include "content/browser/renderer_host/dip_util.h" |
| #include "content/browser/renderer_host/image_transport_factory_android.h" |
| #include "content/browser/renderer_host/render_widget_host_impl.h" |
| #include "content/browser/renderer_host/surface_texture_transport_client_android.h" |
| @@ -34,6 +37,7 @@ |
| #include "content/common/input_messages.h" |
| #include "content/common/view_messages.h" |
| #include "content/public/common/content_switches.h" |
| +#include "skia/ext/image_operations.h" |
| #include "third_party/khronos/GLES2/gl2.h" |
| #include "third_party/khronos/GLES2/gl2ext.h" |
| #include "ui/gfx/android/device_display_info.h" |
| @@ -329,8 +333,7 @@ bool RenderWidgetHostViewAndroid::HasFocus() const { |
| } |
| bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const { |
| - NOTIMPLEMENTED(); |
| - return false; |
| + return HasValidFrame(); |
| } |
| void RenderWidgetHostViewAndroid::Show() { |
| @@ -540,8 +543,33 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface( |
| const gfx::Rect& src_subrect, |
| const gfx::Size& dst_size, |
| const base::Callback<void(bool, const SkBitmap&)>& callback) { |
| - NOTIMPLEMENTED(); |
| - callback.Run(false, SkBitmap()); |
| + if (!CanCopyToBitmap()) { |
|
Sami
2013/08/09 16:08:48
Seems like we could just call IsSurfaceAvailableFo
pfeldman
2013/08/09 16:19:59
Done.
|
| + callback.Run(false, SkBitmap()); |
| + return; |
| + } |
| + |
| + const gfx::Display& display = |
| + gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); |
| + float device_scale_factor = display.device_scale_factor(); |
| + |
| + const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size); |
| + gfx::Rect src_subrect_in_pixel = |
| + ConvertRectToPixel(device_scale_factor, src_subrect); |
| + |
| + scoped_ptr<cc::CopyOutputRequest> request; |
| + if (src_subrect_in_pixel.size() == dst_size_in_pixel) { |
| + request = cc::CopyOutputRequest::CreateBitmapRequest(base::Bind( |
| + &RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceHasResult, |
| + dst_size_in_pixel, |
| + callback)); |
| + } else { |
| + request = cc::CopyOutputRequest::CreateRequest(base::Bind( |
| + &RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceHasResult, |
| + dst_size_in_pixel, |
| + callback)); |
| + } |
| + request->set_area(src_subrect_in_pixel); |
| + layer_->RequestCopyOfOutput(request.Pass()); |
| } |
| void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame( |
| @@ -552,6 +580,10 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame( |
| callback.Run(false); |
| } |
| +bool RenderWidgetHostViewAndroid::CanCopyToBitmap() const { |
| + return true; |
|
Sami
2013/08/09 16:08:48
Do we need this method? Please add a TODO if somet
pfeldman
2013/08/09 16:19:59
Removed
|
| +} |
| + |
| bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const { |
| return false; |
| } |
| @@ -1153,6 +1185,110 @@ void RenderWidgetHostViewAndroid::OnLostResources() { |
| } |
| // static |
| +void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceHasResult( |
| + const gfx::Size& dst_size_in_pixel, |
| + const base::Callback<void(bool, const SkBitmap&)>& callback, |
| + scoped_ptr<cc::CopyOutputResult> result) { |
| + if (result->IsEmpty() || result->size().IsEmpty()) { |
| + callback.Run(false, SkBitmap()); |
| + return; |
| + } |
| + |
| + if (result->HasTexture()) { |
| + PrepareTextureCopyOutputResult(dst_size_in_pixel, callback, result.Pass()); |
| + return; |
| + } |
| + |
| + DCHECK(result->HasBitmap()); |
| + PrepareBitmapCopyOutputResult(dst_size_in_pixel, callback, result.Pass()); |
| +} |
| + |
| +static void CopyFromCompositingSurfaceFinished( |
| + const base::Callback<void(bool, const SkBitmap&)>& callback, |
| + const cc::TextureMailbox::ReleaseCallback& release_callback, |
| + scoped_ptr<SkBitmap> bitmap, |
| + scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock, |
| + bool result) { |
| + bitmap_pixels_lock.reset(); |
| + release_callback.Run(0, false); |
| + callback.Run(result, *bitmap); |
| +} |
| + |
| +// static |
| +void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult( |
| + const gfx::Size& dst_size_in_pixel, |
| + const base::Callback<void(bool, const SkBitmap&)>& callback, |
| + scoped_ptr<cc::CopyOutputResult> result) { |
| + base::ScopedClosureRunner scoped_callback_runner( |
| + base::Bind(callback, false, SkBitmap())); |
| + |
| + DCHECK(result->HasTexture()); |
| + if (!result->HasTexture()) |
| + return; |
| + |
| + scoped_ptr<SkBitmap> bitmap(new SkBitmap); |
| + bitmap->setConfig(SkBitmap::kARGB_8888_Config, |
| + dst_size_in_pixel.width(), dst_size_in_pixel.height()); |
| + if (!bitmap->allocPixels()) |
| + return; |
| + bitmap->setIsOpaque(true); |
| + |
| + ImageTransportFactoryAndroid* factory = |
| + ImageTransportFactoryAndroid::GetInstance(); |
| + GLHelper* gl_helper = factory->GetGLHelper(); |
| + if (!gl_helper) |
| + return; |
| + |
| + scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock( |
| + new SkAutoLockPixels(*bitmap)); |
| + uint8* pixels = static_cast<uint8*>(bitmap->getPixels()); |
| + |
| + scoped_ptr<cc::TextureMailbox> texture_mailbox = result->TakeTexture(); |
| + DCHECK(texture_mailbox->IsTexture()); |
| + if (!texture_mailbox->IsTexture()) |
| + return; |
| + |
| + scoped_callback_runner.Release(); |
| + |
| + gl_helper->CropScaleReadbackAndCleanMailbox( |
| + texture_mailbox->name(), |
| + texture_mailbox->sync_point(), |
| + result->size(), |
| + gfx::Rect(result->size()), |
| + dst_size_in_pixel, |
| + pixels, |
| + base::Bind(&CopyFromCompositingSurfaceFinished, |
| + callback, |
| + texture_mailbox->callback(), |
| + base::Passed(&bitmap), |
| + base::Passed(&bitmap_pixels_lock))); |
| +} |
| + |
| +// static |
| +void RenderWidgetHostViewAndroid::PrepareBitmapCopyOutputResult( |
| + const gfx::Size& dst_size_in_pixel, |
| + const base::Callback<void(bool, const SkBitmap&)>& callback, |
| + scoped_ptr<cc::CopyOutputResult> result) { |
| + DCHECK(result->HasBitmap()); |
| + |
| + base::ScopedClosureRunner scoped_callback_runner( |
| + base::Bind(callback, false, SkBitmap())); |
| + if (!result->HasBitmap()) |
| + return; |
| + |
| + scoped_ptr<SkBitmap> source = result->TakeBitmap(); |
| + DCHECK(source); |
| + if (!source) |
| + return; |
| + |
| + DCHECK_EQ(source->width(), dst_size_in_pixel.width()); |
| + DCHECK_EQ(source->height(), dst_size_in_pixel.height()); |
| + |
| + scoped_callback_runner.Release(); |
| + callback.Run(true, *source); |
| +} |
| + |
| +// static |
| void RenderWidgetHostViewPort::GetDefaultScreenInfo( |
| WebKit::WebScreenInfo* results) { |
| const gfx::Display& display = |