Index: content/browser/renderer_host/render_widget_host_view_aura.cc |
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc |
index 31019a4c96bdceaa1f204645c3745d43b25fe20a..289c1007a5761ec1b404d8ead9ecd15bc2a7d98b 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc |
@@ -13,6 +13,8 @@ |
#include "base/strings/string_number_conversions.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/resources/texture_mailbox.h" |
#include "content/browser/accessibility/browser_accessibility_manager.h" |
#include "content/browser/accessibility/browser_accessibility_state_impl.h" |
@@ -36,6 +38,7 @@ |
#include "content/public/browser/user_metrics.h" |
#include "content/public/common/content_switches.h" |
#include "media/base/video_util.h" |
+#include "skia/ext/image_operations.h" |
#include "third_party/WebKit/public/web/WebCompositionUnderline.h" |
#include "third_party/WebKit/public/web/WebInputEvent.h" |
#include "third_party/WebKit/public/web/WebScreenInfo.h" |
@@ -948,7 +951,7 @@ bool RenderWidgetHostViewAura::HasFocus() const { |
} |
bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const { |
- return current_surface_.get() || current_software_frame_.IsValid() || |
+ return window_->layer()->has_external_content() || |
!!host_->GetBackingStore(false); |
} |
@@ -1165,49 +1168,19 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurface( |
const gfx::Rect& src_subrect, |
const gfx::Size& dst_size, |
const base::Callback<void(bool, const SkBitmap&)>& callback) { |
- |
- base::ScopedClosureRunner scoped_callback_runner( |
- base::Bind(callback, false, SkBitmap())); |
- if (!current_surface_.get()) |
+ if (!window_->layer()->has_external_content()) { |
+ callback.Run(false, SkBitmap()); |
return; |
+ } |
const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size); |
- SkBitmap output; |
- output.setConfig(SkBitmap::kARGB_8888_Config, |
- dst_size_in_pixel.width(), dst_size_in_pixel.height()); |
- if (!output.allocPixels()) |
- return; |
- output.setIsOpaque(true); |
- |
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); |
- GLHelper* gl_helper = factory->GetGLHelper(); |
- if (!gl_helper) |
- return; |
- |
- unsigned char* addr = static_cast<unsigned char*>(output.getPixels()); |
- scoped_callback_runner.Release(); |
- // Wrap the callback with an internal handler so that we can inject our |
- // own completion handlers (where we can try to free the frontbuffer). |
- base::Callback<void(bool)> wrapper_callback = base::Bind( |
- &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished, |
- output, |
- callback); |
- |
- // Convert |src_subrect| from the views coordinate (upper-left origin) into |
- // the OpenGL coordinate (lower-left origin). |
- gfx::Rect src_subrect_in_gl = src_subrect; |
- src_subrect_in_gl.set_y(GetViewBounds().height() - src_subrect.bottom()); |
- |
- gfx::Rect src_subrect_in_pixel = |
- ConvertRectToPixel(current_surface_->device_scale_factor(), |
- src_subrect_in_gl); |
- gl_helper->CropScaleReadbackAndCleanTexture( |
- current_surface_->PrepareTexture(), |
- current_surface_->size(), |
- src_subrect_in_pixel, |
- dst_size_in_pixel, |
- addr, |
- wrapper_callback); |
+ scoped_ptr<cc::CopyOutputRequest> request = |
+ cc::CopyOutputRequest::CreateRequest(base::Bind( |
+ &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult, |
+ dst_size_in_pixel, |
+ callback)); |
+ request->set_area(src_subrect); |
+ window_->layer()->RequestCopyOfOutput(request.Pass()); |
} |
void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame( |
@@ -1765,11 +1738,107 @@ void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor( |
scoped_refptr<ui::Texture>) { |
} |
-void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished( |
- const SkBitmap& bitmap, |
+// static |
+void RenderWidgetHostViewAura::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, |
+ scoped_ptr<SkBitmap> bitmap, |
+ scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock, |
bool result) { |
- callback.Run(result, bitmap); |
+ bitmap_pixels_lock.reset(); |
+ callback.Run(result, *bitmap); |
+} |
+ |
+// static |
+void RenderWidgetHostViewAura::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); |
+ |
+ ImageTransportFactory* factory = ImageTransportFactory::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, |
+ base::Passed(&bitmap), |
+ base::Passed(&bitmap_pixels_lock))); |
+} |
+ |
+// static |
+void RenderWidgetHostViewAura::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( |
+ *source, |
+ skia::ImageOperations::RESIZE_BEST, |
+ dst_size_in_pixel.width(), |
+ dst_size_in_pixel.height()); |
+ callback.Run(true, bitmap); |
} |
void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) { |