blob: a7d366d64b233675d31454ce20c678712fd29d48 [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/android/android_surface_control_compositor.h"
#include <utility>
#include "base/check.h"
#include "base/check_op.h"
#include "base/task/single_thread_task_runner.h"
#include "cc/slim/frame_sink.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
#include "content/browser/renderer_host/compositor_dependencies_android.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "ui/android/window_android.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gl/android/scoped_java_surface_control.h"
namespace content {
AndroidSurfaceControlCompositor::AndroidSurfaceControlCompositor(
viz::FrameSinkId frame_sink_id)
: HostDisplayClient(gfx::kNullAcceleratedWidget),
frame_sink_id_(frame_sink_id) {}
AndroidSurfaceControlCompositor::~AndroidSurfaceControlCompositor() {
display_private_.reset();
layer_tree_.reset();
if (is_registered_) {
GetHostFrameSinkManager()->InvalidateFrameSinkId(
frame_sink_id_, this,
base::BindOnce(
[](gpu::SurfaceHandle surface_handle) {
if (surface_handle != gpu::kNullSurfaceHandle) {
gpu::GpuSurfaceTracker::Get()->RemoveSurface(surface_handle);
}
},
surface_handle_));
} else if (surface_handle_ != gpu::kNullSurfaceHandle) {
gpu::GpuSurfaceTracker::Get()->RemoveSurface(surface_handle_);
}
}
bool AndroidSurfaceControlCompositor::Initialize(
ui::WindowAndroid& window_android,
const base::android::JavaRef<jobject>& j_surface_control,
cc::slim::LayerTreeClient* client,
scoped_refptr<cc::slim::Layer> root_layer,
const gfx::Size& size_pixels,
float device_scale_factor) {
CHECK(!j_surface_control.is_null());
CHECK(root_layer);
bool release_on_destroy = true;
gl::ScopedJavaSurfaceControl scoped_java_surface_control(j_surface_control,
release_on_destroy);
surface_handle_ = gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(
gpu::SurfaceRecord(std::move(scoped_java_surface_control)));
if (surface_handle_ == gpu::kNullSurfaceHandle) {
return false;
}
GetHostFrameSinkManager()->RegisterFrameSinkId(
frame_sink_id_, this, viz::ReportFirstSurfaceActivation::kNo);
is_registered_ = true;
layer_tree_ = cc::slim::LayerTree::Create(client);
layer_tree_->set_background_color(SkColors::kTransparent);
layer_tree_->SetRoot(std::move(root_layer));
return CreateDisplayAndFrameSink(window_android, size_pixels,
device_scale_factor);
}
void AndroidSurfaceControlCompositor::Resize(
const gfx::Size& size_pixels,
float device_scale_factor,
const viz::LocalSurfaceId& local_surface_id) {
if (display_private_) {
display_private_->Resize(size_pixels);
}
if (layer_tree_) {
layer_tree_->SetViewportRectAndScale(gfx::Rect(size_pixels),
device_scale_factor, local_surface_id);
}
}
bool AndroidSurfaceControlCompositor::CreateDisplayAndFrameSink(
ui::WindowAndroid& window_android,
const gfx::Size& size_pixels,
float device_scale_factor) {
CHECK_NE(surface_handle_, gpu::kNullSurfaceHandle);
scoped_refptr<gpu::GpuChannelHost> gpu_channel_host =
BrowserGpuChannelHostFactory::instance()->GetGpuChannel();
if (!gpu_channel_host) {
return false;
}
CompositorDependenciesAndroid::Get().TryEstablishVizConnectionIfNeeded();
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
GetUIThreadTaskRunner({BrowserTaskType::kUserInput});
auto root_params = viz::mojom::RootCompositorFrameSinkParams::New();
mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink> sink_remote;
root_params->compositor_frame_sink =
sink_remote.InitWithNewEndpointAndPassReceiver();
mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> client_receiver =
root_params->compositor_frame_sink_client
.InitWithNewPipeAndPassReceiver();
display_private_.reset();
root_params->display_private =
display_private_.BindNewEndpointAndPassReceiver();
root_params->display_client = GetBoundRemote(task_runner);
gfx::DisplayColorSpaces display_color_spaces =
display::Screen::Get()
->GetDisplayNearestWindow(&window_android)
.GetColorSpaces();
viz::RendererSettings renderer_settings;
renderer_settings.partial_swap_enabled = true;
renderer_settings.allow_antialiasing = false;
renderer_settings.highp_threshold_min = 2048;
renderer_settings.requires_alpha_channel = true;
root_params->frame_sink_id = frame_sink_id_;
root_params->widget = surface_handle_;
root_params->gpu_compositing = true;
root_params->renderer_settings = renderer_settings;
root_params->refresh_rate = window_android.GetRefreshRate();
GetHostFrameSinkManager()->CreateRootCompositorFrameSink(
std::move(root_params), /*maybe_wait_on_destruction=*/false);
display_private_->SetDisplayVisible(true);
display_private_->Resize(size_pixels);
display_private_->SetDisplayColorSpaces(display_color_spaces);
display_private_->SetSupportedRefreshRates(
window_android.GetSupportedRefreshRates());
layer_tree_->SetFrameSink(cc::slim::FrameSink::Create(
std::move(sink_remote), std::move(client_receiver), nullptr,
GetUIThreadTaskRunner({BrowserTaskType::kUserInput}),
base::kInvalidThreadId));
layer_tree_->SetVisible(true);
return true;
}
} // namespace content