Commit 304eff1e authored by Eric Karl's avatar Eric Karl Committed by Commit Bot

Android OOP-D: Add low-bit-depth handling to InProcessCommandBuffer

InProcessCommandBuffer doesn't currently handle dropping to 565
low-bit-depth on low-end Android. This CL adds this logic.

To safely handle low bit depth and virtualized contexts, we need
to know whether our target bit depth is compatible with the default
offscreen context. This change passes the surface format of this
context through CommandBufferTaskExecutor to allow this to be queried
from InProcessCommandBuffer.

Finally, as error-handling for the creation of the offscreen surface
is currently a bit scattered, this CL simplifies things by creating
this surface during init and passing it in to GpuChannelManager, so
any callers can just assume success.

BUG=868476

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I8ffaa05e2ebbf6e910e76a8ef75095edf1cd3fe5
Reviewed-on: https://chromium-review.googlesource.com/1150966Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Commit-Queue: Eric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#578796}
parent c7e6f72b
......@@ -85,7 +85,8 @@ DeferredGpuCommandService::DeferredGpuCommandService(
: gpu::CommandBufferTaskExecutor(gpu_preferences,
gpu_feature_info,
nullptr,
nullptr),
nullptr,
gl::GLSurfaceFormat()),
sync_point_manager_(std::make_unique<gpu::SyncPointManager>()),
gpu_info_(gpu_info) {}
......
......@@ -44,6 +44,7 @@
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/viz/privileged/interfaces/gl/gpu_host.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/init/gl_factory.h"
namespace cc {
......@@ -255,10 +256,14 @@ void PixelTest::SetUpGpuServiceOnGpuThread(base::WaitableEvent* event) {
mojo::MakeRequest(&gpu_host_proxy));
gpu_service_->InitializeWithHost(
std::move(gpu_host_proxy), gpu::GpuProcessActivityFlags(),
gl::init::CreateOffscreenGLSurface(gfx::Size()),
nullptr /* sync_point_manager */, nullptr /* shutdown_event */);
task_executor_ = base::MakeRefCounted<gpu::GpuInProcessThreadService>(
gpu_thread_->task_runner(), gpu_service_->sync_point_manager(),
gpu_service_->mailbox_manager(), gpu_service_->share_group(),
gpu_service_->gpu_channel_manager()
->default_offscreen_surface()
->GetFormat(),
gpu_service_->gpu_feature_info(),
gpu_service_->gpu_channel_manager()->gpu_preferences());
event->Signal();
......
......@@ -198,7 +198,7 @@ GpuServiceImpl::~GpuServiceImpl() {
continue;
if (!data.gl_context ||
!data.gl_context->MakeCurrent(
gpu_channel_manager_->GetDefaultOffscreenSurface())) {
gpu_channel_manager_->default_offscreen_surface())) {
LOG(ERROR) << "Failed to make current.";
data.gr_context->abandonContext();
}
......@@ -240,6 +240,7 @@ void GpuServiceImpl::UpdateGPUInfo() {
void GpuServiceImpl::InitializeWithHost(
mojom::GpuHostPtr gpu_host,
gpu::GpuProcessActivityFlags activity_flags,
scoped_refptr<gl::GLSurface> default_offscreen_surface,
gpu::SyncPointManager* sync_point_manager,
base::WaitableEvent* shutdown_event) {
DCHECK(main_runner_->BelongsToCurrentThread());
......@@ -283,7 +284,8 @@ void GpuServiceImpl::InitializeWithHost(
gpu_channel_manager_.reset(new gpu::GpuChannelManager(
gpu_preferences_, this, watchdog_thread_.get(), main_runner_, io_runner_,
scheduler_.get(), sync_point_manager_, gpu_memory_buffer_factory_.get(),
gpu_feature_info_, std::move(activity_flags)));
gpu_feature_info_, std::move(activity_flags),
std::move(default_offscreen_surface)));
media_gpu_channel_manager_.reset(
new media::MediaGpuChannelManager(gpu_channel_manager_.get()));
......
......@@ -77,8 +77,10 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
void UpdateGPUInfo();
void InitializeWithHost(mojom::GpuHostPtr gpu_host,
void InitializeWithHost(
mojom::GpuHostPtr gpu_host,
gpu::GpuProcessActivityFlags activity_flags,
scoped_refptr<gl::GLSurface> default_offscreen_surface,
gpu::SyncPointManager* sync_point_manager = nullptr,
base::WaitableEvent* shutdown_event = nullptr);
void Bind(mojom::GpuServiceRequest request);
......
......@@ -256,6 +256,7 @@ void VizMainImpl::CreateGpuService(
gpu_service_->InitializeWithHost(
std::move(gpu_host),
gpu::GpuProcessActivityFlags(std::move(activity_flags)),
gpu_init_->TakeDefaultOffscreenSurface(),
dependencies_.sync_point_manager, dependencies_.shutdown_event);
if (!pending_frame_sink_manager_params_.is_null()) {
......@@ -300,6 +301,9 @@ void VizMainImpl::CreateFrameSinkManagerInternal(
task_executor_ = base::MakeRefCounted<gpu::GpuInProcessThreadService>(
gpu_thread_task_runner_, gpu_service_->sync_point_manager(),
gpu_service_->mailbox_manager(), gpu_service_->share_group(),
gpu_service_->gpu_channel_manager()
->default_offscreen_surface()
->GetFormat(),
gpu_service_->gpu_feature_info(),
gpu_service_->gpu_channel_manager()->gpu_preferences());
......
......@@ -16,11 +16,13 @@ CommandBufferTaskExecutor::CommandBufferTaskExecutor(
const GpuPreferences& gpu_preferences,
const GpuFeatureInfo& gpu_feature_info,
MailboxManager* mailbox_manager,
scoped_refptr<gl::GLShareGroup> share_group)
scoped_refptr<gl::GLShareGroup> share_group,
gl::GLSurfaceFormat share_group_surface_format)
: gpu_preferences_(gpu_preferences),
gpu_feature_info_(gpu_feature_info),
mailbox_manager_(mailbox_manager),
share_group_(share_group),
share_group_surface_format_(share_group_surface_format),
shader_translator_cache_(gpu_preferences_) {
if (!mailbox_manager_) {
// TODO(piman): have embedders own the mailbox manager.
......
......@@ -18,6 +18,7 @@
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/ipc/gl_in_process_context_export.h"
#include "ui/gl/gl_surface_format.h"
namespace gl {
class GLShareGroup;
......@@ -40,7 +41,8 @@ class GL_IN_PROCESS_CONTEXT_EXPORT CommandBufferTaskExecutor
CommandBufferTaskExecutor(const GpuPreferences& gpu_preferences,
const GpuFeatureInfo& gpu_feature_info,
MailboxManager* mailbox_manager,
scoped_refptr<gl::GLShareGroup> share_group);
scoped_refptr<gl::GLShareGroup> share_group,
gl::GLSurfaceFormat share_group_surface_format);
// Queues a task to run as soon as possible.
virtual void ScheduleTask(base::OnceClosure task) = 0;
......@@ -58,6 +60,9 @@ class GL_IN_PROCESS_CONTEXT_EXPORT CommandBufferTaskExecutor
const GpuPreferences& gpu_preferences() const { return gpu_preferences_; }
const GpuFeatureInfo& gpu_feature_info() const { return gpu_feature_info_; }
scoped_refptr<gl::GLShareGroup> share_group();
gl::GLSurfaceFormat share_group_surface_format() const {
return share_group_surface_format_;
}
MailboxManager* mailbox_manager() { return mailbox_manager_; }
gles2::Outputter* outputter();
gles2::ProgramCache* program_cache();
......@@ -84,6 +89,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT CommandBufferTaskExecutor
MailboxManager* mailbox_manager_ = nullptr;
std::unique_ptr<gles2::Outputter> outputter_;
scoped_refptr<gl::GLShareGroup> share_group_;
gl::GLSurfaceFormat share_group_surface_format_;
std::unique_ptr<gles2::ProgramCache> program_cache_;
gles2::ImageManager image_manager_;
ServiceDiscardableManager discardable_manager_;
......
......@@ -13,12 +13,14 @@ GpuInProcessThreadService::GpuInProcessThreadService(
gpu::SyncPointManager* sync_point_manager,
gpu::MailboxManager* mailbox_manager,
scoped_refptr<gl::GLShareGroup> share_group,
gl::GLSurfaceFormat share_group_surface_format,
const GpuFeatureInfo& gpu_feature_info,
const GpuPreferences& gpu_preferences)
: gpu::CommandBufferTaskExecutor(gpu_preferences,
gpu_feature_info,
mailbox_manager,
share_group),
share_group,
share_group_surface_format),
task_runner_(task_runner),
sync_point_manager_(sync_point_manager) {}
......
......@@ -25,6 +25,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT GpuInProcessThreadService
gpu::SyncPointManager* sync_point_manager,
gpu::MailboxManager* mailbox_manager,
scoped_refptr<gl::GLShareGroup> share_group,
gl::GLSurfaceFormat share_group_surface_format,
const GpuFeatureInfo& gpu_feature_info,
const GpuPreferences& gpu_preferences);
......
......@@ -120,7 +120,7 @@ class GpuInProcessThreadHolder : public base::Thread {
CreateBufferUsageAndFormatExceptionList();
gpu_thread_service_ = base::MakeRefCounted<GpuInProcessThreadService>(
task_runner(), sync_point_manager_.get(), nullptr, nullptr,
gpu_feature_info_, gpu_preferences);
gl::GLSurfaceFormat(), gpu_feature_info_, gpu_preferences);
}
return gpu_thread_service_;
}
......@@ -336,6 +336,23 @@ gpu::ContextResult InProcessCommandBuffer::InitializeOnGpuThread(
}
} else {
gl::GLSurfaceFormat surface_format;
#if defined(OS_ANDROID)
// Handle Android low-bit-depth surface formats.
if (params.attribs.red_size <= 5 && params.attribs.green_size <= 6 &&
params.attribs.blue_size <= 5 && params.attribs.alpha_size == 0) {
// We hit this code path when creating the onscreen render context
// used for compositing on low-end Android devices.
surface_format.SetRGB565();
DVLOG(1) << __FUNCTION__ << ": Choosing RGB565 mode.";
}
if (!surface_format.IsCompatible(
task_executor_->share_group_surface_format())) {
use_virtualized_gl_context_ = false;
}
#endif
switch (params.attribs.color_space) {
case COLOR_SPACE_UNSPECIFIED:
surface_format.SetColorSpace(
......
......@@ -122,12 +122,7 @@ gpu::ContextResult GLES2CommandBufferStub::Initialize(
use_virtualized_gl_context_ |= manager->mailbox_manager()->UsesSync();
bool offscreen = (surface_handle_ == kNullSurfaceHandle);
gl::GLSurface* default_surface = manager->GetDefaultOffscreenSurface();
if (!default_surface) {
LOG(ERROR) << "ContextResult::kFatalFailure: "
"Failed to create default offscreen surface.";
return gpu::ContextResult::kFatalFailure;
}
gl::GLSurface* default_surface = manager->default_offscreen_surface();
// On low-spec Android devices, the default offscreen surface is
// RGB565, but WebGL rendering contexts still ask for RGBA8888 mode.
// That combination works for offscreen rendering, we can still use
......
......@@ -59,7 +59,8 @@ GpuChannelManager::GpuChannelManager(
SyncPointManager* sync_point_manager,
GpuMemoryBufferFactory* gpu_memory_buffer_factory,
const GpuFeatureInfo& gpu_feature_info,
GpuProcessActivityFlags activity_flags)
GpuProcessActivityFlags activity_flags,
scoped_refptr<gl::GLSurface> default_offscreen_surface)
: task_runner_(task_runner),
io_task_runner_(io_task_runner),
gpu_preferences_(gpu_preferences),
......@@ -72,6 +73,7 @@ GpuChannelManager::GpuChannelManager(
scheduler_(scheduler),
sync_point_manager_(sync_point_manager),
shader_translator_cache_(gpu_preferences_),
default_offscreen_surface_(std::move(default_offscreen_surface)),
gpu_memory_buffer_factory_(gpu_memory_buffer_factory),
gpu_feature_info_(gpu_feature_info),
exiting_for_lost_context_(false),
......@@ -219,14 +221,6 @@ void GpuChannelManager::DestroyAllChannels() {
gpu_channels_.clear();
}
gl::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() {
if (!default_offscreen_surface_.get()) {
default_offscreen_surface_ =
gl::init::CreateOffscreenGLSurface(gfx::Size());
}
return default_offscreen_surface_.get();
}
void GpuChannelManager::GetVideoMemoryUsageStats(
VideoMemoryUsageStats* video_memory_usage_stats) const {
// For each context group, assign its memory usage to its PID
......@@ -355,13 +349,7 @@ GpuChannelManager::GetRasterDecoderContextState(ContextResult* result) {
return raster_decoder_context_state_;
}
scoped_refptr<gl::GLSurface> surface = GetDefaultOffscreenSurface();
if (!surface) {
LOG(ERROR) << "Failed to create offscreen surface";
*result = ContextResult::kFatalFailure;
return nullptr;
}
scoped_refptr<gl::GLSurface> surface = default_offscreen_surface();
bool use_virtualized_gl_contexts = false;
#if defined(OS_MACOSX)
// Virtualize PreferIntegratedGpu contexts by default on OS X to prevent
......
......@@ -72,7 +72,8 @@ class GPU_IPC_SERVICE_EXPORT GpuChannelManager
SyncPointManager* sync_point_manager,
GpuMemoryBufferFactory* gpu_memory_buffer_factory,
const GpuFeatureInfo& gpu_feature_info,
GpuProcessActivityFlags activity_flags);
GpuProcessActivityFlags activity_flags,
scoped_refptr<gl::GLSurface> default_offscreen_surface);
~GpuChannelManager() override;
GpuChannelManagerDelegate* delegate() const { return delegate_; }
......@@ -119,7 +120,9 @@ class GPU_IPC_SERVICE_EXPORT GpuChannelManager
GpuChannel* LookupChannel(int32_t client_id) const;
gl::GLSurface* GetDefaultOffscreenSurface();
gl::GLSurface* default_offscreen_surface() const {
return default_offscreen_surface_.get();
}
GpuMemoryBufferFactory* gpu_memory_buffer_factory() {
return gpu_memory_buffer_factory_;
......
......@@ -76,20 +76,16 @@ GpuChannelTestCommon::GpuChannelTestCommon()
io_task_runner_(new base::TestSimpleTaskRunner),
sync_point_manager_(new SyncPointManager()),
scheduler_(new Scheduler(task_runner_, sync_point_manager_.get())),
channel_manager_delegate_(new TestGpuChannelManagerDelegate()),
channel_manager_(
new GpuChannelManager(GpuPreferences(),
channel_manager_delegate_.get(),
nullptr, /* watchdog */
task_runner_.get(),
io_task_runner_.get(),
scheduler_.get(),
sync_point_manager_.get(),
nullptr, /* gpu_memory_buffer_factory */
GpuFeatureInfo(),
GpuProcessActivityFlags())) {
channel_manager_delegate_(new TestGpuChannelManagerDelegate()) {
// We need GL bindings to actually initialize command buffers.
gl::GLSurfaceTestSupport::InitializeOneOffWithStubBindings();
channel_manager_.reset(new GpuChannelManager(
GpuPreferences(), channel_manager_delegate_.get(), nullptr, /* watchdog */
task_runner_.get(), io_task_runner_.get(), scheduler_.get(),
sync_point_manager_.get(), nullptr, /* gpu_memory_buffer_factory */
GpuFeatureInfo(), GpuProcessActivityFlags(),
gl::init::CreateOffscreenGLSurface(gfx::Size())));
}
GpuChannelTestCommon::~GpuChannelTestCommon() {
......
......@@ -24,6 +24,7 @@
#include "ui/gfx/switches.h"
#include "ui/gl/gl_features.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/init/gl_factory.h"
......@@ -271,6 +272,12 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line,
VLOG(1) << "gl::init::InitializeExtensionSettingsOneOffPlatform failed";
return false;
}
default_offscreen_surface_ =
gl::init::CreateOffscreenGLSurface(gfx::Size());
if (!default_offscreen_surface_) {
VLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
return false;
}
}
base::TimeDelta initialize_one_off_time =
......@@ -328,6 +335,8 @@ void GpuInit::InitializeInProcess(base::CommandLine* command_line,
InitializeGLThreadSafe(command_line, gpu_preferences_, &gpu_info_,
&gpu_feature_info_);
default_offscreen_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
}
#else
void GpuInit::InitializeInProcess(base::CommandLine* command_line,
......@@ -398,6 +407,11 @@ void GpuInit::InitializeInProcess(base::CommandLine* command_line,
if (!gl::init::InitializeExtensionSettingsOneOffPlatform()) {
VLOG(1) << "gl::init::InitializeExtensionSettingsOneOffPlatform failed";
}
default_offscreen_surface_ =
gl::init::CreateOffscreenGLSurface(gfx::Size());
if (!default_offscreen_surface_) {
VLOG(1) << "gl::init::CreateOffscreenGLSurface failed";
}
}
}
#endif // OS_ANDROID
......
......@@ -18,6 +18,10 @@ namespace base {
class CommandLine;
}
namespace gl {
class GLSurface;
}
namespace gpu {
class VulkanImplementation;
......@@ -62,6 +66,9 @@ class GPU_IPC_SERVICE_EXPORT GpuInit {
std::unique_ptr<GpuWatchdogThread> TakeWatchdogThread() {
return std::move(watchdog_thread_);
}
scoped_refptr<gl::GLSurface> TakeDefaultOffscreenSurface() {
return std::move(default_offscreen_surface_);
}
bool init_successful() const { return init_successful_; }
#if BUILDFLAG(ENABLE_VULKAN)
VulkanImplementation* vulkan_implementation() {
......@@ -77,6 +84,7 @@ class GPU_IPC_SERVICE_EXPORT GpuInit {
GPUInfo gpu_info_;
GpuFeatureInfo gpu_feature_info_;
GpuPreferences gpu_preferences_;
scoped_refptr<gl::GLSurface> default_offscreen_surface_;
bool init_successful_ = false;
// The following data are collected from hardware GPU and saved before
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment