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