0

Set custom Skia GrContextOptions for WebView on Android TV

This creates a new embedder delegate that allows the embedder to modify
the GrContextOptions passed to skia. Behind a flag that is disabled by
default, this CL disables mip map sharpening and sets MSAA sample count
to 0.

Bug: 364872963
Change-Id: Ifec3c530d0a9bf837b313b01ed7c41094446e483
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5982515
Reviewed-by: Peter Beverloo <peter@chromium.org>
Reviewed-by: Alexander Timin <altimin@chromium.org>
Commit-Queue: Alex Mitra <alexmitra@chromium.org>
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1389835}
This commit is contained in:
Alex Mitra
2024-11-29 16:22:10 +00:00
committed by Chromium LUCI CQ
parent 43ac25ca0d
commit c246bcc072
27 changed files with 262 additions and 19 deletions

@ -6,6 +6,7 @@ include_rules = [
"+android_webview/common/aw_features.h",
"+android_webview/common/aw_switches.h",
"+android_webview/common/crash_reporter/crash_keys.h",
"+android_webview/common/gfx",
"+android_webview/public/browser",
"+components/viz/service/gl",
"+components/viz/service/main",

@ -6,6 +6,7 @@
#include <utility>
#include "android_webview/common/gfx/aw_gr_context_options_provider.h"
#include "android_webview/public/browser/draw_fn.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
@ -20,6 +21,7 @@
#include "gpu/vulkan/vulkan_fence_helper.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "gpu/vulkan/vulkan_util.h"
#include "third_party/skia/include/gpu/ganesh/GrContextOptions.h"
#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/vk/GrVkDirectContext.h"
#include "third_party/skia/include/gpu/vk/VulkanBackendContext.h"
@ -156,7 +158,11 @@ bool AwVulkanContextProvider::Globals::Initialize(
gpu::CreateSkiaVulkanMemoryAllocator(device_queue.get()),
.fGetProc = get_proc,
};
gr_context = GrDirectContexts::MakeVulkan(backend_context);
GrContextOptions options;
std::unique_ptr<AwGrContextOptionsProvider> options_provider =
std::make_unique<AwGrContextOptionsProvider>();
options_provider->SetCustomGrContextOptions(options);
gr_context = GrDirectContexts::MakeVulkan(backend_context, options);
if (!gr_context) {
LOG(ERROR) << "Unable to initialize GrContext.";
return false;

@ -11,6 +11,7 @@
#include "android_webview/browser/gfx/gpu_service_webview.h"
#include "android_webview/browser/gfx/skia_output_surface_dependency_webview.h"
#include "android_webview/browser/gfx/task_queue_webview.h"
#include "android_webview/common/aw_features.h"
#include "android_webview/common/crash_reporter/crash_keys.h"
#include "base/command_line.h"
#include "base/feature_list.h"
@ -103,7 +104,9 @@ void OnContextLost(std::unique_ptr<bool> expect_loss,
OutputSurfaceProviderWebView::OutputSurfaceProviderWebView(
AwVulkanContextProvider* vulkan_context_provider)
: vulkan_context_provider_(vulkan_context_provider) {
: vulkan_context_provider_(vulkan_context_provider),
aw_gr_context_options_provider_(
std::make_unique<AwGrContextOptionsProvider>()) {
// Should be kept in sync with compositor_impl_android.cc.
renderer_settings_.allow_antialiasing = false;
renderer_settings_.highp_threshold_min = 2048;
@ -111,7 +114,7 @@ OutputSurfaceProviderWebView::OutputSurfaceProviderWebView(
// Webview does not own the surface so should not clear it.
renderer_settings_.should_clear_root_render_pass = false;
enable_vulkan_ = features::IsUsingVulkan();
enable_vulkan_ = ::features::IsUsingVulkan();
DCHECK(!enable_vulkan_ || vulkan_context_provider_);
auto* command_line = base::CommandLine::ForCurrentProcess();
@ -212,10 +215,15 @@ void OutputSurfaceProviderWebView::InitializeContext() {
expect_context_loss_ = expect_context_loss_ptr.get();
shared_context_state_ = base::MakeRefCounted<gpu::SharedContextState>(
share_group, std::move(gl_surface_for_scs), std::move(gl_context),
false /* use_virtualized_gl_contexts */,
/*use_virtualized_gl_contexts=*/false,
base::BindOnce(&OnContextLost, std::move(expect_context_loss_ptr)),
GpuServiceWebView::GetInstance()->gpu_preferences().gr_context_type,
vulkan_context_provider_);
vulkan_context_provider_, /*metal_context_provider=*/nullptr,
/*dawn_context_provider=*/nullptr, /*peak_memory_monitor=*/nullptr,
/*created_on_compositor_gpu_thread=*/false,
base::FeatureList::IsEnabled(features::kWebViewDisableSharpeningAndMSAA)
? aw_gr_context_options_provider_.get()
: nullptr);
if (!enable_vulkan_) {
auto feature_info = base::MakeRefCounted<gpu::gles2::FeatureInfo>(
workarounds, GpuServiceWebView::GetInstance()->gpu_feature_info());

@ -8,6 +8,7 @@
#include <memory>
#include "android_webview/browser/gfx/aw_gl_surface.h"
#include "android_webview/common/gfx/aw_gr_context_options_provider.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "components/viz/common/display/renderer_settings.h"
@ -57,6 +58,8 @@ class OutputSurfaceProviderWebView {
void InitializeContext();
const raw_ptr<AwVulkanContextProvider> vulkan_context_provider_;
const std::unique_ptr<AwGrContextOptionsProvider>
aw_gr_context_options_provider_;
// The member variables are effectively const after constructor, so it's safe
// to call accessors on different threads.
viz::RendererSettings renderer_settings_;

@ -27,6 +27,8 @@ source_set("common") {
"crash_reporter/crash_keys.cc",
"crash_reporter/crash_keys.h",
"devtools_instrumentation.h",
"gfx/aw_gr_context_options_provider.cc",
"gfx/aw_gr_context_options_provider.h",
"url_constants.cc",
"url_constants.h",
]
@ -44,6 +46,7 @@ source_set("common") {
"//components/version_info:generate_version_info",
"//components/version_info/android:channel_getter",
"//content/public/common",
"//gpu/command_buffer/service:gles2",
"//gpu/config",
"//ipc",
"//mojo/public/cpp/bindings",

@ -29,6 +29,13 @@ BASE_FEATURE(kWebViewDigitalAssetLinksLoadIncludes,
"WebViewDigitalAssetLinksLoadIncludes",
base::FEATURE_DISABLED_BY_DEFAULT);
// Disables MSAA and default sharpening when rendering scaled elements. This is
// often preferable when rendering images/video but can have adverse effects for
// text on some displays.
BASE_FEATURE(kWebViewDisableSharpeningAndMSAA,
"WebViewDisableSharpeningAndMSAA",
base::FEATURE_DISABLED_BY_DEFAULT);
// Allows JS DataTransfer Files from content URIs in drag-drop.
BASE_FEATURE(kWebViewDragDropFiles,
"WebViewDragDropFiles",

@ -18,6 +18,7 @@ namespace android_webview::features {
BASE_DECLARE_FEATURE(kWebViewAutoSAA);
BASE_DECLARE_FEATURE(kWebViewBackForwardCache);
BASE_DECLARE_FEATURE(kWebViewDigitalAssetLinksLoadIncludes);
BASE_DECLARE_FEATURE(kWebViewDisableSharpeningAndMSAA);
BASE_DECLARE_FEATURE(kWebViewDragDropFiles);
BASE_DECLARE_FEATURE(kWebViewExtraHeadersSameOriginOnly);
BASE_DECLARE_FEATURE(kWebViewFileSystemAccess);

@ -0,0 +1,21 @@
// Copyright 2024 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/common/gfx/aw_gr_context_options_provider.h"
#include "android_webview/common/aw_features.h"
namespace android_webview {
void AwGrContextOptionsProvider::SetCustomGrContextOptions(
GrContextOptions& options) const {
if (base::FeatureList::IsEnabled(
features::kWebViewDisableSharpeningAndMSAA)) {
// crbug.com/364872963
options.fInternalMultisampleCount = 0;
options.fSharpenMipmappedTextures = false;
}
}
} // namespace android_webview

@ -0,0 +1,25 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_WEBVIEW_COMMON_GFX_AW_GR_CONTEXT_OPTIONS_PROVIDER_H_
#define ANDROID_WEBVIEW_COMMON_GFX_AW_GR_CONTEXT_OPTIONS_PROVIDER_H_
#include "gpu/command_buffer/service/shared_context_state.h"
namespace android_webview {
// Used by gfx to set custom GrContextOptions which get passed to skia. These
// options control how content is rendered on screen.
class AwGrContextOptionsProvider
: public gpu::SharedContextState::GrContextOptionsProvider {
public:
AwGrContextOptionsProvider() = default;
virtual ~AwGrContextOptionsProvider() = default;
void SetCustomGrContextOptions(GrContextOptions& options) const override;
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_COMMON_GFX_AW_GR_CONTEXT_OPTIONS_PROVIDER_H_

@ -9,6 +9,7 @@ source_set("gpu") {
]
deps = [
"//android_webview/common:common",
"//base",
"//content/public/gpu",
]

@ -12,12 +12,14 @@ AwContentGpuClient::AwContentGpuClient(
GetSyncPointManagerCallback sync_point_manager_callback,
GetSharedImageManagerCallback shared_image_manager_callback,
GetSchedulerCallback scheduler_callback,
GetVizCompositorThreadRunnerCallback viz_compositor_thread_runner_callback)
GetVizCompositorThreadRunnerCallback viz_compositor_thread_runner_callback,
const AwGrContextOptionsProvider* gr_context_options_provider)
: sync_point_manager_callback_(std::move(sync_point_manager_callback)),
shared_image_manager_callback_(std::move(shared_image_manager_callback)),
scheduler_callback_(std::move(scheduler_callback)),
viz_compositor_thread_runner_callback_(
std::move(viz_compositor_thread_runner_callback)) {}
std::move(viz_compositor_thread_runner_callback)),
gr_context_options_provider_(gr_context_options_provider) {}
AwContentGpuClient::~AwContentGpuClient() {}
@ -38,4 +40,9 @@ AwContentGpuClient::GetVizCompositorThreadRunner() {
return viz_compositor_thread_runner_callback_.Run();
}
const gpu::SharedContextState::GrContextOptionsProvider*
AwContentGpuClient::GetGrContextOptionsProvider() {
return gr_context_options_provider_;
}
} // namespace android_webview

@ -5,6 +5,7 @@
#ifndef ANDROID_WEBVIEW_GPU_AW_CONTENT_GPU_CLIENT_H_
#define ANDROID_WEBVIEW_GPU_AW_CONTENT_GPU_CLIENT_H_
#include "android_webview/common/gfx/aw_gr_context_options_provider.h"
#include "base/functional/callback.h"
#include "content/public/gpu/content_gpu_client.h"
@ -25,7 +26,8 @@ class AwContentGpuClient : public content::ContentGpuClient {
GetSharedImageManagerCallback shared_image_manager_callback,
GetSchedulerCallback scheduler_callback,
GetVizCompositorThreadRunnerCallback
viz_compositor_thread_runner_callback);
viz_compositor_thread_runner_callback,
const AwGrContextOptionsProvider* gr_context_options_provider);
AwContentGpuClient(const AwContentGpuClient&) = delete;
AwContentGpuClient& operator=(const AwContentGpuClient&) = delete;
@ -37,12 +39,15 @@ class AwContentGpuClient : public content::ContentGpuClient {
gpu::SharedImageManager* GetSharedImageManager() override;
gpu::Scheduler* GetScheduler() override;
viz::VizCompositorThreadRunner* GetVizCompositorThreadRunner() override;
const gpu::SharedContextState::GrContextOptionsProvider*
GetGrContextOptionsProvider() override;
private:
GetSyncPointManagerCallback sync_point_manager_callback_;
GetSharedImageManagerCallback shared_image_manager_callback_;
GetSchedulerCallback scheduler_callback_;
GetVizCompositorThreadRunnerCallback viz_compositor_thread_runner_callback_;
raw_ptr<const AwGrContextOptionsProvider> gr_context_options_provider_;
};
} // namespace android_webview

@ -380,7 +380,8 @@ content::ContentGpuClient* AwMainDelegate::CreateContentGpuClient() {
base::BindRepeating(&GetSyncPointManager),
base::BindRepeating(&GetSharedImageManager),
base::BindRepeating(&GetScheduler),
base::BindRepeating(&GetVizCompositorThreadRunner));
base::BindRepeating(&GetVizCompositorThreadRunner),
&aw_gr_context_options_provider_);
return content_gpu_client_.get();
}

@ -9,6 +9,7 @@
#include "android_webview/browser/aw_feature_list_creator.h"
#include "android_webview/common/aw_content_client.h"
#include "android_webview/common/gfx/aw_gr_context_options_provider.h"
#include "components/memory_system/memory_system.h"
#include "content/public/app/content_main_delegate.h"
@ -65,6 +66,7 @@ class AwMainDelegate : public content::ContentMainDelegate {
std::unique_ptr<AwContentBrowserClient> content_browser_client_;
std::unique_ptr<AwContentGpuClient> content_gpu_client_;
std::unique_ptr<AwContentRendererClient> content_renderer_client_;
AwGrContextOptionsProvider aw_gr_context_options_provider_;
memory_system::MemorySystem memory_system_;
};

@ -555,7 +555,9 @@ void GpuServiceImpl::InitializeWithHost(
gpu::SyncPointManager* sync_point_manager,
gpu::SharedImageManager* shared_image_manager,
gpu::Scheduler* scheduler,
base::WaitableEvent* shutdown_event) {
base::WaitableEvent* shutdown_event,
const gpu::SharedContextState::GrContextOptionsProvider*
gr_context_options_provider) {
if (!sync_point_manager) {
sync_point_manager = CreateSyncPointManager();
}
@ -577,6 +579,8 @@ void GpuServiceImpl::InitializeWithHost(
shutdown_event = CreateShutdownEvent();
}
gr_context_options_provider_ = gr_context_options_provider;
InitializeWithHostInternal(
std::move(pending_gpu_host), std::move(use_shader_cache_shm_count),
default_offscreen_surface, std::move(creation_params), sync_point_manager,
@ -647,7 +651,7 @@ void GpuServiceImpl::InitializeWithHostInternal(
std::move(default_offscreen_surface),
image_decode_accelerator_worker_.get(), vulkan_context_provider(),
metal_context_provider(), dawn_context_provider(),
dawn_caching_interface_factory());
dawn_caching_interface_factory(), gr_context_options_provider_);
media_gpu_channel_manager_ = std::make_unique<media::MediaGpuChannelManager>(
gpu_channel_manager_.get());

@ -154,7 +154,9 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl
gpu::SyncPointManager* sync_point_manager = nullptr,
gpu::SharedImageManager* shared_image_manager = nullptr,
gpu::Scheduler* scheduler = nullptr,
base::WaitableEvent* shutdown_event = nullptr);
base::WaitableEvent* shutdown_event = nullptr,
const gpu::SharedContextState::GrContextOptionsProvider*
gr_context_options_provider = nullptr);
#else
void InitializeWithHost(
mojo::PendingRemote<mojom::GpuHost> gpu_host,
@ -662,6 +664,9 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl
std::unique_ptr<base::WaitableEvent> owned_shutdown_event_;
raw_ptr<base::WaitableEvent> shutdown_event_ = nullptr;
raw_ptr<const gpu::SharedContextState::GrContextOptionsProvider>
gr_context_options_provider_ = nullptr;
// Callback that safely exits GPU process.
base::OnceCallback<void(ExitCode)> exit_callback_;
base::AtomicFlag is_exiting_;

@ -207,7 +207,8 @@ void VizMainImpl::CreateGpuService(
gpu::GpuProcessShmCount(std::move(use_shader_cache_shm_region)),
gpu_init_->TakeDefaultOffscreenSurface(), std::move(params),
dependencies_.sync_point_manager, dependencies_.shared_image_manager,
dependencies_.scheduler, dependencies_.shutdown_event);
dependencies_.scheduler, dependencies_.shutdown_event,
dependencies_.gr_context_options_provider);
#else
gpu_service_->InitializeWithHost(
gpu_host.Unbind(),

@ -102,6 +102,8 @@ class VizMainImpl : public mojom::VizMain {
raw_ptr<gpu::SharedImageManager> shared_image_manager = nullptr;
raw_ptr<gpu::Scheduler> scheduler = nullptr;
raw_ptr<VizCompositorThreadRunner> viz_compositor_thread_runner = nullptr;
raw_ptr<const gpu::SharedContextState::GrContextOptionsProvider>
gr_context_options_provider = nullptr;
#endif
};

@ -97,6 +97,8 @@ viz::VizMainImpl::ExternalDependencies CreateVizMainDependencies() {
deps.scheduler = GetContentClient()->gpu()->GetScheduler();
deps.viz_compositor_thread_runner =
GetContentClient()->gpu()->GetVizCompositorThreadRunner();
deps.gr_context_options_provider =
GetContentClient()->gpu()->GetGrContextOptionsProvider();
}
#endif

@ -34,6 +34,7 @@ target(link_target_type, "gpu_sources") {
"//content/gpu:gpu_sources",
"//content/public/common:common_sources",
"//gpu/command_buffer/service",
"//gpu/command_buffer/service:gles2",
"//gpu/config",
]

@ -23,6 +23,11 @@ viz::VizCompositorThreadRunner*
ContentGpuClient::GetVizCompositorThreadRunner() {
return nullptr;
}
const gpu::SharedContextState::GrContextOptionsProvider*
ContentGpuClient::GetGrContextOptionsProvider() {
return nullptr;
}
#endif
} // namespace content

@ -10,6 +10,7 @@
#include "build/buildflag.h"
#include "content/common/content_export.h"
#include "content/public/common/content_client.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "mojo/public/cpp/bindings/binder_map.h"
namespace gpu {
@ -57,6 +58,8 @@ class CONTENT_EXPORT ContentGpuClient {
virtual gpu::SharedImageManager* GetSharedImageManager();
virtual gpu::Scheduler* GetScheduler();
virtual viz::VizCompositorThreadRunner* GetVizCompositorThreadRunner();
virtual const gpu::SharedContextState::GrContextOptionsProvider*
GetGrContextOptionsProvider();
#endif
};

@ -368,7 +368,8 @@ SharedContextState::SharedContextState(
viz::MetalContextProvider* metal_context_provider,
DawnContextProvider* dawn_context_provider,
base::WeakPtr<gpu::MemoryTracker::Observer> peak_memory_monitor,
bool created_on_compositor_gpu_thread)
bool created_on_compositor_gpu_thread,
const GrContextOptionsProvider* gr_context_options_provider)
: use_virtualized_gl_contexts_(use_virtualized_gl_contexts),
context_lost_callback_(std::move(context_lost_callback)),
gr_context_type_(gr_context_type),
@ -378,6 +379,7 @@ SharedContextState::SharedContextState(
vk_context_provider_(vulkan_context_provider),
metal_context_provider_(metal_context_provider),
dawn_context_provider_(dawn_context_provider),
gr_context_options_provider_(gr_context_options_provider),
created_on_compositor_gpu_thread_(created_on_compositor_gpu_thread),
share_group_(std::move(share_group)),
context_(context),
@ -577,6 +579,10 @@ bool SharedContextState::InitializeGanesh(
if (gpu_preferences.force_max_texture_size)
options.fMaxTextureSizeOverride = gpu_preferences.force_max_texture_size;
if (gr_context_options_provider_) {
gr_context_options_provider_->SetCustomGrContextOptions(options);
}
if (gr_context_type_ == GrContextType::kGL) {
DCHECK(context_->IsCurrent(nullptr));
sk_sp<GrGLInterface> gr_gl_interface(gl::init::CreateGrGLInterface(

@ -10,6 +10,7 @@
#include <vector>
#include "base/containers/lru_cache.h"
#include "base/gtest_prod_util.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
@ -87,6 +88,16 @@ class GPU_GLES2_EXPORT SharedContextState
using ContextLostCallback =
base::OnceCallback<void(bool, error::ContextLostReason)>;
// This interface is used by the embedder to set custom GrContextOptions which
// are passed to Skia.
class GrContextOptionsProvider {
public:
~GrContextOptionsProvider() = default;
// The passed GrContextOptions will have the default fields set. The
// embedder may modify the options as needed.
virtual void SetCustomGrContextOptions(GrContextOptions& options) const = 0;
};
// TODO(vikassoni): Refactor code to have seperate constructor for GL and
// Vulkan and not initialize/use GL related info for vulkan and vice-versa.
SharedContextState(
@ -100,7 +111,9 @@ class GPU_GLES2_EXPORT SharedContextState
viz::MetalContextProvider* metal_context_provider = nullptr,
DawnContextProvider* dawn_context_provider = nullptr,
base::WeakPtr<gpu::MemoryTracker::Observer> peak_memory_monitor = nullptr,
bool created_on_compositor_gpu_thread = false);
bool created_on_compositor_gpu_thread = false,
const gpu::SharedContextState::GrContextOptionsProvider*
gr_context_options_provider = nullptr);
SharedContextState(const SharedContextState&) = delete;
SharedContextState& operator=(const SharedContextState&) = delete;
@ -285,6 +298,10 @@ class GPU_GLES2_EXPORT SharedContextState
private:
friend class base::RefCounted<SharedContextState>;
friend class raster::RasterDecoderTestBase;
FRIEND_TEST_ALL_PREFIXES(SharedContextStateTest,
GLOptionsProviderSetsCustomOptions);
FRIEND_TEST_ALL_PREFIXES(SharedContextStateTest,
VulkanOptionsProviderSetsCustomOptions);
// Observer which is notified when SkiaOutputSurfaceImpl takes ownership of a
// shared image, and forward information to both histograms and task manager.
@ -383,6 +400,8 @@ class GPU_GLES2_EXPORT SharedContextState
const raw_ptr<viz::VulkanContextProvider> vk_context_provider_ = nullptr;
const raw_ptr<viz::MetalContextProvider> metal_context_provider_ = nullptr;
const raw_ptr<DawnContextProvider> dawn_context_provider_ = nullptr;
raw_ptr<const GrContextOptionsProvider> gr_context_options_provider_ =
nullptr;
bool created_on_compositor_gpu_thread_ = false;
bool is_drdc_enabled_ = false;
raw_ptr<GrDirectContext, DanglingUntriaged> gr_context_ = nullptr;

@ -22,12 +22,14 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_context_stub.h"
#include "ui/gl/gl_mock.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface_stub.h"
#include "ui/gl/init/gl_factory.h"
#include "ui/gl/test/gl_surface_test_support.h"
using ::testing::_;
using ::testing::InSequence;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::StrictMock;
@ -39,6 +41,15 @@ class SharedContextStateTest : public ::testing::Test {
SharedContextStateTest() = default;
};
class MockGrContextOptionsProvider
: public SharedContextState::GrContextOptionsProvider {
public:
MOCK_METHOD(void,
SetCustomGrContextOptions,
(GrContextOptions & options),
(const, override));
};
TEST_F(SharedContextStateTest, InitFailsIfLostContext) {
const ContextType context_type = CONTEXT_TYPE_OPENGLES2;
@ -100,4 +111,88 @@ TEST_F(SharedContextStateTest, InitFailsIfLostContext) {
gl::GLSurfaceTestSupport::ShutdownGL(display);
}
TEST_F(SharedContextStateTest, GLOptionsProviderSetsCustomOptions) {
gl::SetGLGetProcAddressProc(gl::MockGLInterface::GetGLProcAddress);
auto* display = gl::GLSurfaceTestSupport::InitializeOneOffWithMockBindings();
ASSERT_TRUE(display);
{
NiceMock<gl::MockGLInterface> gl_interface;
gl::MockGLInterface::SetGLInterface(&gl_interface);
InSequence sequence;
auto share_group = base::MakeRefCounted<gl::GLShareGroup>();
auto surface = base::MakeRefCounted<gl::GLSurfaceStub>();
auto context = base::MakeRefCounted<gl::GLContextStub>(share_group.get());
const char gl_version[] = "OpenGL ES 2.0";
context->SetGLVersionString(gl_version);
const char gl_extensions[] = "GL_KHR_robustness";
context->SetExtensionsString(gl_extensions);
// The stub ctx needs to be initialized so that the gl::GLContext can
// store the offscreen stub |surface|.
context->Initialize(surface.get(), {});
context->MakeCurrent(surface.get());
GpuDriverBugWorkarounds workarounds;
auto shared_context_state = base::MakeRefCounted<SharedContextState>(
share_group.get(), surface, context,
false /* use_virtualized_gl_contexts */, base::DoNothing(),
GrContextType::kGL);
StrictMock<MockGrContextOptionsProvider> provider;
shared_context_state->gr_context_options_provider_ = &provider;
EXPECT_CALL(provider, SetCustomGrContextOptions(_))
.Times(1)
.RetiresOnSaturation();
shared_context_state->InitializeGanesh(
GpuPreferences(), workarounds, /*cache=*/nullptr,
/*use_shader_cache_shm_count=*/nullptr, /*progress_reporter=*/nullptr);
}
gl::GLSurfaceTestSupport::ShutdownGL(display);
}
TEST_F(SharedContextStateTest, VulkanOptionsProviderSetsCustomOptions) {
gl::SetGLGetProcAddressProc(gl::MockGLInterface::GetGLProcAddress);
auto* display = gl::GLSurfaceTestSupport::InitializeOneOffWithMockBindings();
ASSERT_TRUE(display);
{
NiceMock<gl::MockGLInterface> gl_interface;
gl::MockGLInterface::SetGLInterface(&gl_interface);
// This line and passing kVulkan into InitializeGanesh should ensure we go
// down the Vulkan code path.
gl::SetGLImplementationParts(
gl::GLImplementationParts(gl::ANGLEImplementation::kVulkan));
InSequence sequence;
auto share_group = base::MakeRefCounted<gl::GLShareGroup>();
auto surface = base::MakeRefCounted<gl::GLSurfaceStub>();
auto context = base::MakeRefCounted<gl::GLContextStub>(share_group.get());
const char gl_version[] = "OpenGL ES 2.0";
context->SetGLVersionString(gl_version);
const char gl_extensions[] = "GL_KHR_robustness";
context->SetExtensionsString(gl_extensions);
// The stub ctx needs to be initialized so that the gl::GLContext can
// store the offscreen stub |surface|.
context->Initialize(surface.get(), {});
context->MakeCurrent(surface.get());
GpuDriverBugWorkarounds workarounds;
auto shared_context_state = base::MakeRefCounted<SharedContextState>(
share_group.get(), surface, context,
false /* use_virtualized_gl_contexts */, base::DoNothing(),
GrContextType::kVulkan);
StrictMock<MockGrContextOptionsProvider> provider;
shared_context_state->gr_context_options_provider_ = &provider;
EXPECT_CALL(provider, SetCustomGrContextOptions(_))
.Times(1)
.RetiresOnSaturation();
shared_context_state->InitializeGanesh(
GpuPreferences(), workarounds, /*cache=*/nullptr,
/*use_shader_cache_shm_count=*/nullptr, /*progress_reporter=*/nullptr);
}
gl::GLSurfaceTestSupport::ShutdownGL(display);
}
} // namespace gpu

@ -342,7 +342,9 @@ GpuChannelManager::GpuChannelManager(
viz::VulkanContextProvider* vulkan_context_provider,
viz::MetalContextProvider* metal_context_provider,
DawnContextProvider* dawn_context_provider,
webgpu::DawnCachingInterfaceFactory* dawn_caching_interface_factory)
webgpu::DawnCachingInterfaceFactory* dawn_caching_interface_factory,
const SharedContextState::GrContextOptionsProvider*
gr_context_options_provider)
: task_runner_(task_runner),
io_task_runner_(io_task_runner),
gpu_preferences_(gpu_preferences),
@ -370,7 +372,8 @@ GpuChannelManager::GpuChannelManager(
vulkan_context_provider_(vulkan_context_provider),
metal_context_provider_(metal_context_provider),
dawn_context_provider_(dawn_context_provider),
peak_memory_monitor_(this, task_runner) {
peak_memory_monitor_(this, task_runner),
gr_context_options_provider_(gr_context_options_provider) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(task_runner->BelongsToCurrentThread());
DCHECK(io_task_runner);
@ -1003,7 +1006,8 @@ scoped_refptr<SharedContextState> GpuChannelManager::GetSharedContextState(
context_lost_count_ + 1),
gpu_preferences_.gr_context_type, vulkan_context_provider_,
metal_context_provider_, dawn_context_provider_,
peak_memory_monitor_.GetWeakPtr());
peak_memory_monitor_.GetWeakPtr(),
/*created_on_compositor_gpu_thread=*/false, gr_context_options_provider_);
// Initialize GL context, so Vulkan and GL interop can work properly.
auto feature_info = base::MakeRefCounted<gles2::FeatureInfo>(

@ -111,7 +111,9 @@ class GPU_IPC_SERVICE_EXPORT GpuChannelManager
viz::MetalContextProvider* metal_context_provider = nullptr,
DawnContextProvider* dawn_context_provider = nullptr,
webgpu::DawnCachingInterfaceFactory* dawn_caching_interface_factory =
nullptr);
nullptr,
const SharedContextState::GrContextOptionsProvider*
gr_context_options_provider = nullptr);
GpuChannelManager(const GpuChannelManager&) = delete;
GpuChannelManager& operator=(const GpuChannelManager&) = delete;
@ -405,6 +407,9 @@ class GPU_IPC_SERVICE_EXPORT GpuChannelManager
GpuPeakMemoryMonitor peak_memory_monitor_;
raw_ptr<const SharedContextState::GrContextOptionsProvider>
gr_context_options_provider_ = nullptr;
// Creation time of GpuChannelManger.
const base::TimeTicks creation_time_ = base::TimeTicks::Now();