chromium/android_webview/browser/gfx/display_webview.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/browser/gfx/display_webview.h"

#include "android_webview/browser/gfx/overlay_processor_webview.h"
#include "android_webview/browser/gfx/root_frame_sink.h"
#include "base/memory/ptr_util.h"
#include "components/viz/common/features.h"
#include "components/viz/service/display/overlay_processor_stub.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "gpu/config/gpu_finch_features.h"

namespace android_webview {

std::unique_ptr<DisplayWebView> DisplayWebView::Create(
    const viz::RendererSettings& settings,
    const viz::DebugRendererSettings* debug_settings,
    const viz::FrameSinkId& frame_sink_id,
    std::unique_ptr<viz::DisplayCompositorMemoryAndTaskController>
        gpu_dependency,
    std::unique_ptr<viz::OutputSurface> output_surface,
    viz::FrameSinkManagerImpl* frame_sink_manager,
    RootFrameSink* root_frame_sink) {
  std::unique_ptr<viz::OverlayProcessorInterface> overlay_processor;
  OverlayProcessorWebView* overlay_processor_webview_raw = nullptr;
  if (features::IsAndroidSurfaceControlEnabled()) {
    // TODO(crbug.com/40113791): This is to help triage bugs on pre-release
    // android. Remove this log once feature is controlled only by feature flag
    // or launched.
    LOG(WARNING) << "WebView overlays are enabled!";
    auto overlay_processor_webview = std::make_unique<OverlayProcessorWebView>(
        gpu_dependency.get(), frame_sink_manager);
    overlay_processor_webview_raw = overlay_processor_webview.get();
    overlay_processor = std::move(overlay_processor_webview);
  } else {
    overlay_processor = std::make_unique<viz::OverlayProcessorStub>();
  }

  auto scheduler = std::make_unique<DisplaySchedulerWebView>(
      root_frame_sink, overlay_processor_webview_raw);

  return base::WrapUnique(new DisplayWebView(
      settings, debug_settings, frame_sink_id, std::move(gpu_dependency),
      std::move(output_surface), std::move(overlay_processor),
      std::move(scheduler), overlay_processor_webview_raw, frame_sink_manager,
      root_frame_sink));
}

DisplayWebView::DisplayWebView(
    const viz::RendererSettings& settings,
    const viz::DebugRendererSettings* debug_settings,
    const viz::FrameSinkId& frame_sink_id,
    std::unique_ptr<viz::DisplayCompositorMemoryAndTaskController>
        gpu_dependency,
    std::unique_ptr<viz::OutputSurface> output_surface,
    std::unique_ptr<viz::OverlayProcessorInterface> overlay_processor,
    std::unique_ptr<viz::DisplaySchedulerBase> scheduler,
    OverlayProcessorWebView* overlay_processor_webview,
    viz::FrameSinkManagerImpl* frame_sink_manager,
    RootFrameSink* root_frame_sink)
    : viz::Display(/*bitmap_manager=*/nullptr,
                   /*shared_image_manager=*/nullptr,
                   /*sync_point_manager=*/nullptr,
                   /*gpu_scheduler=*/nullptr,
                   settings,
                   debug_settings,
                   frame_sink_id,
                   std::move(gpu_dependency),
                   std::move(output_surface),
                   std::move(overlay_processor),
                   std::move(scheduler),
                   /*current_task_runner=*/nullptr),
      overlay_processor_webview_(overlay_processor_webview),
      frame_sink_manager_(frame_sink_manager),
      root_frame_sink_(root_frame_sink),
      use_new_invalidate_heuristic_(
          features::UseWebViewNewInvalidateHeuristic()) {
  if (overlay_processor_webview_) {
    frame_sink_manager_observation_.Observe(frame_sink_manager);
  }
}

DisplayWebView::~DisplayWebView() = default;

void DisplayWebView::OnFrameSinkDidFinishFrame(
    const viz::FrameSinkId& frame_sink_id,
    const viz::BeginFrameArgs& args) {
  DCHECK(overlay_processor_webview_);
  auto surface_id =
      overlay_processor_webview_->GetOverlaySurfaceId(frame_sink_id);
  if (surface_id.is_valid()) {
    auto* surface =
        frame_sink_manager_->surface_manager()->GetSurfaceForId(surface_id);
    DCHECK(surface);

    if (use_new_invalidate_heuristic_) {
      // For overlays we are going to display this frame immediately, so commit
      // it.
      surface->CommitFramesRecursively(
          [](const viz::SurfaceId&, const viz::BeginFrameId&) { return true; });
    }

    // TODO(vasilyt): We don't need full aggregation here as we don't need
    // aggregated frame.
    aggregator_->Aggregate(current_surface_id_, base::TimeTicks::Now(),
                           gfx::OVERLAY_TRANSFORM_NONE, gfx::Rect(),
                           ++swapped_trace_id_);
    auto* resolved_data = aggregator_->GetLatestFrameData(surface_id);
    if (resolved_data) {
      if (!overlay_processor_webview_->ProcessForFrameSinkId(frame_sink_id,
                                                             resolved_data)) {
        // If we failed to update overlay buffer, we need to invalidate to make
        // sure full draw happens.
        root_frame_sink_->InvalidateForOverlays();
      }
    }
  }
}

const base::flat_set<viz::SurfaceId>& DisplayWebView::GetContainedSurfaceIds() {
  return aggregator_->previous_contained_surfaces();
}

}  // namespace android_webview