Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(912)

Unified Diff: content/browser/compositor/delegated_frame_host.cc

Issue 417943004: Use Surfaces to hold delegated renderer contents. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/compositor/delegated_frame_host.cc
diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc
index 91c8e035ceefcbef7fe1d401eaf64c2764a0cba0..b81374a43429a0ac1b0a57aae9f5d67555d1e803 100644
--- a/content/browser/compositor/delegated_frame_host.cc
+++ b/content/browser/compositor/delegated_frame_host.cc
@@ -11,6 +11,9 @@
#include "cc/output/copy_output_request.h"
#include "cc/resources/single_release_callback.h"
#include "cc/resources/texture_mailbox.h"
+#include "cc/surfaces/surface_factory.h"
+#include "content/browser/compositor/delegated_frame_layer_host.h"
+#include "content/browser/compositor/delegated_frame_surface_host.h"
#include "content/browser/compositor/resize_lock.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
@@ -43,808 +46,14 @@ void DelegatedFrameHostClient::RequestCopyOfOutput(
GetDelegatedFrameHost()->RequestCopyOfOutput(request.Pass());
}
-////////////////////////////////////////////////////////////////////////////////
-// DelegatedFrameHost
-
-DelegatedFrameHost::DelegatedFrameHost(DelegatedFrameHostClient* client)
- : client_(client),
- last_output_surface_id_(0),
- pending_delegated_ack_count_(0),
- skipped_frames_(false),
- can_lock_compositor_(YES_CAN_LOCK),
- delegated_frame_evictor_(new DelegatedFrameEvictor(this)) {
- ImageTransportFactory::GetInstance()->AddObserver(this);
-}
-
-void DelegatedFrameHost::WasShown() {
- delegated_frame_evictor_->SetVisible(true);
-
- if (!released_front_lock_.get()) {
- ui::Compositor* compositor = client_->GetCompositor();
- if (compositor)
- released_front_lock_ = compositor->GetCompositorLock();
- }
-}
-
-void DelegatedFrameHost::WasHidden() {
- delegated_frame_evictor_->SetVisible(false);
- released_front_lock_ = NULL;
-}
-
-void DelegatedFrameHost::MaybeCreateResizeLock() {
- if (!client_->ShouldCreateResizeLock())
- return;
- DCHECK(client_->GetCompositor());
-
- // Listen to changes in the compositor lock state.
- ui::Compositor* compositor = client_->GetCompositor();
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
-
- bool defer_compositor_lock =
- can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
- can_lock_compositor_ == NO_PENDING_COMMIT;
-
- if (can_lock_compositor_ == YES_CAN_LOCK)
- can_lock_compositor_ = YES_DID_LOCK;
-
- resize_lock_ = client_->CreateResizeLock(defer_compositor_lock);
-}
-
-bool DelegatedFrameHost::ShouldCreateResizeLock() {
- RenderWidgetHostImpl* host = client_->GetHost();
-
- if (resize_lock_)
- return false;
-
- if (host->should_auto_resize())
- return false;
-
- gfx::Size desired_size = client_->DesiredFrameSize();
- if (desired_size == current_frame_size_in_dip_ || desired_size.IsEmpty())
- return false;
-
- ui::Compositor* compositor = client_->GetCompositor();
- if (!compositor)
- return false;
-
- return true;
-}
-
-void DelegatedFrameHost::RequestCopyOfOutput(
- scoped_ptr<cc::CopyOutputRequest> request) {
- client_->GetLayer()->RequestCopyOfOutput(request.Pass());
-}
-
-void DelegatedFrameHost::CopyFromCompositingSurface(
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkColorType color_type) {
- // Only ARGB888 and RGB565 supported as of now.
- bool format_support = ((color_type == kRGB_565_SkColorType) ||
- (color_type == kN32_SkColorType));
- DCHECK(format_support);
- if (!CanCopyToBitmap()) {
- callback.Run(false, SkBitmap());
- return;
- }
-
- const gfx::Size& dst_size_in_pixel =
- client_->ConvertViewSizeToPixel(dst_size);
- scoped_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(base::Bind(
- &DelegatedFrameHost::CopyFromCompositingSurfaceHasResult,
- dst_size_in_pixel,
- color_type,
- callback));
- gfx::Rect src_subrect_in_pixel =
- ConvertRectToPixel(client_->CurrentDeviceScaleFactor(), src_subrect);
- request->set_area(src_subrect_in_pixel);
- client_->RequestCopyOfOutput(request.Pass());
-}
-
-void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame(
- const gfx::Rect& src_subrect,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) {
- if (!CanCopyToVideoFrame()) {
- callback.Run(false);
- return;
- }
-
- // Try get a texture to reuse.
- scoped_refptr<OwnedMailbox> subscriber_texture;
- if (frame_subscriber_) {
- if (!idle_frame_subscriber_textures_.empty()) {
- subscriber_texture = idle_frame_subscriber_textures_.back();
- idle_frame_subscriber_textures_.pop_back();
- } else if (GLHelper* helper =
- ImageTransportFactory::GetInstance()->GetGLHelper()) {
- subscriber_texture = new OwnedMailbox(helper);
- }
- }
-
- scoped_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(base::Bind(
- &DelegatedFrameHost::
- CopyFromCompositingSurfaceHasResultForVideo,
- AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
- subscriber_texture,
- target,
- callback));
- gfx::Rect src_subrect_in_pixel =
- ConvertRectToPixel(client_->CurrentDeviceScaleFactor(), src_subrect);
- request->set_area(src_subrect_in_pixel);
- if (subscriber_texture.get()) {
- request->SetTextureMailbox(
- cc::TextureMailbox(subscriber_texture->mailbox(),
- subscriber_texture->target(),
- subscriber_texture->sync_point()));
- }
- client_->RequestCopyOfOutput(request.Pass());
-}
-
-bool DelegatedFrameHost::CanCopyToBitmap() const {
- return client_->GetCompositor() &&
- client_->GetLayer()->has_external_content();
-}
-
-bool DelegatedFrameHost::CanCopyToVideoFrame() const {
- return client_->GetCompositor() &&
- client_->GetLayer()->has_external_content();
-}
-
-bool DelegatedFrameHost::CanSubscribeFrame() const {
- return true;
-}
-
-void DelegatedFrameHost::BeginFrameSubscription(
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
- frame_subscriber_ = subscriber.Pass();
-}
-
-void DelegatedFrameHost::EndFrameSubscription() {
- idle_frame_subscriber_textures_.clear();
- frame_subscriber_.reset();
-}
-
-bool DelegatedFrameHost::ShouldSkipFrame(gfx::Size size_in_dip) const {
- // Should skip a frame only when another frame from the renderer is guaranteed
- // to replace it. Otherwise may cause hangs when the renderer is waiting for
- // the completion of latency infos (such as when taking a Snapshot.)
- if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
- can_lock_compositor_ == NO_PENDING_COMMIT ||
- !resize_lock_.get())
- return false;
-
- return size_in_dip != resize_lock_->expected_size();
-}
-
-void DelegatedFrameHost::WasResized() {
- MaybeCreateResizeLock();
-}
-
-gfx::Size DelegatedFrameHost::GetRequestedRendererSize() const {
- if (resize_lock_)
- return resize_lock_->expected_size();
- else
- return client_->DesiredFrameSize();
-}
-
-void DelegatedFrameHost::CheckResizeLock() {
- if (!resize_lock_ ||
- resize_lock_->expected_size() != current_frame_size_in_dip_)
- return;
-
- // Since we got the size we were looking for, unlock the compositor. But delay
- // the release of the lock until we've kicked a frame with the new texture, to
- // avoid resizing the UI before we have a chance to draw a "good" frame.
- resize_lock_->UnlockCompositor();
- ui::Compositor* compositor = client_->GetCompositor();
- if (compositor) {
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
- }
-}
-
-void DelegatedFrameHost::DidReceiveFrameFromRenderer() {
- if (frame_subscriber() && CanCopyToVideoFrame()) {
- const base::TimeTicks present_time = base::TimeTicks::Now();
- scoped_refptr<media::VideoFrame> frame;
- RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
- if (frame_subscriber()->ShouldCaptureFrame(present_time,
- &frame, &callback)) {
- CopyFromCompositingSurfaceToVideoFrame(
- gfx::Rect(current_frame_size_in_dip_),
- frame,
- base::Bind(callback, present_time));
- }
- }
-}
-
-void DelegatedFrameHost::SwapDelegatedFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::DelegatedFrameData> frame_data,
- float frame_device_scale_factor,
- const std::vector<ui::LatencyInfo>& latency_info) {
- RenderWidgetHostImpl* host = client_->GetHost();
- DCHECK(!frame_data->render_pass_list.empty());
-
- cc::RenderPass* root_pass = frame_data->render_pass_list.back();
-
- gfx::Size frame_size = root_pass->output_rect.size();
- gfx::Size frame_size_in_dip =
- ConvertSizeToDIP(frame_device_scale_factor, frame_size);
-
- gfx::Rect damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
- damage_rect.Intersect(gfx::Rect(frame_size));
- gfx::Rect damage_rect_in_dip =
- ConvertRectToDIP(frame_device_scale_factor, damage_rect);
-
- if (ShouldSkipFrame(frame_size_in_dip)) {
- cc::CompositorFrameAck ack;
- cc::TransferableResource::ReturnResources(frame_data->resource_list,
- &ack.resources);
-
- skipped_latency_info_list_.insert(skipped_latency_info_list_.end(),
- latency_info.begin(), latency_info.end());
-
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- host->GetRoutingID(), output_surface_id,
- host->GetProcess()->GetID(), ack);
- skipped_frames_ = true;
- return;
- }
-
- if (skipped_frames_) {
- skipped_frames_ = false;
- damage_rect = gfx::Rect(frame_size);
- damage_rect_in_dip = gfx::Rect(frame_size_in_dip);
-
- // Give the same damage rect to the compositor.
- cc::RenderPass* root_pass = frame_data->render_pass_list.back();
- root_pass->damage_rect = damage_rect;
- }
-
- if (output_surface_id != last_output_surface_id_) {
- // Resource ids are scoped by the output surface.
- // If the originating output surface doesn't match the last one, it
- // indicates the renderer's output surface may have been recreated, in which
- // case we should recreate the DelegatedRendererLayer, to avoid matching
- // resources from the old one with resources from the new one which would
- // have the same id. Changing the layer to showing painted content destroys
- // the DelegatedRendererLayer.
- EvictDelegatedFrame();
-
- // Drop the cc::DelegatedFrameResourceCollection so that we will not return
- // any resources from the old output surface with the new output surface id.
- if (resource_collection_.get()) {
- resource_collection_->SetClient(NULL);
-
- if (resource_collection_->LoseAllResources())
- SendReturnedDelegatedResources(last_output_surface_id_);
-
- resource_collection_ = NULL;
- }
- last_output_surface_id_ = output_surface_id;
- }
- if (frame_size.IsEmpty()) {
- DCHECK(frame_data->resource_list.empty());
- EvictDelegatedFrame();
- } else {
- if (!resource_collection_) {
- resource_collection_ = new cc::DelegatedFrameResourceCollection;
- resource_collection_->SetClient(this);
- }
- // If the physical frame size changes, we need a new |frame_provider_|. If
- // the physical frame size is the same, but the size in DIP changed, we
- // need to adjust the scale at which the frames will be drawn, and we do
- // this by making a new |frame_provider_| also to ensure the scale change
- // is presented in sync with the new frame content.
- if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() ||
- frame_size_in_dip != current_frame_size_in_dip_) {
- frame_provider_ = new cc::DelegatedFrameProvider(
- resource_collection_.get(), frame_data.Pass());
- client_->GetLayer()->SetShowDelegatedContent(frame_provider_.get(),
- frame_size_in_dip);
- } else {
- frame_provider_->SetFrameData(frame_data.Pass());
- }
- }
- released_front_lock_ = NULL;
- current_frame_size_in_dip_ = frame_size_in_dip;
- CheckResizeLock();
-
- client_->SchedulePaintInRect(damage_rect_in_dip);
-
- pending_delegated_ack_count_++;
-
- ui::Compositor* compositor = client_->GetCompositor();
- if (!compositor) {
- SendDelegatedFrameAck(output_surface_id);
- } else {
- std::vector<ui::LatencyInfo>::const_iterator it;
- for (it = latency_info.begin(); it != latency_info.end(); ++it)
- compositor->SetLatencyInfo(*it);
- // If we've previously skipped any latency infos add them.
- for (it = skipped_latency_info_list_.begin();
- it != skipped_latency_info_list_.end();
- ++it)
- compositor->SetLatencyInfo(*it);
- skipped_latency_info_list_.clear();
- AddOnCommitCallbackAndDisableLocks(
- base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck,
- AsWeakPtr(),
- output_surface_id));
- }
- DidReceiveFrameFromRenderer();
- if (frame_provider_.get())
- delegated_frame_evictor_->SwappedFrame(!host->is_hidden());
- // Note: the frame may have been evicted immediately.
-}
-
-void DelegatedFrameHost::SendDelegatedFrameAck(uint32 output_surface_id) {
- RenderWidgetHostImpl* host = client_->GetHost();
- cc::CompositorFrameAck ack;
- if (resource_collection_)
- resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(host->GetRoutingID(),
- output_surface_id,
- host->GetProcess()->GetID(),
- ack);
- DCHECK_GT(pending_delegated_ack_count_, 0);
- pending_delegated_ack_count_--;
-}
-
-void DelegatedFrameHost::UnusedResourcesAreAvailable() {
- if (pending_delegated_ack_count_)
- return;
-
- SendReturnedDelegatedResources(last_output_surface_id_);
-}
-
-void DelegatedFrameHost::SendReturnedDelegatedResources(
- uint32 output_surface_id) {
- RenderWidgetHostImpl* host = client_->GetHost();
- DCHECK(resource_collection_);
-
- cc::CompositorFrameAck ack;
- resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
- DCHECK(!ack.resources.empty());
-
- RenderWidgetHostImpl::SendReclaimCompositorResources(
- host->GetRoutingID(),
- output_surface_id,
- host->GetProcess()->GetID(),
- ack);
-}
-
-void DelegatedFrameHost::EvictDelegatedFrame() {
- client_->GetLayer()->SetShowPaintedContent();
- frame_provider_ = NULL;
- delegated_frame_evictor_->DiscardedFrame();
-}
-
-// static
-void DelegatedFrameHost::CopyFromCompositingSurfaceHasResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType color_type,
- 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, color_type,
- callback,
- result.Pass());
- return;
- }
-
- DCHECK(result->HasBitmap());
- PrepareBitmapCopyOutputResult(dst_size_in_pixel, color_type, callback,
- result.Pass());
-}
-
-static void CopyFromCompositingSurfaceFinished(
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- scoped_ptr<cc::SingleReleaseCallback> release_callback,
- scoped_ptr<SkBitmap> bitmap,
- scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
- bool result) {
- bitmap_pixels_lock.reset();
-
- uint32 sync_point = 0;
- if (result) {
- GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
- sync_point = gl_helper->InsertSyncPoint();
- }
- bool lost_resource = sync_point == 0;
- release_callback->Run(sync_point, lost_resource);
-
- callback.Run(result, *bitmap);
-}
-
// static
-void DelegatedFrameHost::PrepareTextureCopyOutputResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType color_type,
- 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()));
-
- scoped_ptr<SkBitmap> bitmap(new SkBitmap);
- if (!bitmap->allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
- dst_size_in_pixel.height(),
- color_type,
- kOpaque_SkAlphaType)))
- return;
-
- 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());
-
- cc::TextureMailbox texture_mailbox;
- scoped_ptr<cc::SingleReleaseCallback> release_callback;
- result->TakeTexture(&texture_mailbox, &release_callback);
- DCHECK(texture_mailbox.IsTexture());
-
- ignore_result(scoped_callback_runner.Release());
-
- gl_helper->CropScaleReadbackAndCleanMailbox(
- texture_mailbox.mailbox(),
- texture_mailbox.sync_point(),
- result->size(),
- gfx::Rect(result->size()),
- dst_size_in_pixel,
- pixels,
- color_type,
- base::Bind(&CopyFromCompositingSurfaceFinished,
- callback,
- base::Passed(&release_callback),
- base::Passed(&bitmap),
- base::Passed(&bitmap_pixels_lock)),
- GLHelper::SCALER_QUALITY_FAST);
-}
-
-// static
-void DelegatedFrameHost::PrepareBitmapCopyOutputResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType color_type,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- if (color_type != kN32_SkColorType) {
- NOTIMPLEMENTED();
- callback.Run(false, SkBitmap());
- return;
- }
- DCHECK(result->HasBitmap());
- scoped_ptr<SkBitmap> source = result->TakeBitmap();
- DCHECK(source);
- SkBitmap bitmap = skia::ImageOperations::Resize(
- *source,
- skia::ImageOperations::RESIZE_BEST,
- dst_size_in_pixel.width(),
- dst_size_in_pixel.height());
- callback.Run(true, bitmap);
-}
-
-// static
-void DelegatedFrameHost::ReturnSubscriberTexture(
- base::WeakPtr<DelegatedFrameHost> dfh,
- scoped_refptr<OwnedMailbox> subscriber_texture,
- uint32 sync_point) {
- if (!subscriber_texture.get())
- return;
- if (!dfh)
- return;
-
- subscriber_texture->UpdateSyncPoint(sync_point);
-
- if (dfh->frame_subscriber_ && subscriber_texture->texture_id())
- dfh->idle_frame_subscriber_textures_.push_back(subscriber_texture);
-}
-
-void DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo(
- base::WeakPtr<DelegatedFrameHost> dfh,
- const base::Callback<void(bool)>& callback,
- scoped_refptr<OwnedMailbox> subscriber_texture,
- scoped_ptr<cc::SingleReleaseCallback> release_callback,
- bool result) {
- callback.Run(result);
-
- uint32 sync_point = 0;
- if (result) {
- GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
- sync_point = gl_helper->InsertSyncPoint();
- }
- if (release_callback) {
- // A release callback means the texture came from the compositor, so there
- // should be no |subscriber_texture|.
- DCHECK(!subscriber_texture);
- bool lost_resource = sync_point == 0;
- release_callback->Run(sync_point, lost_resource);
- }
- ReturnSubscriberTexture(dfh, subscriber_texture, sync_point);
-}
-
-// static
-void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
- base::WeakPtr<DelegatedFrameHost> dfh,
- scoped_refptr<OwnedMailbox> subscriber_texture,
- scoped_refptr<media::VideoFrame> video_frame,
- const base::Callback<void(bool)>& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
- base::ScopedClosureRunner scoped_return_subscriber_texture(
- base::Bind(&ReturnSubscriberTexture, dfh, subscriber_texture, 0));
-
- if (!dfh)
- return;
- if (result->IsEmpty())
- return;
- if (result->size().IsEmpty())
- return;
-
- // Compute the dest size we want after the letterboxing resize. Make the
- // coordinates and sizes even because we letterbox in YUV space
- // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
- // line up correctly.
- // The video frame's coded_size() and the result's size() are both physical
- // pixels.
- gfx::Rect region_in_frame =
- media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
- result->size());
- region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
- region_in_frame.y() & ~1,
- region_in_frame.width() & ~1,
- region_in_frame.height() & ~1);
- if (region_in_frame.IsEmpty())
- return;
-
- if (!result->HasTexture()) {
- DCHECK(result->HasBitmap());
- scoped_ptr<SkBitmap> bitmap = result->TakeBitmap();
- // Scale the bitmap to the required size, if necessary.
- SkBitmap scaled_bitmap;
- if (result->size().width() != region_in_frame.width() ||
- result->size().height() != region_in_frame.height()) {
- skia::ImageOperations::ResizeMethod method =
- skia::ImageOperations::RESIZE_GOOD;
- scaled_bitmap = skia::ImageOperations::Resize(*bitmap.get(), method,
- region_in_frame.width(),
- region_in_frame.height());
- } else {
- scaled_bitmap = *bitmap.get();
- }
-
- {
- SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);
-
- media::CopyRGBToVideoFrame(
- reinterpret_cast<uint8*>(scaled_bitmap.getPixels()),
- scaled_bitmap.rowBytes(),
- region_in_frame,
- video_frame.get());
- }
- ignore_result(scoped_callback_runner.Release());
- callback.Run(true);
- return;
- }
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper)
- return;
- if (subscriber_texture.get() && !subscriber_texture->texture_id())
- return;
-
- cc::TextureMailbox texture_mailbox;
- scoped_ptr<cc::SingleReleaseCallback> release_callback;
- result->TakeTexture(&texture_mailbox, &release_callback);
- DCHECK(texture_mailbox.IsTexture());
-
- gfx::Rect result_rect(result->size());
-
- content::ReadbackYUVInterface* yuv_readback_pipeline =
- dfh->yuv_readback_pipeline_.get();
- if (yuv_readback_pipeline == NULL ||
- yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
- yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
- yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
- GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
- std::string quality_switch = switches::kTabCaptureDownscaleQuality;
- // If we're scaling up, we can use the "best" quality.
- if (result_rect.size().width() < region_in_frame.size().width() &&
- result_rect.size().height() < region_in_frame.size().height())
- quality_switch = switches::kTabCaptureUpscaleQuality;
-
- std::string switch_value =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
- if (switch_value == "fast")
- quality = GLHelper::SCALER_QUALITY_FAST;
- else if (switch_value == "good")
- quality = GLHelper::SCALER_QUALITY_GOOD;
- else if (switch_value == "best")
- quality = GLHelper::SCALER_QUALITY_BEST;
-
- dfh->yuv_readback_pipeline_.reset(
- gl_helper->CreateReadbackPipelineYUV(quality,
- result_rect.size(),
- result_rect,
- video_frame->coded_size(),
- region_in_frame,
- true,
- true));
- yuv_readback_pipeline = dfh->yuv_readback_pipeline_.get();
- }
-
- ignore_result(scoped_callback_runner.Release());
- ignore_result(scoped_return_subscriber_texture.Release());
- base::Callback<void(bool result)> finished_callback = base::Bind(
- &DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo,
- dfh->AsWeakPtr(),
- callback,
- subscriber_texture,
- base::Passed(&release_callback));
- yuv_readback_pipeline->ReadbackYUV(texture_mailbox.mailbox(),
- texture_mailbox.sync_point(),
- video_frame.get(),
- finished_callback);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DelegatedFrameHost, ui::CompositorObserver implementation:
-
-void DelegatedFrameHost::OnCompositingDidCommit(
- ui::Compositor* compositor) {
- RenderWidgetHostImpl* host = client_->GetHost();
- if (can_lock_compositor_ == NO_PENDING_COMMIT) {
- can_lock_compositor_ = YES_CAN_LOCK;
- if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
- can_lock_compositor_ = YES_DID_LOCK;
- }
- RunOnCommitCallbacks();
- if (resize_lock_ &&
- resize_lock_->expected_size() == current_frame_size_in_dip_) {
- resize_lock_.reset();
- host->WasResized();
- // We may have had a resize while we had the lock (e.g. if the lock expired,
- // or if the UI still gave us some resizes), so make sure we grab a new lock
- // if necessary.
- MaybeCreateResizeLock();
- }
-}
-
-void DelegatedFrameHost::OnCompositingStarted(
- ui::Compositor* compositor, base::TimeTicks start_time) {
- last_draw_ended_ = start_time;
-}
-
-void DelegatedFrameHost::OnCompositingEnded(
- ui::Compositor* compositor) {
-}
-
-void DelegatedFrameHost::OnCompositingAborted(ui::Compositor* compositor) {
-}
-
-void DelegatedFrameHost::OnCompositingLockStateChanged(
- ui::Compositor* compositor) {
- // A compositor lock that is part of a resize lock timed out. We
- // should display a renderer frame.
- if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
- can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
- }
-}
-
-void DelegatedFrameHost::OnUpdateVSyncParameters(
- base::TimeTicks timebase,
- base::TimeDelta interval) {
- RenderWidgetHostImpl* host = client_->GetHost();
- if (client_->IsVisible())
- host->UpdateVSyncParameters(timebase, interval);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
-
-void DelegatedFrameHost::OnLostResources() {
- RenderWidgetHostImpl* host = client_->GetHost();
- if (frame_provider_.get())
- EvictDelegatedFrame();
- idle_frame_subscriber_textures_.clear();
- yuv_readback_pipeline_.reset();
-
- host->ScheduleComposite();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DelegatedFrameHost, private:
-
-DelegatedFrameHost::~DelegatedFrameHost() {
- ImageTransportFactory::GetInstance()->RemoveObserver(this);
-
- if (resource_collection_.get())
- resource_collection_->SetClient(NULL);
-
- DCHECK(!vsync_manager_);
-}
-
-void DelegatedFrameHost::RunOnCommitCallbacks() {
- for (std::vector<base::Closure>::const_iterator
- it = on_compositing_did_commit_callbacks_.begin();
- it != on_compositing_did_commit_callbacks_.end(); ++it) {
- it->Run();
- }
- on_compositing_did_commit_callbacks_.clear();
-}
-
-void DelegatedFrameHost::AddOnCommitCallbackAndDisableLocks(
- const base::Closure& callback) {
- ui::Compositor* compositor = client_->GetCompositor();
- DCHECK(compositor);
-
- if (!compositor->HasObserver(this))
- compositor->AddObserver(this);
-
- can_lock_compositor_ = NO_PENDING_COMMIT;
- on_compositing_did_commit_callbacks_.push_back(callback);
-}
-
-void DelegatedFrameHost::AddedToWindow() {
- ui::Compositor* compositor = client_->GetCompositor();
- if (compositor) {
- DCHECK(!vsync_manager_);
- vsync_manager_ = compositor->vsync_manager();
- vsync_manager_->AddObserver(this);
- }
-}
-
-void DelegatedFrameHost::RemovingFromWindow() {
- RunOnCommitCallbacks();
- resize_lock_.reset();
- client_->GetHost()->WasResized();
- ui::Compositor* compositor = client_->GetCompositor();
- if (compositor && compositor->HasObserver(this))
- compositor->RemoveObserver(this);
-
- if (vsync_manager_) {
- vsync_manager_->RemoveObserver(this);
- vsync_manager_ = NULL;
- }
-}
-
-void DelegatedFrameHost::LockResources() {
- DCHECK(frame_provider_);
- delegated_frame_evictor_->LockFrame();
-}
-
-void DelegatedFrameHost::UnlockResources() {
- DCHECK(frame_provider_);
- delegated_frame_evictor_->UnlockFrame();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DelegatedFrameHost, ui::LayerOwnerDelegate implementation:
-
-void DelegatedFrameHost::OnLayerRecreated(ui::Layer* old_layer,
- ui::Layer* new_layer) {
- // The new_layer is the one that will be used by our Window, so that's the one
- // that should keep our frame. old_layer will be returned to the
- // RecreateLayer caller, and should have a copy.
- if (frame_provider_.get()) {
- new_layer->SetShowDelegatedContent(frame_provider_.get(),
- current_frame_size_in_dip_);
+DelegatedFrameHost* DelegatedFrameHost::Create(
+ DelegatedFrameHostClient* client) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseSurfaces)) {
+ return new DelegatedFrameSurfaceHost(client);
+ } else {
+ return new DelegatedFrameLayerHost(client);
}
}

Powered by Google App Engine
This is Rietveld 408576698