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..7ab263759cf1294dfea919cab170536bf89a906f 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" |
| @@ -276,6 +280,36 @@ bool RenderWidgetHostViewAndroid::PopulateBitmapWithContents(jobject jbitmap) { |
| return true; |
| } |
| +bool RenderWidgetHostViewAndroid::PopulateBitmapWithContents( |
|
no sievers
2013/08/07 18:41:43
So this is unneeded then?
pfeldman
2013/08/09 13:59:02
Correct. Removed.
|
| + const gfx::Size& size, SkBitmap* bitmap) { |
| + if (!CompositorImpl::IsInitialized() || |
| + texture_id_in_layer_ == 0 || |
| + texture_size_in_layer_.IsEmpty()) |
| + return false; |
| + |
| + GLHelper* helper = ImageTransportFactoryAndroid::GetInstance()->GetGLHelper(); |
| + |
| + WebKit::WebGLId texture = helper->CopyAndScaleTexture( |
| + texture_id_in_layer_, |
| + texture_size_in_layer_, |
| + size, |
| + true, |
| + GLHelper::SCALER_QUALITY_FAST); |
| + if (texture == 0) |
| + return false; |
| + |
| + helper->ReadbackTextureSync( |
| + texture, |
| + gfx::Rect(size), |
| + static_cast<unsigned char*> (bitmap->getPixels())); |
| + |
| + WebKit::WebGraphicsContext3D* context = |
| + ImageTransportFactoryAndroid::GetInstance()->GetContext3D(); |
| + context->deleteTexture(texture); |
| + |
| + return true; |
| +} |
| + |
| bool RenderWidgetHostViewAndroid::HasValidFrame() const { |
| return texture_id_in_layer_ != 0 && |
| content_view_core_ && |
| @@ -540,8 +574,21 @@ 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()) { |
| + callback.Run(false, SkBitmap()); |
| + return; |
| + } |
| + |
| + const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size); |
| + scoped_ptr<cc::CopyOutputRequest> request = |
| + cc::CopyOutputRequest::CreateRequest(base::Bind( |
|
no sievers
2013/08/07 19:51:28
Should this create a bitmap request if we don't ha
Sami
2013/08/08 11:35:00
Yeah, no need to make a redundant copy in that cas
pfeldman
2013/08/09 13:59:02
Done.
|
| + &RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceHasResult, |
| + dst_size_in_pixel, |
| + callback)); |
| + gfx::Rect src_subrect_in_pixel = |
| + ConvertRectToPixel(current_device_scale_factor_, src_subrect); |
| + request->set_area(src_subrect_in_pixel); |
| + layer_->RequestCopyOfOutput(request.Pass()); |
| } |
| void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame( |
| @@ -552,6 +599,10 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame( |
| callback.Run(false); |
| } |
| +bool RenderWidgetHostViewAndroid::CanCopyToBitmap() const { |
| + return true; |
| +} |
| + |
| bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const { |
| return false; |
| } |
| @@ -1153,6 +1204,113 @@ 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; |
| + |
| + scoped_callback_runner.Release(); |
| + |
| + SkBitmap bitmap = skia::ImageOperations::Resize( |
|
no sievers
2013/08/07 19:51:28
Let's remove this and dcheck() that the dimensions
pfeldman
2013/08/09 13:59:02
Done.
|
| + *source, |
| + skia::ImageOperations::RESIZE_BEST, |
| + dst_size_in_pixel.width(), |
| + dst_size_in_pixel.height()); |
| + callback.Run(true, bitmap); |
| +} |
| + |
| +// static |
| void RenderWidgetHostViewPort::GetDefaultScreenInfo( |
| WebKit::WebScreenInfo* results) { |
| const gfx::Display& display = |