| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/delegated_frame_host.h" | 5 #include "content/browser/renderer_host/delegated_frame_host.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 void DelegatedFrameHost::CopyFromCompositingSurface( | 129 void DelegatedFrameHost::CopyFromCompositingSurface( |
| 130 const gfx::Rect& src_subrect, | 130 const gfx::Rect& src_subrect, |
| 131 const gfx::Size& output_size, | 131 const gfx::Size& output_size, |
| 132 const ReadbackRequestCallback& callback, | 132 const ReadbackRequestCallback& callback, |
| 133 const SkColorType preferred_color_type) { | 133 const SkColorType preferred_color_type) { |
| 134 // Only ARGB888 and RGB565 supported as of now. | 134 // Only ARGB888 and RGB565 supported as of now. |
| 135 bool format_support = ((preferred_color_type == kAlpha_8_SkColorType) || | 135 bool format_support = ((preferred_color_type == kAlpha_8_SkColorType) || |
| 136 (preferred_color_type == kRGB_565_SkColorType) || | 136 (preferred_color_type == kRGB_565_SkColorType) || |
| 137 (preferred_color_type == kN32_SkColorType)); | 137 (preferred_color_type == kN32_SkColorType)); |
| 138 DCHECK(format_support); | 138 DCHECK(format_support); |
| 139 if (!CanCopyToBitmap()) { | 139 if (!CanCopyFromCompositingSurface()) { |
| 140 callback.Run(SkBitmap(), content::READBACK_SURFACE_UNAVAILABLE); | 140 callback.Run(SkBitmap(), content::READBACK_SURFACE_UNAVAILABLE); |
| 141 return; | 141 return; |
| 142 } | 142 } |
| 143 | 143 |
| 144 std::unique_ptr<cc::CopyOutputRequest> request = | 144 std::unique_ptr<cc::CopyOutputRequest> request = |
| 145 cc::CopyOutputRequest::CreateRequest( | 145 cc::CopyOutputRequest::CreateRequest( |
| 146 base::Bind(&CopyFromCompositingSurfaceHasResult, output_size, | 146 base::Bind(&CopyFromCompositingSurfaceHasResult, output_size, |
| 147 preferred_color_type, callback)); | 147 preferred_color_type, callback)); |
| 148 if (!src_subrect.IsEmpty()) | 148 if (!src_subrect.IsEmpty()) |
| 149 request->set_area(src_subrect); | 149 request->set_area(src_subrect); |
| 150 RequestCopyOfOutput(std::move(request)); | 150 RequestCopyOfOutput(std::move(request)); |
| 151 } | 151 } |
| 152 | 152 |
| 153 void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame( | 153 void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame( |
| 154 const gfx::Rect& src_subrect, | 154 const gfx::Rect& src_subrect, |
| 155 const scoped_refptr<media::VideoFrame>& target, | 155 scoped_refptr<media::VideoFrame> target, |
| 156 const base::Callback<void(const gfx::Rect&, bool)>& callback) { | 156 const base::Callback<void(const gfx::Rect&, bool)>& callback) { |
| 157 if (!CanCopyToVideoFrame()) { | 157 if (!CanCopyFromCompositingSurface()) { |
| 158 callback.Run(gfx::Rect(), false); | 158 callback.Run(gfx::Rect(), false); |
| 159 return; | 159 return; |
| 160 } | 160 } |
| 161 | 161 |
| 162 std::unique_ptr<cc::CopyOutputRequest> request = | 162 std::unique_ptr<cc::CopyOutputRequest> request = |
| 163 cc::CopyOutputRequest::CreateRequest(base::Bind( | 163 cc::CopyOutputRequest::CreateRequest(base::Bind( |
| 164 &DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo, | 164 &DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo, |
| 165 AsWeakPtr(), // For caching the ReadbackYUVInterface on this class. | 165 AsWeakPtr(), // For caching the ReadbackYUVInterface on this class. |
| 166 nullptr, target, callback)); | 166 nullptr, std::move(target), callback)); |
| 167 request->set_area(src_subrect); | 167 if (!src_subrect.IsEmpty()) |
| 168 request->set_area(src_subrect); |
| 168 RequestCopyOfOutput(std::move(request)); | 169 RequestCopyOfOutput(std::move(request)); |
| 169 } | 170 } |
| 170 | 171 |
| 171 bool DelegatedFrameHost::CanCopyToBitmap() const { | 172 bool DelegatedFrameHost::CanCopyFromCompositingSurface() const { |
| 172 return compositor_ && | 173 return compositor_ && |
| 173 client_->DelegatedFrameHostGetLayer()->has_external_content(); | 174 client_->DelegatedFrameHostGetLayer()->has_external_content(); |
| 174 } | 175 } |
| 175 | |
| 176 bool DelegatedFrameHost::CanCopyToVideoFrame() const { | |
| 177 return compositor_ && | |
| 178 client_->DelegatedFrameHostGetLayer()->has_external_content(); | |
| 179 } | |
| 180 | 176 |
| 181 void DelegatedFrameHost::BeginFrameSubscription( | 177 void DelegatedFrameHost::BeginFrameSubscription( |
| 182 std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) { | 178 std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) { |
| 183 frame_subscriber_ = std::move(subscriber); | 179 frame_subscriber_ = std::move(subscriber); |
| 184 } | 180 } |
| 185 | 181 |
| 186 void DelegatedFrameHost::EndFrameSubscription() { | 182 void DelegatedFrameHost::EndFrameSubscription() { |
| 187 idle_frame_subscriber_textures_.clear(); | 183 idle_frame_subscriber_textures_.clear(); |
| 188 frame_subscriber_.reset(); | 184 frame_subscriber_.reset(); |
| 189 } | 185 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 if (current_frame_size_in_dip_.height() < | 286 if (current_frame_size_in_dip_.height() < |
| 291 client_->DelegatedFrameHostDesiredSizeInDIP().height()) { | 287 client_->DelegatedFrameHostDesiredSizeInDIP().height()) { |
| 292 bottom_gutter_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); | 288 bottom_gutter_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); |
| 293 bottom_gutter_->SetColor(GetGutterColor()); | 289 bottom_gutter_->SetColor(GetGutterColor()); |
| 294 int width = current_frame_size_in_dip_.width(); | 290 int width = current_frame_size_in_dip_.width(); |
| 295 int height = client_->DelegatedFrameHostDesiredSizeInDIP().height() - | 291 int height = client_->DelegatedFrameHostDesiredSizeInDIP().height() - |
| 296 current_frame_size_in_dip_.height(); | 292 current_frame_size_in_dip_.height(); |
| 297 bottom_gutter_->SetBounds( | 293 bottom_gutter_->SetBounds( |
| 298 gfx::Rect(0, current_frame_size_in_dip_.height(), width, height)); | 294 gfx::Rect(0, current_frame_size_in_dip_.height(), width, height)); |
| 299 client_->DelegatedFrameHostGetLayer()->Add(bottom_gutter_.get()); | 295 client_->DelegatedFrameHostGetLayer()->Add(bottom_gutter_.get()); |
| 300 | |
| 301 } else { | 296 } else { |
| 302 bottom_gutter_.reset(); | 297 bottom_gutter_.reset(); |
| 303 } | 298 } |
| 304 } | 299 } |
| 305 | 300 |
| 306 gfx::Size DelegatedFrameHost::GetRequestedRendererSize() const { | 301 gfx::Size DelegatedFrameHost::GetRequestedRendererSize() const { |
| 307 if (resize_lock_) | 302 if (resize_lock_) |
| 308 return resize_lock_->expected_size(); | 303 return resize_lock_->expected_size(); |
| 309 else | 304 else |
| 310 return client_->DelegatedFrameHostDesiredSizeInDIP(); | 305 return client_->DelegatedFrameHostDesiredSizeInDIP(); |
| 311 } | 306 } |
| 312 | 307 |
| 313 void DelegatedFrameHost::CheckResizeLock() { | 308 void DelegatedFrameHost::CheckResizeLock() { |
| 314 if (!resize_lock_ || | 309 if (!resize_lock_ || |
| 315 resize_lock_->expected_size() != current_frame_size_in_dip_) | 310 resize_lock_->expected_size() != current_frame_size_in_dip_) |
| 316 return; | 311 return; |
| 317 | 312 |
| 318 // Since we got the size we were looking for, unlock the compositor. But delay | 313 // Since we got the size we were looking for, unlock the compositor. But delay |
| 319 // the release of the lock until we've kicked a frame with the new texture, to | 314 // the release of the lock until we've kicked a frame with the new texture, to |
| 320 // avoid resizing the UI before we have a chance to draw a "good" frame. | 315 // avoid resizing the UI before we have a chance to draw a "good" frame. |
| 321 resize_lock_->UnlockCompositor(); | 316 resize_lock_->UnlockCompositor(); |
| 322 } | 317 } |
| 323 | 318 |
| 324 void DelegatedFrameHost::AttemptFrameSubscriberCapture( | 319 void DelegatedFrameHost::AttemptFrameSubscriberCapture( |
| 325 const gfx::Rect& damage_rect) { | 320 const gfx::Rect& damage_rect) { |
| 326 if (!frame_subscriber() || !CanCopyToVideoFrame()) | 321 if (!frame_subscriber() || !CanCopyFromCompositingSurface()) |
| 327 return; | 322 return; |
| 328 | 323 |
| 329 const base::TimeTicks now = tick_clock_->NowTicks(); | 324 const base::TimeTicks now = tick_clock_->NowTicks(); |
| 330 base::TimeTicks present_time; | 325 base::TimeTicks present_time; |
| 331 if (vsync_interval_ <= base::TimeDelta()) { | 326 if (vsync_interval_ <= base::TimeDelta()) { |
| 332 present_time = now; | 327 present_time = now; |
| 333 } else { | 328 } else { |
| 334 const int64_t intervals_elapsed = (now - vsync_timebase_) / vsync_interval_; | 329 const int64_t intervals_elapsed = (now - vsync_timebase_) / vsync_interval_; |
| 335 present_time = vsync_timebase_ + (intervals_elapsed + 1) * vsync_interval_; | 330 present_time = vsync_timebase_ + (intervals_elapsed + 1) * vsync_interval_; |
| 336 } | 331 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 362 // DelegatedFrameHost (e.g., a call to CopyFromCompositingSurface() for | 357 // DelegatedFrameHost (e.g., a call to CopyFromCompositingSurface() for |
| 363 // screenshots) since those copy requests do not specify |frame_subscriber()| | 358 // screenshots) since those copy requests do not specify |frame_subscriber()| |
| 364 // as a source. | 359 // as a source. |
| 365 request->set_source(frame_subscriber()->GetSourceIdForCopyRequest()); | 360 request->set_source(frame_subscriber()->GetSourceIdForCopyRequest()); |
| 366 if (subscriber_texture.get()) { | 361 if (subscriber_texture.get()) { |
| 367 request->SetTextureMailbox(cc::TextureMailbox( | 362 request->SetTextureMailbox(cc::TextureMailbox( |
| 368 subscriber_texture->mailbox(), subscriber_texture->sync_token(), | 363 subscriber_texture->mailbox(), subscriber_texture->sync_token(), |
| 369 subscriber_texture->target())); | 364 subscriber_texture->target())); |
| 370 } | 365 } |
| 371 | 366 |
| 372 if (local_surface_id_.is_valid()) { | 367 // To avoid unnecessary browser composites, try to go directly to the Surface |
| 373 // To avoid unnecessary composites, go directly to the Surface rather than | 368 // rather than through the Layer (which goes through the browser compositor). |
| 374 // through RequestCopyOfOutput (which goes through the browser | 369 if (local_surface_id_.is_valid() && |
| 375 // compositor). | 370 request_copy_of_output_callback_for_testing_.is_null()) { |
| 376 if (!request_copy_of_output_callback_for_testing_.is_null()) | 371 support_->RequestCopyOfSurface(std::move(request)); |
| 377 request_copy_of_output_callback_for_testing_.Run(std::move(request)); | |
| 378 else | |
| 379 support_->RequestCopyOfSurface(std::move(request)); | |
| 380 } else { | 372 } else { |
| 381 request->set_area(gfx::Rect(current_frame_size_in_dip_)); | |
| 382 RequestCopyOfOutput(std::move(request)); | 373 RequestCopyOfOutput(std::move(request)); |
| 383 } | 374 } |
| 384 } | 375 } |
| 385 | 376 |
| 386 void DelegatedFrameHost::SwapDelegatedFrame(uint32_t compositor_frame_sink_id, | 377 void DelegatedFrameHost::SwapDelegatedFrame(uint32_t compositor_frame_sink_id, |
| 387 cc::CompositorFrame frame) { | 378 cc::CompositorFrame frame) { |
| 388 #if defined(OS_CHROMEOS) | 379 #if defined(OS_CHROMEOS) |
| 389 DCHECK(!resize_lock_ || !client_->IsAutoResizeEnabled()); | 380 DCHECK(!resize_lock_ || !client_->IsAutoResizeEnabled()); |
| 390 #endif | 381 #endif |
| 391 float frame_device_scale_factor = frame.metadata.device_scale_factor; | 382 float frame_device_scale_factor = frame.metadata.device_scale_factor; |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 // with too much entropy (which can drastically increase CPU utilization). | 666 // with too much entropy (which can drastically increase CPU utilization). |
| 676 // When up-scaling, always use "best" because the quality improvement is | 667 // When up-scaling, always use "best" because the quality improvement is |
| 677 // huge with insignificant performance penalty. Note that this strategy | 668 // huge with insignificant performance penalty. Note that this strategy |
| 678 // differs from single-frame snapshot capture. | 669 // differs from single-frame snapshot capture. |
| 679 display_compositor::GLHelper::ScalerQuality quality = | 670 display_compositor::GLHelper::ScalerQuality quality = |
| 680 ((result_rect.size().width() < region_in_frame.size().width()) && | 671 ((result_rect.size().width() < region_in_frame.size().width()) && |
| 681 (result_rect.size().height() < region_in_frame.size().height())) | 672 (result_rect.size().height() < region_in_frame.size().height())) |
| 682 ? display_compositor::GLHelper::SCALER_QUALITY_BEST | 673 ? display_compositor::GLHelper::SCALER_QUALITY_BEST |
| 683 : display_compositor::GLHelper::SCALER_QUALITY_FAST; | 674 : display_compositor::GLHelper::SCALER_QUALITY_FAST; |
| 684 | 675 |
| 676 DVLOG(1) << "Re-creating YUV readback pipeline for source rect " |
| 677 << result_rect.ToString() << " and destination size " |
| 678 << region_in_frame.size().ToString(); |
| 679 |
| 685 dfh->yuv_readback_pipeline_.reset(gl_helper->CreateReadbackPipelineYUV( | 680 dfh->yuv_readback_pipeline_.reset(gl_helper->CreateReadbackPipelineYUV( |
| 686 quality, result_rect.size(), result_rect, region_in_frame.size(), true, | 681 quality, result_rect.size(), result_rect, region_in_frame.size(), true, |
| 687 true)); | 682 true)); |
| 688 yuv_readback_pipeline = dfh->yuv_readback_pipeline_.get(); | 683 yuv_readback_pipeline = dfh->yuv_readback_pipeline_.get(); |
| 689 } | 684 } |
| 690 | 685 |
| 691 ignore_result(scoped_callback_runner.Release()); | 686 ignore_result(scoped_callback_runner.Release()); |
| 692 ignore_result(scoped_return_subscriber_texture.Release()); | 687 ignore_result(scoped_return_subscriber_texture.Release()); |
| 693 | 688 |
| 694 base::Callback<void(bool result)> finished_callback = base::Bind( | 689 base::Callback<void(bool result)> finished_callback = base::Bind( |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 compositor_ = nullptr; | 810 compositor_ = nullptr; |
| 816 } | 811 } |
| 817 | 812 |
| 818 void DelegatedFrameHost::LockResources() { | 813 void DelegatedFrameHost::LockResources() { |
| 819 DCHECK(local_surface_id_.is_valid()); | 814 DCHECK(local_surface_id_.is_valid()); |
| 820 delegated_frame_evictor_->LockFrame(); | 815 delegated_frame_evictor_->LockFrame(); |
| 821 } | 816 } |
| 822 | 817 |
| 823 void DelegatedFrameHost::RequestCopyOfOutput( | 818 void DelegatedFrameHost::RequestCopyOfOutput( |
| 824 std::unique_ptr<cc::CopyOutputRequest> request) { | 819 std::unique_ptr<cc::CopyOutputRequest> request) { |
| 825 if (!request_copy_of_output_callback_for_testing_.is_null()) { | 820 // If a specific area has not been requested, set one to ensure correct |
| 826 request_copy_of_output_callback_for_testing_.Run(std::move(request)); | 821 // clipping occurs. |
| 827 } else { | 822 if (!request->has_area()) |
| 823 request->set_area(gfx::Rect(current_frame_size_in_dip_)); |
| 824 |
| 825 if (request_copy_of_output_callback_for_testing_.is_null()) { |
| 828 client_->DelegatedFrameHostGetLayer()->RequestCopyOfOutput( | 826 client_->DelegatedFrameHostGetLayer()->RequestCopyOfOutput( |
| 829 std::move(request)); | 827 std::move(request)); |
| 828 } else { |
| 829 request_copy_of_output_callback_for_testing_.Run(std::move(request)); |
| 830 } | 830 } |
| 831 } | 831 } |
| 832 | 832 |
| 833 void DelegatedFrameHost::UnlockResources() { | 833 void DelegatedFrameHost::UnlockResources() { |
| 834 DCHECK(local_surface_id_.is_valid()); | 834 DCHECK(local_surface_id_.is_valid()); |
| 835 delegated_frame_evictor_->UnlockFrame(); | 835 delegated_frame_evictor_->UnlockFrame(); |
| 836 } | 836 } |
| 837 | 837 |
| 838 void DelegatedFrameHost::OnNeedsBeginFrames(bool needs_begin_frames) { | 838 void DelegatedFrameHost::OnNeedsBeginFrames(bool needs_begin_frames) { |
| 839 needs_begin_frame_ = needs_begin_frames; | 839 needs_begin_frame_ = needs_begin_frames; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 858 | 858 |
| 859 void DelegatedFrameHost::ResetCompositorFrameSinkSupport() { | 859 void DelegatedFrameHost::ResetCompositorFrameSinkSupport() { |
| 860 if (!support_) | 860 if (!support_) |
| 861 return; | 861 return; |
| 862 if (compositor_) | 862 if (compositor_) |
| 863 compositor_->RemoveFrameSink(frame_sink_id_); | 863 compositor_->RemoveFrameSink(frame_sink_id_); |
| 864 support_.reset(); | 864 support_.reset(); |
| 865 } | 865 } |
| 866 | 866 |
| 867 } // namespace content | 867 } // namespace content |
| OLD | NEW |