| 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..399c98c8f86cf79383971d23de3c006a3543254e 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"
|
| @@ -82,6 +86,17 @@ void SendImeEventAck(RenderWidgetHostImpl* host) {
|
| host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
|
| }
|
|
|
| +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);
|
| +}
|
| +
|
| } // anonymous namespace
|
|
|
| RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
|
| @@ -329,8 +344,7 @@ bool RenderWidgetHostViewAndroid::HasFocus() const {
|
| }
|
|
|
| bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
|
| - NOTIMPLEMENTED();
|
| - return false;
|
| + return HasValidFrame();
|
| }
|
|
|
| void RenderWidgetHostViewAndroid::Show() {
|
| @@ -540,8 +554,36 @@ 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 (!IsSurfaceAvailableForCopy()) {
|
| + callback.Run(false, SkBitmap());
|
| + return;
|
| + }
|
| +
|
| + const gfx::Display& display =
|
| + gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
|
| + float device_scale_factor = display.device_scale_factor();
|
| +
|
| + DCHECK_EQ(device_scale_factor,
|
| + ui::GetScaleFactorScale(GetScaleFactorForView(this)));
|
| +
|
| + 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::PrepareBitmapCopyOutputResult,
|
| + dst_size_in_pixel,
|
| + callback));
|
| + } else {
|
| + request = cc::CopyOutputRequest::CreateRequest(base::Bind(
|
| + &RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult,
|
| + dst_size_in_pixel,
|
| + callback));
|
| + }
|
| + request->set_area(src_subrect_in_pixel);
|
| + layer_->RequestCopyOfOutput(request.Pass());
|
| }
|
|
|
| void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
|
| @@ -1153,6 +1195,80 @@ void RenderWidgetHostViewAndroid::OnLostResources() {
|
| }
|
|
|
| // static
|
| +void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
|
| + const gfx::Size& dst_size_in_pixel,
|
| + const base::Callback<void(bool, const SkBitmap&)>& callback,
|
| + scoped_ptr<cc::CopyOutputResult> result) {
|
| + DCHECK(result->HasTexture());
|
| + base::ScopedClosureRunner scoped_callback_runner(
|
| + base::Bind(callback, false, SkBitmap()));
|
| +
|
| + if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
|
| + 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() || result->IsEmpty() || result->size().IsEmpty())
|
| + 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 =
|
|
|