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 = |