1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_widget_host_view_android.h"
7 #include <android/bitmap.h>
9 #include "base/android/sys_utils.h"
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/worker_pool.h"
19 #include "cc/base/latency_info_swap_promise.h"
20 #include "cc/layers/delegated_frame_provider.h"
21 #include "cc/layers/delegated_renderer_layer.h"
22 #include "cc/layers/layer.h"
23 #include "cc/output/compositor_frame.h"
24 #include "cc/output/compositor_frame_ack.h"
25 #include "cc/output/copy_output_request.h"
26 #include "cc/output/copy_output_result.h"
27 #include "cc/resources/single_release_callback.h"
28 #include "cc/trees/layer_tree_host.h"
29 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
30 #include "content/browser/android/content_view_core_impl.h"
31 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
32 #include "content/browser/android/overscroll_glow.h"
33 #include "content/browser/devtools/render_view_devtools_agent_host.h"
34 #include "content/browser/gpu/compositor_util.h"
35 #include "content/browser/gpu/gpu_data_manager_impl.h"
36 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
37 #include "content/browser/gpu/gpu_surface_tracker.h"
38 #include "content/browser/media/media_web_contents_observer.h"
39 #include "content/browser/renderer_host/compositor_impl_android.h"
40 #include "content/browser/renderer_host/dip_util.h"
41 #include "content/browser/renderer_host/image_transport_factory_android.h"
42 #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
43 #include "content/browser/renderer_host/input/web_input_event_builders_android.h"
44 #include "content/browser/renderer_host/input/web_input_event_util.h"
45 #include "content/browser/renderer_host/render_process_host_impl.h"
46 #include "content/browser/renderer_host/render_view_host_impl.h"
47 #include "content/browser/renderer_host/render_widget_host_impl.h"
48 #include "content/common/gpu/client/gl_helper.h"
49 #include "content/common/gpu/gpu_messages.h"
50 #include "content/common/input/did_overscroll_params.h"
51 #include "content/common/input_messages.h"
52 #include "content/common/view_messages.h"
53 #include "content/public/browser/browser_thread.h"
54 #include "content/public/browser/devtools_agent_host.h"
55 #include "content/public/browser/render_view_host.h"
56 #include "content/public/common/content_switches.h"
57 #include "gpu/command_buffer/client/gles2_interface.h"
58 #include "gpu/config/gpu_driver_bug_workaround_type.h"
59 #include "skia/ext/image_operations.h"
60 #include "third_party/khronos/GLES2/gl2.h"
61 #include "third_party/khronos/GLES2/gl2ext.h"
62 #include "third_party/skia/include/core/SkCanvas.h"
63 #include "ui/base/android/window_android.h"
64 #include "ui/base/android/window_android_compositor.h"
65 #include "ui/events/gesture_detection/gesture_config_helper.h"
66 #include "ui/events/gesture_detection/motion_event.h"
67 #include "ui/gfx/android/device_display_info.h"
68 #include "ui/gfx/android/java_bitmap.h"
69 #include "ui/gfx/display.h"
70 #include "ui/gfx/screen.h"
71 #include "ui/gfx/size_conversions.h"
77 const int kUndefinedOutputSurfaceId = -1;
79 // Used to accomodate finite precision when comparing scaled viewport and
80 // content widths. While this value may seem large, width=device-width on an N7
81 // V1 saw errors of ~0.065 between computed window and content widths.
82 const float kMobileViewportWidthEpsilon = 0.15f;
84 static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
86 // Sends an acknowledgement to the renderer of a processed IME event.
87 void SendImeEventAck(RenderWidgetHostImpl* host) {
88 host->Send(new ViewMsg_ImeEventAck(host->GetRoutingID()));
91 void CopyFromCompositingSurfaceFinished(
92 const base::Callback<void(bool, const SkBitmap&)>& callback,
93 scoped_ptr<cc::SingleReleaseCallback> release_callback,
94 scoped_ptr<SkBitmap> bitmap,
95 const base::TimeTicks& start_time,
96 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
98 bitmap_pixels_lock.reset();
99 release_callback->Run(0, false);
100 UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
101 base::TimeTicks::Now() - start_time);
102 callback.Run(result, *bitmap);
105 ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) {
106 ui::LatencyInfo latency_info;
107 // The latency number should only be added if the timestamp is valid.
108 if (event.timeStampSeconds) {
109 const int64 time_micros = static_cast<int64>(
110 event.timeStampSeconds * base::Time::kMicrosecondsPerSecond);
111 latency_info.AddLatencyNumberWithTimestamp(
112 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
115 base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros),
121 OverscrollGlow::DisplayParameters CreateOverscrollDisplayParameters(
122 const cc::CompositorFrameMetadata& frame_metadata) {
123 const float scale_factor =
124 frame_metadata.page_scale_factor * frame_metadata.device_scale_factor;
126 // Compute the size and offsets for each edge, where each effect is sized to
127 // the viewport and offset by the distance of each viewport edge to the
128 // respective content edge.
129 OverscrollGlow::DisplayParameters params;
130 params.size = gfx::ScaleSize(frame_metadata.viewport_size, scale_factor);
131 params.edge_offsets[EdgeEffect::EDGE_TOP] =
132 -frame_metadata.root_scroll_offset.y() * scale_factor;
133 params.edge_offsets[EdgeEffect::EDGE_LEFT] =
134 -frame_metadata.root_scroll_offset.x() * scale_factor;
135 params.edge_offsets[EdgeEffect::EDGE_BOTTOM] =
136 (frame_metadata.root_layer_size.height() -
137 frame_metadata.root_scroll_offset.y() -
138 frame_metadata.viewport_size.height()) * scale_factor;
139 params.edge_offsets[EdgeEffect::EDGE_RIGHT] =
140 (frame_metadata.root_layer_size.width() -
141 frame_metadata.root_scroll_offset.x() -
142 frame_metadata.viewport_size.width()) * scale_factor;
143 params.device_scale_factor = frame_metadata.device_scale_factor;
148 ui::GestureProvider::Config CreateGestureProviderConfig() {
149 ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
150 config.disable_click_delay =
151 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableClickDelay);
155 bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) {
156 return frame_metadata.min_page_scale_factor ==
157 frame_metadata.max_page_scale_factor;
160 bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) {
161 float window_width_dip =
162 frame_metadata.page_scale_factor * frame_metadata.viewport_size.width();
163 float content_width_css = frame_metadata.root_layer_size.width();
164 return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
167 } // anonymous namespace
169 RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
171 scoped_ptr<cc::CompositorFrame> output_frame)
172 : output_surface_id(output_id), frame(output_frame.Pass()) {}
174 RenderWidgetHostViewAndroid::LastFrameInfo::~LastFrameInfo() {}
176 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
177 RenderWidgetHostImpl* widget_host,
178 ContentViewCoreImpl* content_view_core)
179 : host_(widget_host),
180 needs_begin_frame_(false),
181 is_showing_(!widget_host->is_hidden()),
182 content_view_core_(NULL),
183 ime_adapter_android_(this),
184 cached_background_color_(SK_ColorWHITE),
185 last_output_surface_id_(kUndefinedOutputSurfaceId),
186 weak_ptr_factory_(this),
187 overscroll_effect_enabled_(!CommandLine::ForCurrentProcess()->HasSwitch(
188 switches::kDisableOverscrollEdgeEffect)),
189 overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)),
190 gesture_provider_(CreateGestureProviderConfig(), this),
191 gesture_text_selector_(this),
192 flush_input_requested_(false),
193 accelerated_surface_route_id_(0),
194 using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
195 widget_host->GetProcess()->GetID(),
196 widget_host->GetRoutingID()) != NULL),
197 frame_evictor_(new DelegatedFrameEvictor(this)),
198 locks_on_frame_count_(0),
199 observing_root_window_(false) {
200 host_->SetView(this);
201 SetContentViewCore(content_view_core);
202 ImageTransportFactoryAndroid::AddObserver(this);
205 RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
206 ImageTransportFactoryAndroid::RemoveObserver(this);
207 SetContentViewCore(NULL);
208 DCHECK(ack_callbacks_.empty());
209 if (resource_collection_.get())
210 resource_collection_->SetClient(NULL);
214 bool RenderWidgetHostViewAndroid::OnMessageReceived(
215 const IPC::Message& message) {
217 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAndroid, message)
218 IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
219 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
220 OnDidChangeBodyBackgroundColor)
221 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
222 OnSetNeedsBeginFrame)
223 IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
224 OnSmartClipDataExtracted)
225 IPC_MESSAGE_UNHANDLED(handled = false)
226 IPC_END_MESSAGE_MAP()
230 void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) {
234 void RenderWidgetHostViewAndroid::InitAsPopup(
235 RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
239 void RenderWidgetHostViewAndroid::InitAsFullscreen(
240 RenderWidgetHostView* reference_host_view) {
245 RenderWidgetHostViewAndroid::GetRenderWidgetHost() const {
249 void RenderWidgetHostViewAndroid::WasShown() {
250 if (!host_ || !host_->is_hidden())
255 if (content_view_core_ && !using_synchronous_compositor_) {
256 content_view_core_->GetWindowAndroid()->AddObserver(this);
257 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
258 observing_root_window_ = true;
262 void RenderWidgetHostViewAndroid::WasHidden() {
265 if (!host_ || host_->is_hidden())
268 // Inform the renderer that we are being hidden so it can reduce its resource
272 if (content_view_core_ && !using_synchronous_compositor_) {
273 content_view_core_->GetWindowAndroid()->RemoveObserver(this);
274 observing_root_window_ = false;
278 void RenderWidgetHostViewAndroid::WasResized() {
282 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
283 // Ignore the given size as only the Java code has the power to
284 // resize the view on Android.
285 default_size_ = size;
288 void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
289 SetSize(rect.size());
292 void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
294 SkBitmap::Config bitmap_config,
295 gfx::Rect src_subrect,
296 const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
297 if (!IsSurfaceAvailableForCopy()) {
298 result_callback.Run(false, SkBitmap());
302 gfx::Size bounds = layer_->bounds();
303 if (src_subrect.IsEmpty())
304 src_subrect = gfx::Rect(bounds);
305 DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
306 DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
307 const gfx::Display& display =
308 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
309 float device_scale_factor = display.device_scale_factor();
310 DCHECK_GT(device_scale_factor, 0);
312 gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
313 CopyFromCompositingSurface(
314 src_subrect, dst_size, result_callback, bitmap_config);
317 bool RenderWidgetHostViewAndroid::HasValidFrame() const {
318 if (!content_view_core_)
323 if (texture_size_in_layer_.IsEmpty())
326 if (!frame_evictor_->HasFrame())
332 gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
333 return content_view_core_->GetViewAndroid();
336 gfx::NativeViewId RenderWidgetHostViewAndroid::GetNativeViewId() const {
337 return reinterpret_cast<gfx::NativeViewId>(
338 const_cast<RenderWidgetHostViewAndroid*>(this));
341 gfx::NativeViewAccessible
342 RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
347 void RenderWidgetHostViewAndroid::MovePluginWindows(
348 const std::vector<WebPluginGeometry>& moves) {
349 // We don't have plugin windows on Android. Do nothing. Note: this is called
350 // from RenderWidgetHost::OnUpdateRect which is itself invoked while
351 // processing the corresponding message from Renderer.
354 void RenderWidgetHostViewAndroid::Focus() {
356 host_->SetInputMethodActive(true);
357 if (overscroll_effect_enabled_)
358 overscroll_effect_->Enable();
361 void RenderWidgetHostViewAndroid::Blur() {
362 host_->ExecuteEditCommand("Unselect", "");
363 host_->SetInputMethodActive(false);
365 overscroll_effect_->Disable();
368 bool RenderWidgetHostViewAndroid::HasFocus() const {
369 if (!content_view_core_)
370 return false; // ContentViewCore not created yet.
372 return content_view_core_->HasFocus();
375 bool RenderWidgetHostViewAndroid::IsSurfaceAvailableForCopy() const {
376 return HasValidFrame();
379 void RenderWidgetHostViewAndroid::Show() {
385 layer_->SetHideLayerAndSubtree(false);
387 frame_evictor_->SetVisible(true);
391 void RenderWidgetHostViewAndroid::Hide() {
396 if (layer_ && locks_on_frame_count_ == 0)
397 layer_->SetHideLayerAndSubtree(true);
399 frame_evictor_->SetVisible(false);
403 bool RenderWidgetHostViewAndroid::IsShowing() {
404 // ContentViewCoreImpl represents the native side of the Java
405 // ContentViewCore. It being NULL means that it is not attached
406 // to the View system yet, so we treat this RWHVA as hidden.
407 return is_showing_ && content_view_core_;
410 void RenderWidgetHostViewAndroid::LockCompositingSurface() {
411 DCHECK(HasValidFrame());
413 DCHECK(frame_evictor_->HasFrame());
414 frame_evictor_->LockFrame();
415 locks_on_frame_count_++;
418 void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
419 if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
422 DCHECK(HasValidFrame());
423 frame_evictor_->UnlockFrame();
424 locks_on_frame_count_--;
426 if (locks_on_frame_count_ == 0) {
427 if (last_frame_info_) {
428 InternalSwapCompositorFrame(last_frame_info_->output_surface_id,
429 last_frame_info_->frame.Pass());
430 last_frame_info_.reset();
433 if (!is_showing_ && layer_)
434 layer_->SetHideLayerAndSubtree(true);
438 void RenderWidgetHostViewAndroid::SetTextSurroundingSelectionCallback(
439 const TextSurroundingSelectionCallback& callback) {
440 // Only one outstanding request is allowed at any given time.
441 DCHECK(!callback.is_null());
442 text_surrounding_selection_callback_ = callback;
445 void RenderWidgetHostViewAndroid::OnTextSurroundingSelectionResponse(
446 const base::string16& content,
449 if (text_surrounding_selection_callback_.is_null())
451 text_surrounding_selection_callback_.Run(content, start_offset, end_offset);
452 text_surrounding_selection_callback_.Reset();
455 void RenderWidgetHostViewAndroid::ReleaseLocksOnSurface() {
456 if (!frame_evictor_->HasFrame()) {
457 DCHECK_EQ(locks_on_frame_count_, 0u);
460 while (locks_on_frame_count_ > 0) {
461 UnlockCompositingSurface();
466 gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
467 if (!content_view_core_)
468 return gfx::Rect(default_size_);
470 return gfx::Rect(content_view_core_->GetViewSize());
473 gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
474 if (!content_view_core_)
477 return content_view_core_->GetPhysicalBackingSize();
480 float RenderWidgetHostViewAndroid::GetOverdrawBottomHeight() const {
481 if (!content_view_core_)
484 return content_view_core_->GetOverdrawBottomHeightDip();
487 void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
488 // There are no cursors on Android.
491 void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
492 // Do nothing. The UI notification is handled through ContentViewClient which
493 // is TabContentsDelegate.
496 long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
497 return reinterpret_cast<intptr_t>(&ime_adapter_android_);
500 void RenderWidgetHostViewAndroid::TextInputStateChanged(
501 const ViewHostMsg_TextInputState_Params& params) {
502 // If the change is not originated from IME (e.g. Javascript, autofill),
503 // send back the renderer an acknowledgement, regardless of how we exit from
505 base::ScopedClosureRunner ack_caller;
506 if (params.is_non_ime_change)
507 ack_caller.Reset(base::Bind(&SendImeEventAck, host_));
512 content_view_core_->UpdateImeAdapter(
513 GetNativeImeAdapter(),
514 static_cast<int>(params.type),
515 params.value, params.selection_start, params.selection_end,
516 params.composition_start, params.composition_end,
517 params.show_ime_if_needed, params.is_non_ime_change);
520 void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
522 if (cached_background_color_ == color)
525 cached_background_color_ = color;
526 if (content_view_core_)
527 content_view_core_->OnBackgroundColorChanged(color);
530 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
531 if (enabled == needs_begin_frame_)
534 TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
536 if (content_view_core_ && enabled)
537 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
539 needs_begin_frame_ = enabled;
542 void RenderWidgetHostViewAndroid::OnStartContentIntent(
543 const GURL& content_url) {
544 if (content_view_core_)
545 content_view_core_->StartContentIntent(content_url);
548 void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
549 const base::string16& text,
550 const base::string16& html,
551 const gfx::Rect rect) {
552 if (content_view_core_)
553 content_view_core_->OnSmartClipDataExtracted(text, html, rect);
556 bool RenderWidgetHostViewAndroid::OnTouchEvent(
557 const ui::MotionEvent& event) {
561 if (!gesture_provider_.OnTouchEvent(event))
564 if (gesture_text_selector_.OnTouchEvent(event)) {
565 gesture_provider_.OnTouchEventAck(false);
569 // Short-circuit touch forwarding if no touch handlers exist.
570 if (!host_->ShouldForwardTouchEvent()) {
571 const bool event_consumed = false;
572 gesture_provider_.OnTouchEventAck(event_consumed);
576 SendTouchEvent(CreateWebTouchEventFromMotionEvent(event));
580 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
581 const ui::MotionEvent* current_down_event =
582 gesture_provider_.GetCurrentDownEvent();
583 if (!current_down_event)
586 scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
587 DCHECK(cancel_event);
588 OnTouchEvent(*cancel_event);
591 void RenderWidgetHostViewAndroid::SetDoubleTapSupportEnabled(bool enabled) {
592 gesture_provider_.SetDoubleTapSupportForPlatformEnabled(enabled);
595 void RenderWidgetHostViewAndroid::SetMultiTouchZoomSupportEnabled(
597 gesture_provider_.SetMultiTouchZoomSupportEnabled(enabled);
600 void RenderWidgetHostViewAndroid::ImeCancelComposition() {
601 ime_adapter_android_.CancelComposition();
604 void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
605 ime_adapter_android_.FocusedNodeChanged(is_editable_node);
608 void RenderWidgetHostViewAndroid::RenderProcessGone(
609 base::TerminationStatus status, int error_code) {
613 void RenderWidgetHostViewAndroid::Destroy() {
615 SetContentViewCore(NULL);
617 // The RenderWidgetHost's destruction led here, so don't call it.
623 void RenderWidgetHostViewAndroid::SetTooltipText(
624 const base::string16& tooltip_text) {
625 // Tooltips don't makes sense on Android.
628 void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
630 const gfx::Range& range) {
631 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
633 if (text.empty() || range.is_empty() || !content_view_core_)
635 size_t pos = range.GetMin() - offset;
636 size_t n = range.length();
638 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
639 if (pos >= text.length()) {
640 NOTREACHED() << "The text can not cover range.";
644 std::string utf8_selection = base::UTF16ToUTF8(text.substr(pos, n));
646 content_view_core_->OnSelectionChanged(utf8_selection);
649 void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
650 const ViewHostMsg_SelectionBounds_Params& params) {
651 if (content_view_core_) {
652 content_view_core_->OnSelectionBoundsChanged(params);
656 void RenderWidgetHostViewAndroid::ScrollOffsetChanged() {
659 void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) {
660 RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
661 host_->SetBackgroundOpaque(opaque);
664 void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
665 const gfx::Rect& src_subrect,
666 const gfx::Size& dst_size,
667 const base::Callback<void(bool, const SkBitmap&)>& callback,
668 const SkBitmap::Config bitmap_config) {
669 if (!IsReadbackConfigSupported(bitmap_config)) {
670 callback.Run(false, SkBitmap());
673 base::TimeTicks start_time = base::TimeTicks::Now();
674 if (!using_synchronous_compositor_ && !IsSurfaceAvailableForCopy()) {
675 callback.Run(false, SkBitmap());
678 const gfx::Display& display =
679 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
680 float device_scale_factor = display.device_scale_factor();
681 gfx::Size dst_size_in_pixel =
682 ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
683 gfx::Rect src_subrect_in_pixel =
684 ConvertRectToPixel(device_scale_factor, src_subrect);
686 if (using_synchronous_compositor_) {
687 SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
689 UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
690 base::TimeTicks::Now() - start_time);
694 scoped_ptr<cc::CopyOutputRequest> request;
695 scoped_refptr<cc::Layer> readback_layer;
696 DCHECK(content_view_core_);
697 DCHECK(content_view_core_->GetWindowAndroid());
698 ui::WindowAndroidCompositor* compositor =
699 content_view_core_->GetWindowAndroid()->GetCompositor();
701 DCHECK(frame_provider_);
702 scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
703 cc::DelegatedRendererLayer::Create(frame_provider_);
704 delegated_layer->SetBounds(content_size_in_layer_);
705 delegated_layer->SetHideLayerAndSubtree(true);
706 delegated_layer->SetIsDrawable(true);
707 delegated_layer->SetContentsOpaque(true);
708 compositor->AttachLayerForReadback(delegated_layer);
710 readback_layer = delegated_layer;
711 request = cc::CopyOutputRequest::CreateRequest(
712 base::Bind(&RenderWidgetHostViewAndroid::
713 PrepareTextureCopyOutputResultForDelegatedReadback,
719 request->set_area(src_subrect_in_pixel);
720 readback_layer->RequestCopyOfOutput(request.Pass());
723 void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
724 const gfx::Rect& src_subrect,
725 const scoped_refptr<media::VideoFrame>& target,
726 const base::Callback<void(bool)>& callback) {
731 bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
735 void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
736 const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap) {
737 if (!content_view_core_)
740 content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
743 scoped_ptr<SyntheticGestureTarget>
744 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
745 return scoped_ptr<SyntheticGestureTarget>(new SyntheticGestureTargetAndroid(
746 host_, content_view_core_->CreateTouchEventSynthesizer()));
749 void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
750 uint32 output_surface_id) {
752 cc::CompositorFrameAck ack;
753 if (resource_collection_.get())
754 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
755 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(),
757 host_->GetProcess()->GetID(),
761 void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
762 uint32 output_surface_id) {
763 DCHECK(resource_collection_);
765 cc::CompositorFrameAck ack;
766 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
767 DCHECK(!ack.resources.empty());
769 RenderWidgetHostImpl::SendReclaimCompositorResources(
770 host_->GetRoutingID(),
772 host_->GetProcess()->GetID(),
776 void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
777 if (ack_callbacks_.size())
779 SendReturnedDelegatedResources(last_output_surface_id_);
782 void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
784 frame_provider_ = NULL;
788 void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
789 uint32 output_surface_id,
790 scoped_ptr<cc::DelegatedFrameData> frame_data) {
791 bool has_content = !texture_size_in_layer_.IsEmpty();
793 if (output_surface_id != last_output_surface_id_) {
794 // Drop the cc::DelegatedFrameResourceCollection so that we will not return
795 // any resources from the old output surface with the new output surface id.
796 if (resource_collection_.get()) {
797 resource_collection_->SetClient(NULL);
798 if (resource_collection_->LoseAllResources())
799 SendReturnedDelegatedResources(last_output_surface_id_);
800 resource_collection_ = NULL;
802 DestroyDelegatedContent();
804 last_output_surface_id_ = output_surface_id;
807 // DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
808 // renderer frame, assuming that the browser compositor will scale
809 // it back up to device scale. But on Android we put our browser layers in
810 // physical pixels and set our browser CC device_scale_factor to 1, so this
811 // suppresses the transform. This line may need to be removed when fixing
812 // http://crbug.com/384134 or http://crbug.com/310763
813 frame_data->device_scale_factor = 1.0f;
816 DestroyDelegatedContent();
818 if (!resource_collection_.get()) {
819 resource_collection_ = new cc::DelegatedFrameResourceCollection;
820 resource_collection_->SetClient(this);
822 if (!frame_provider_ ||
823 texture_size_in_layer_ != frame_provider_->frame_size()) {
825 frame_provider_ = new cc::DelegatedFrameProvider(
826 resource_collection_.get(), frame_data.Pass());
827 layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
830 frame_provider_->SetFrameData(frame_data.Pass());
835 layer_->SetIsDrawable(true);
836 layer_->SetContentsOpaque(true);
837 layer_->SetBounds(content_size_in_layer_);
838 layer_->SetNeedsDisplay();
841 base::Closure ack_callback =
842 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
843 weak_ptr_factory_.GetWeakPtr(),
846 ack_callbacks_.push(ack_callback);
847 if (host_->is_hidden())
851 void RenderWidgetHostViewAndroid::ComputeContentsSize(
852 const cc::CompositorFrameMetadata& frame_metadata) {
853 // Calculate the content size. This should be 0 if the texture_size is 0.
854 gfx::Vector2dF offset;
855 if (texture_size_in_layer_.GetArea() > 0)
856 offset = frame_metadata.location_bar_content_translation;
857 offset.set_y(offset.y() + frame_metadata.overdraw_bottom_height);
858 offset.Scale(frame_metadata.device_scale_factor);
859 content_size_in_layer_ =
860 gfx::Size(texture_size_in_layer_.width() - offset.x(),
861 texture_size_in_layer_.height() - offset.y());
863 overscroll_effect_->UpdateDisplayParameters(
864 CreateOverscrollDisplayParameters(frame_metadata));
867 void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
868 uint32 output_surface_id,
869 scoped_ptr<cc::CompositorFrame> frame) {
870 if (!frame->delegated_frame_data) {
871 LOG(ERROR) << "Non-delegated renderer path no longer supported";
875 if (locks_on_frame_count_ > 0) {
876 DCHECK(HasValidFrame());
877 RetainFrame(output_surface_id, frame.Pass());
881 if (layer_ && layer_->layer_tree_host()) {
882 for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
883 scoped_ptr<cc::SwapPromise> swap_promise(
884 new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
885 layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass());
889 DCHECK(!frame->delegated_frame_data->render_pass_list.empty());
891 cc::RenderPass* root_pass =
892 frame->delegated_frame_data->render_pass_list.back();
893 texture_size_in_layer_ = root_pass->output_rect.size();
894 ComputeContentsSize(frame->metadata);
896 SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
897 frame_evictor_->SwappedFrame(!host_->is_hidden());
899 OnFrameMetadataUpdated(frame->metadata);
902 void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
903 uint32 output_surface_id,
904 scoped_ptr<cc::CompositorFrame> frame) {
905 InternalSwapCompositorFrame(output_surface_id, frame.Pass());
908 void RenderWidgetHostViewAndroid::RetainFrame(
909 uint32 output_surface_id,
910 scoped_ptr<cc::CompositorFrame> frame) {
911 DCHECK(locks_on_frame_count_);
913 // Store the incoming frame so that it can be swapped when all the locks have
914 // been released. If there is already a stored frame, then replace and skip
915 // the previous one but make sure we still eventually send the ACK. Holding
916 // the ACK also blocks the renderer when its max_frames_pending is reached.
917 if (last_frame_info_) {
918 base::Closure ack_callback =
919 base::Bind(&RenderWidgetHostViewAndroid::SendDelegatedFrameAck,
920 weak_ptr_factory_.GetWeakPtr(),
921 last_frame_info_->output_surface_id);
923 ack_callbacks_.push(ack_callback);
926 last_frame_info_.reset(new LastFrameInfo(output_surface_id, frame.Pass()));
929 void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
930 const cc::CompositorFrameMetadata& frame_metadata) {
931 // This is a subset of OnSwapCompositorFrame() used in the synchronous
933 OnFrameMetadataUpdated(frame_metadata);
934 ComputeContentsSize(frame_metadata);
936 // DevTools ScreenCast support for Android WebView.
937 if (DevToolsAgentHost::HasFor(RenderViewHost::From(GetRenderWidgetHost()))) {
938 scoped_refptr<DevToolsAgentHost> dtah =
939 DevToolsAgentHost::GetOrCreateFor(
940 RenderViewHost::From(GetRenderWidgetHost()));
941 // Unblock the compositor.
942 BrowserThread::PostTask(
943 BrowserThread::UI, FROM_HERE,
944 base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame,
945 static_cast<RenderViewDevToolsAgentHost*>(dtah.get()),
950 void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
952 layer_->SetContentsOpaque(!enabled);
955 void RenderWidgetHostViewAndroid::SynchronousCopyContents(
956 const gfx::Rect& src_subrect_in_pixel,
957 const gfx::Size& dst_size_in_pixel,
958 const base::Callback<void(bool, const SkBitmap&)>& callback,
959 const SkBitmap::Config config) {
960 SynchronousCompositor* compositor =
961 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
962 host_->GetRoutingID());
964 callback.Run(false, SkBitmap());
969 bitmap.setConfig(config,
970 dst_size_in_pixel.width(),
971 dst_size_in_pixel.height());
972 bitmap.allocPixels();
973 SkCanvas canvas(bitmap);
975 (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(),
976 (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height());
977 compositor->DemandDrawSw(&canvas);
978 callback.Run(true, bitmap);
981 void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
982 const cc::CompositorFrameMetadata& frame_metadata) {
984 // Disable double tap zoom for pages that have a width=device-width or
985 // narrower viewport (indicating that this is a mobile-optimized or responsive
986 // web design, so text will be legible without zooming). Also disable
987 // double tap and pinch for pages that prevent zooming in or out.
988 bool has_mobile_viewport = HasMobileViewport(frame_metadata);
989 bool has_fixed_page_scale = HasFixedPageScale(frame_metadata);
990 gesture_provider_.SetDoubleTapSupportForPageEnabled(
991 !has_fixed_page_scale && !has_mobile_viewport);
993 if (!content_view_core_)
995 // All offsets and sizes are in CSS pixels.
996 content_view_core_->UpdateFrameInfo(
997 frame_metadata.root_scroll_offset,
998 frame_metadata.page_scale_factor,
999 gfx::Vector2dF(frame_metadata.min_page_scale_factor,
1000 frame_metadata.max_page_scale_factor),
1001 frame_metadata.root_layer_size,
1002 frame_metadata.viewport_size,
1003 frame_metadata.location_bar_offset,
1004 frame_metadata.location_bar_content_translation,
1005 frame_metadata.overdraw_bottom_height);
1006 #if defined(VIDEO_HOLE)
1007 if (host_ && host_->IsRenderView()) {
1008 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
1009 RenderViewHost::From(host_));
1010 rvhi->media_web_contents_observer()->OnFrameInfoUpdated();
1012 #endif // defined(VIDEO_HOLE)
1015 void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id,
1017 accelerated_surface_route_id_ = route_id;
1020 void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
1021 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
1023 NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer";
1026 void RenderWidgetHostViewAndroid::AttachLayers() {
1027 if (!content_view_core_)
1032 content_view_core_->AttachLayer(layer_);
1033 if (overscroll_effect_enabled_)
1034 overscroll_effect_->Enable();
1035 layer_->SetHideLayerAndSubtree(!is_showing_);
1038 void RenderWidgetHostViewAndroid::RemoveLayers() {
1039 if (!content_view_core_)
1044 content_view_core_->RemoveLayer(layer_);
1045 overscroll_effect_->Disable();
1048 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
1049 content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
1052 bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
1053 return overscroll_effect_->Animate(frame_time);
1056 void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
1057 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
1062 void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() {
1066 void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
1070 void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
1072 DestroyDelegatedContent();
1073 frame_evictor_->DiscardedFrame();
1076 bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
1077 const gfx::Size& desired_size) {
1082 void RenderWidgetHostViewAndroid::GetScreenInfo(blink::WebScreenInfo* result) {
1083 // ScreenInfo isn't tied to the widget on Android. Always return the default.
1084 RenderWidgetHostViewBase::GetDefaultScreenInfo(result);
1087 // TODO(jrg): Find out the implications and answer correctly here,
1088 // as we are returning the WebView and not root window bounds.
1089 gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
1090 return GetViewBounds();
1093 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
1094 gfx::GLSurfaceHandle handle =
1095 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_TRANSPORT);
1096 if (CompositorImpl::IsInitialized()) {
1097 handle.parent_client_id =
1098 ImageTransportFactoryAndroid::GetInstance()->GetChannelID();
1103 void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
1104 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1105 const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
1106 gesture_provider_.OnTouchEventAck(event_consumed);
1109 void RenderWidgetHostViewAndroid::GestureEventAck(
1110 const blink::WebGestureEvent& event,
1111 InputEventAckState ack_result) {
1112 if (content_view_core_)
1113 content_view_core_->OnGestureEventAck(event, ack_result);
1116 InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
1117 const blink::WebInputEvent& input_event) {
1118 if (content_view_core_ &&
1119 content_view_core_->FilterInputEvent(input_event))
1120 return INPUT_EVENT_ACK_STATE_CONSUMED;
1123 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1125 if (input_event.type == blink::WebInputEvent::GestureTapDown ||
1126 input_event.type == blink::WebInputEvent::TouchStart) {
1127 GpuDataManagerImpl* gpu_data = GpuDataManagerImpl::GetInstance();
1128 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
1129 if (shim && gpu_data && accelerated_surface_route_id_ &&
1130 gpu_data->IsDriverBugWorkaroundActive(gpu::WAKE_UP_GPU_BEFORE_DRAWING))
1132 new AcceleratedSurfaceMsg_WakeUpGpu(accelerated_surface_route_id_));
1135 SynchronousCompositorImpl* compositor =
1136 SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
1137 host_->GetRoutingID());
1139 return compositor->HandleInputEvent(input_event);
1140 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1143 void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
1144 if (flush_input_requested_ || !content_view_core_)
1146 TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
1147 flush_input_requested_ = true;
1148 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1151 void RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManagerIfNeeded() {
1152 if (!host_ || host_->accessibility_mode() != AccessibilityModeComplete)
1155 if (!GetBrowserAccessibilityManager()) {
1156 base::android::ScopedJavaLocalRef<jobject> obj;
1157 if (content_view_core_)
1158 obj = content_view_core_->GetJavaObject();
1159 SetBrowserAccessibilityManager(
1160 new BrowserAccessibilityManagerAndroid(
1162 BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
1167 bool RenderWidgetHostViewAndroid::LockMouse() {
1172 void RenderWidgetHostViewAndroid::UnlockMouse() {
1176 // Methods called from the host to the render
1178 void RenderWidgetHostViewAndroid::SendKeyEvent(
1179 const NativeWebKeyboardEvent& event) {
1181 host_->ForwardKeyboardEvent(event);
1184 void RenderWidgetHostViewAndroid::SendTouchEvent(
1185 const blink::WebTouchEvent& event) {
1187 host_->ForwardTouchEventWithLatencyInfo(event, CreateLatencyInfo(event));
1189 // Send a proactive BeginFrame on the next vsync to reduce latency.
1190 // This is good enough as long as the first touch event has Begin semantics
1191 // and the actual scroll happens on the next vsync.
1192 // TODO: Is this actually still needed?
1193 if (content_view_core_) {
1194 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1198 void RenderWidgetHostViewAndroid::SendMouseEvent(
1199 const blink::WebMouseEvent& event) {
1201 host_->ForwardMouseEvent(event);
1204 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
1205 const blink::WebMouseWheelEvent& event) {
1207 host_->ForwardWheelEvent(event);
1210 void RenderWidgetHostViewAndroid::SendGestureEvent(
1211 const blink::WebGestureEvent& event) {
1212 // Sending a gesture that may trigger overscroll should resume the effect.
1213 if (overscroll_effect_enabled_)
1214 overscroll_effect_->Enable();
1217 host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
1220 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
1222 host_->MoveCaret(point);
1225 SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
1226 return cached_background_color_;
1229 void RenderWidgetHostViewAndroid::DidOverscroll(
1230 const DidOverscrollParams& params) {
1231 if (!content_view_core_ || !layer_ || !is_showing_)
1234 const float device_scale_factor = content_view_core_->GetDpiScale();
1235 if (overscroll_effect_->OnOverscrolled(
1236 content_view_core_->GetLayer(),
1237 base::TimeTicks::Now(),
1238 gfx::ScaleVector2d(params.accumulated_overscroll,
1239 device_scale_factor),
1240 gfx::ScaleVector2d(params.latest_overscroll_delta,
1241 device_scale_factor),
1242 gfx::ScaleVector2d(params.current_fling_velocity,
1243 device_scale_factor))) {
1248 void RenderWidgetHostViewAndroid::DidStopFlinging() {
1249 if (content_view_core_)
1250 content_view_core_->DidStopFlinging();
1253 void RenderWidgetHostViewAndroid::SetContentViewCore(
1254 ContentViewCoreImpl* content_view_core) {
1256 if (observing_root_window_ && content_view_core_) {
1257 content_view_core_->GetWindowAndroid()->RemoveObserver(this);
1258 observing_root_window_ = false;
1261 bool resize = false;
1262 if (content_view_core != content_view_core_) {
1263 ReleaseLocksOnSurface();
1267 content_view_core_ = content_view_core;
1269 if (GetBrowserAccessibilityManager()) {
1270 base::android::ScopedJavaLocalRef<jobject> obj;
1271 if (content_view_core_)
1272 obj = content_view_core_->GetJavaObject();
1273 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerAndroid()->
1274 SetContentViewCore(obj);
1278 if (content_view_core_ && !using_synchronous_compositor_) {
1279 content_view_core_->GetWindowAndroid()->AddObserver(this);
1280 observing_root_window_ = true;
1281 if (needs_begin_frame_)
1282 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1285 if (resize && content_view_core_)
1289 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
1290 while (!ack_callbacks_.empty()) {
1291 ack_callbacks_.front().Run();
1292 ack_callbacks_.pop();
1296 void RenderWidgetHostViewAndroid::OnGestureEvent(
1297 const ui::GestureEventData& gesture) {
1298 if (gesture_text_selector_.OnGestureEvent(gesture))
1301 SendGestureEvent(CreateWebGestureEventFromGestureEventData(gesture));
1304 void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
1308 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
1309 DCHECK(content_view_core_);
1310 DCHECK(!using_synchronous_compositor_);
1314 void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
1315 base::TimeDelta vsync_period) {
1316 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync");
1320 if (flush_input_requested_) {
1321 flush_input_requested_ = false;
1322 host_->FlushInput();
1325 TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
1326 base::TimeTicks display_time = frame_time + vsync_period;
1328 // TODO(brianderson): Use adaptive draw-time estimation.
1329 base::TimeDelta estimated_browser_composite_time =
1330 base::TimeDelta::FromMicroseconds(
1331 (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
1333 base::TimeTicks deadline = display_time - estimated_browser_composite_time;
1335 host_->Send(new ViewMsg_BeginFrame(
1336 host_->GetRoutingID(),
1337 cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
1339 if (needs_begin_frame_)
1340 content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
1343 void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
1344 if (Animate(begin_frame_time))
1348 void RenderWidgetHostViewAndroid::OnLostResources() {
1349 ReleaseLocksOnSurface();
1351 DestroyDelegatedContent();
1352 DCHECK(ack_callbacks_.empty());
1357 RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
1358 const gfx::Size& dst_size_in_pixel,
1359 const SkBitmap::Config config,
1360 const base::TimeTicks& start_time,
1361 scoped_refptr<cc::Layer> readback_layer,
1362 const base::Callback<void(bool, const SkBitmap&)>& callback,
1363 scoped_ptr<cc::CopyOutputResult> result) {
1364 readback_layer->RemoveFromParent();
1365 PrepareTextureCopyOutputResult(
1366 dst_size_in_pixel, config, start_time, callback, result.Pass());
1370 void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
1371 const gfx::Size& dst_size_in_pixel,
1372 const SkBitmap::Config bitmap_config,
1373 const base::TimeTicks& start_time,
1374 const base::Callback<void(bool, const SkBitmap&)>& callback,
1375 scoped_ptr<cc::CopyOutputResult> result) {
1376 base::ScopedClosureRunner scoped_callback_runner(
1377 base::Bind(callback, false, SkBitmap()));
1379 if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
1382 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
1383 bitmap->setConfig(bitmap_config,
1384 dst_size_in_pixel.width(),
1385 dst_size_in_pixel.height(),
1386 0, kOpaque_SkAlphaType);
1387 if (!bitmap->allocPixels())
1390 ImageTransportFactoryAndroid* factory =
1391 ImageTransportFactoryAndroid::GetInstance();
1392 GLHelper* gl_helper = factory->GetGLHelper();
1397 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
1398 new SkAutoLockPixels(*bitmap));
1399 uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
1401 cc::TextureMailbox texture_mailbox;
1402 scoped_ptr<cc::SingleReleaseCallback> release_callback;
1403 result->TakeTexture(&texture_mailbox, &release_callback);
1404 DCHECK(texture_mailbox.IsTexture());
1405 if (!texture_mailbox.IsTexture())
1408 ignore_result(scoped_callback_runner.Release());
1410 gl_helper->CropScaleReadbackAndCleanMailbox(
1411 texture_mailbox.mailbox(),
1412 texture_mailbox.sync_point(),
1414 gfx::Rect(result->size()),
1418 base::Bind(&CopyFromCompositingSurfaceFinished,
1420 base::Passed(&release_callback),
1421 base::Passed(&bitmap),
1423 base::Passed(&bitmap_pixels_lock)),
1424 GLHelper::SCALER_QUALITY_GOOD);
1427 bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
1428 SkBitmap::Config bitmap_config) {
1429 ImageTransportFactoryAndroid* factory =
1430 ImageTransportFactoryAndroid::GetInstance();
1431 GLHelper* gl_helper = factory->GetGLHelper();
1434 return gl_helper->IsReadbackConfigSupported(bitmap_config);
1437 SkBitmap::Config RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
1438 // Define the criteria here. If say the 16 texture readback is
1439 // supported we should go with that (this degrades quality)
1440 // or stick back to the default format.
1441 if (base::android::SysUtils::IsLowEndDevice()) {
1442 if (IsReadbackConfigSupported(SkBitmap::kRGB_565_Config))
1443 return SkBitmap::kRGB_565_Config;
1445 return SkBitmap::kARGB_8888_Config;
1448 void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
1449 if (content_view_core_)
1450 content_view_core_->ShowSelectionHandlesAutomatically();
1453 void RenderWidgetHostViewAndroid::SelectRange(
1454 float x1, float y1, float x2, float y2) {
1455 if (content_view_core_)
1456 static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())->
1457 SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2));
1460 void RenderWidgetHostViewAndroid::Unselect() {
1461 if (content_view_core_)
1462 content_view_core_->GetWebContents()->Unselect();
1465 void RenderWidgetHostViewAndroid::LongPress(
1466 base::TimeTicks time, float x, float y) {
1467 blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
1468 blink::WebInputEvent::GestureLongPress,
1469 (time - base::TimeTicks()).InSecondsF(), x, y);
1470 SendGestureEvent(long_press);
1474 void RenderWidgetHostViewBase::GetDefaultScreenInfo(
1475 blink::WebScreenInfo* results) {
1476 const gfx::Display& display =
1477 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
1478 results->rect = display.bounds();
1479 // TODO(husky): Remove any system controls from availableRect.
1480 results->availableRect = display.work_area();
1481 results->deviceScaleFactor = display.device_scale_factor();
1482 results->orientationAngle = display.RotationAsDegree();
1483 gfx::DeviceDisplayInfo info;
1484 results->depth = info.GetBitsPerPixel();
1485 results->depthPerComponent = info.GetBitsPerComponent();
1486 results->isMonochrome = (results->depthPerComponent == 0);
1489 } // namespace content