Commit 8c5a694e authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

Make SkiaRenderer work with Android WebView.

Known issues:
 * flickers on the search result page.
 * webview becomes blank after rotation.
 * rendering to fbo doesn't work

Bug: 919865
Change-Id: I577b2df1c48320c11be4397c10595db748f02b79
Reviewed-on: https://chromium-review.googlesource.com/c/1440072
Commit-Queue: Peng Huang <penghuang@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#628233}
parent 8e9236f4
......@@ -35,6 +35,7 @@ include_rules = [
"+components/visitedlink/browser",
"+components/viz/common",
"+components/viz/service/display",
"+components/viz/service/display_embedder",
"+components/viz/service/frame_sinks",
"+components/viz/test",
"+components/webdata/common",
......
......@@ -8,7 +8,7 @@
namespace android_webview {
AwGLSurface::AwGLSurface() {}
AwGLSurface::AwGLSurface() : size_(1, 1) {}
AwGLSurface::~AwGLSurface() {}
......@@ -29,7 +29,7 @@ gfx::SwapResult AwGLSurface::SwapBuffers(PresentationCallback callback) {
}
gfx::Size AwGLSurface::GetSize() {
return gfx::Size(1, 1);
return size_;
}
void* AwGLSurface::GetHandle() {
......@@ -44,4 +44,12 @@ gl::GLSurfaceFormat AwGLSurface::GetFormat() {
return gl::GLSurfaceFormat();
}
bool AwGLSurface::Resize(const gfx::Size& size,
float scale_factor,
ColorSpace color_space,
bool has_alpha) {
size_ = size;
return true;
}
} // namespace android_webview
......@@ -26,11 +26,16 @@ class AwGLSurface : public gl::GLSurface {
void* GetHandle() override;
void* GetDisplay() override;
gl::GLSurfaceFormat GetFormat() override;
bool Resize(const gfx::Size& size,
float scale_factor,
ColorSpace color_space,
bool has_alpha) override;
protected:
~AwGLSurface() override;
private:
gfx::Size size_;
DISALLOW_COPY_AND_ASSIGN(AwGLSurface);
};
......
......@@ -14,17 +14,23 @@
#include "android_webview/browser/parent_output_surface.h"
#include "base/stl_util.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display/display_scheduler.h"
#include "components/viz/service/display_embedder/skia_output_surface_impl.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/transform.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/init/gl_factory.h"
namespace android_webview {
......@@ -33,6 +39,11 @@ namespace {
// from RenderWidgetHostImpl.
constexpr uint32_t kDefaultClientId = 0u;
SurfacesInstance* g_surfaces_instance = nullptr;
void OnContextLost() {
NOTREACHED() << "Non owned context lost!";
}
} // namespace
// static
......@@ -54,12 +65,14 @@ SurfacesInstance::SurfacesInstance()
// Webview does not own the surface so should not clear it.
settings.should_clear_root_render_pass = false;
settings.use_skia_renderer = features::IsUsingSkiaRenderer();
// The SharedBitmapManager is null as we do not support or use software
// compositing on Android.
frame_sink_manager_ = std::make_unique<viz::FrameSinkManagerImpl>(
/*shared_bitmap_manager=*/nullptr);
parent_local_surface_id_allocator_.reset(
new viz::ParentLocalSurfaceIdAllocator());
parent_local_surface_id_allocator_ =
std::make_unique<viz::ParentLocalSurfaceIdAllocator>();
constexpr bool is_root = true;
constexpr bool needs_sync_points = true;
......@@ -67,19 +80,47 @@ SurfacesInstance::SurfacesInstance()
this, frame_sink_manager_.get(), frame_sink_id_, is_root,
needs_sync_points);
begin_frame_source_.reset(new viz::StubBeginFrameSource);
std::unique_ptr<ParentOutputSurface> output_surface_holder(
new ParentOutputSurface(AwRenderThreadContextProvider::Create(
base::WrapRefCounted(new AwGLSurface),
DeferredGpuCommandService::GetInstance())));
output_surface_ = output_surface_holder.get();
std::unique_ptr<viz::OutputSurface> output_surface;
viz::SkiaOutputSurface* skia_output_surface = nullptr;
if (settings.use_skia_renderer) {
auto* task_executor = DeferredGpuCommandService::GetInstance();
if (!shared_context_state_) {
auto surface = base::MakeRefCounted<AwGLSurface>();
auto gl_context =
gl::init::CreateGLContext(task_executor->share_group().get(),
surface.get(), gl::GLContextAttribs());
gl_context->MakeCurrent(surface.get());
shared_context_state_ = base::MakeRefCounted<gpu::SharedContextState>(
task_executor->share_group(), std::move(surface),
std::move(gl_context), false /* use_virtualized_gl_contexts */,
base::BindOnce(&OnContextLost),
nullptr /* vulkan_context_provider */);
shared_context_state_->InitializeGrContext(
gpu::GpuDriverBugWorkarounds(task_executor->gpu_feature_info()
.enabled_gpu_driver_bug_workarounds),
nullptr /* gr_shader_cache */);
}
output_surface = std::make_unique<viz::SkiaOutputSurfaceImpl>(
task_executor, base::MakeRefCounted<AwGLSurface>(),
shared_context_state_);
skia_output_surface =
static_cast<viz::SkiaOutputSurface*>(output_surface.get());
} else {
auto context_provider = AwRenderThreadContextProvider::Create(
base::MakeRefCounted<AwGLSurface>(),
DeferredGpuCommandService::GetInstance());
output_surface =
std::make_unique<ParentOutputSurface>(std::move(context_provider));
}
begin_frame_source_ = std::make_unique<viz::StubBeginFrameSource>();
auto scheduler = std::make_unique<viz::DisplayScheduler>(
begin_frame_source_.get(), nullptr /* current_task_runner */,
output_surface_holder->capabilities().max_frames_pending);
output_surface->capabilities().max_frames_pending);
display_ = std::make_unique<viz::Display>(
nullptr /* shared_bitmap_manager */, settings, frame_sink_id_,
std::move(output_surface_holder), std::move(scheduler),
nullptr /* current_task_runner */);
std::move(output_surface), std::move(scheduler),
nullptr /* current_task_runner */, skia_output_surface);
display_->Initialize(this, frame_sink_manager_->surface_manager(),
false /* enable_shared_images */);
frame_sink_manager_->RegisterBeginFrameSource(begin_frame_source_.get(),
......@@ -95,6 +136,8 @@ SurfacesInstance::~SurfacesInstance() {
DCHECK_EQ(g_surfaces_instance, this);
frame_sink_manager_->UnregisterBeginFrameSource(begin_frame_source_.get());
g_surfaces_instance = nullptr;
display_ = nullptr;
DCHECK(!shared_context_state_ || shared_context_state_->HasOneRef());
DCHECK(child_ids_.empty());
}
......@@ -169,6 +212,10 @@ void SurfacesInstance::DrawAndSwap(const gfx::Size& viewport,
support_->SubmitCompositorFrame(root_id_allocation_.local_surface_id(),
std::move(frame));
if (shared_context_state_) {
// GL state could be changed across frames, so we need reset GrContext.
shared_context_state_->PessimisticallyResetGrContext();
}
display_->Resize(viewport);
display_->DrawAndSwap();
display_->DidReceiveSwapBuffersAck();
......
......@@ -23,18 +23,19 @@ class Size;
class Transform;
}
namespace gpu {
class SharedContextState;
}
namespace viz {
class BeginFrameSource;
class CompositorFrameSinkSupport;
class Display;
class FrameSinkManagerImpl;
class ParentLocalSurfaceIdAllocator;
} // namespace viz
namespace android_webview {
class ParentOutputSurface;
class SurfacesInstance : public base::RefCounted<SurfacesInstance>,
public viz::DisplayClient,
public viz::mojom::CompositorFrameSinkClient {
......@@ -102,11 +103,10 @@ class SurfacesInstance : public base::RefCounted<SurfacesInstance>,
std::vector<viz::SurfaceId> child_ids_;
viz::FrameTokenGenerator next_frame_token_;
// This is owned by |display_|.
ParentOutputSurface* output_surface_;
gfx::Size surface_size_;
scoped_refptr<gpu::SharedContextState> shared_context_state_;
DISALLOW_COPY_AND_ASSIGN(SurfacesInstance);
};
......
......@@ -4,6 +4,7 @@
#include "components/viz/service/display_embedder/skia_output_surface_impl.h"
#include <memory>
#include <utility>
#include <vector>
......@@ -23,6 +24,7 @@
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
#include "gpu/command_buffer/service/scheduler.h"
#include "gpu/command_buffer/service/shared_image_representation.h"
#include "gpu/ipc/command_buffer_task_executor.h"
#include "third_party/skia/include/core/SkYUVAIndex.h"
#include "ui/gfx/skia_util.h"
#include "ui/gl/gl_bindings.h"
......@@ -45,6 +47,8 @@ template <typename... Args>
base::RepeatingCallback<void(Args...)> CreateSafeCallback(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const base::RepeatingCallback<void(Args...)>& callback) {
if (!task_runner)
return callback;
return base::BindRepeating(&PostAsyncTask<Args...>, task_runner, callback);
}
......@@ -291,6 +295,20 @@ SkiaOutputSurfaceImpl::SkiaOutputSurfaceImpl(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
SkiaOutputSurfaceImpl::SkiaOutputSurfaceImpl(
scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor,
scoped_refptr<gl::GLSurface> gl_surface,
scoped_refptr<gpu::SharedContextState> shared_context_state)
: gpu_service_(nullptr),
task_executor_(std::move(task_executor)),
gl_surface_(std::move(gl_surface)),
shared_context_state_(std::move(shared_context_state)),
is_using_vulkan_(false),
surface_handle_(gpu::kNullSurfaceHandle),
synthetic_begin_frame_source_(nullptr),
show_overdraw_feedback_(false),
weak_ptr_factory_(this) {}
SkiaOutputSurfaceImpl::~SkiaOutputSurfaceImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
recorder_.reset();
......@@ -311,8 +329,12 @@ void SkiaOutputSurfaceImpl::BindToClient(OutputSurfaceClient* client) {
client_ = client;
weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
client_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
if (task_executor_) {
DCHECK(!sequence_);
sequence_ = task_executor_->CreateSequence();
} else {
client_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
}
base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
auto callback = base::BindOnce(&SkiaOutputSurfaceImpl::InitializeOnGpuThread,
......@@ -572,12 +594,12 @@ gpu::SyncToken SkiaOutputSurfaceImpl::SubmitPaint() {
callback = base::BindOnce(
&SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
base::Unretained(impl_on_gpu_.get()), current_render_pass_id_,
std::move(ddl), sync_fence_release_);
std::move(ddl), resource_sync_tokens_, sync_fence_release_);
} else {
callback =
base::BindOnce(&SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame,
base::Unretained(impl_on_gpu_.get()), std::move(ddl),
std::move(overdraw_ddl), sync_fence_release_);
callback = base::BindOnce(
&SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame,
base::Unretained(impl_on_gpu_.get()), std::move(ddl),
std::move(overdraw_ddl), resource_sync_tokens_, sync_fence_release_);
}
ScheduleGpuTask(std::move(callback), std::move(resource_sync_tokens_));
current_render_pass_id_ = 0;
......@@ -637,20 +659,36 @@ void SkiaOutputSurfaceImpl::RemoveContextLostObserver(
}
void SkiaOutputSurfaceImpl::InitializeOnGpuThread(base::WaitableEvent* event) {
base::ScopedClosureRunner scoped_runner(
base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event)));
base::Optional<base::ScopedClosureRunner> scoped_runner;
if (event) {
scoped_runner.emplace(
base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event)));
}
auto did_swap_buffer_complete_callback = base::BindRepeating(
&SkiaOutputSurfaceImpl::DidSwapBuffersComplete, weak_ptr_);
did_swap_buffer_complete_callback = CreateSafeCallback(
client_thread_task_runner_, did_swap_buffer_complete_callback);
auto buffer_presented_callback =
base::BindRepeating(&SkiaOutputSurfaceImpl::BufferPresented, weak_ptr_);
buffer_presented_callback =
CreateSafeCallback(client_thread_task_runner_, buffer_presented_callback);
auto context_lost_callback =
base::BindRepeating(&SkiaOutputSurfaceImpl::ContextLost, weak_ptr_);
impl_on_gpu_ = std::make_unique<SkiaOutputSurfaceImplOnGpu>(
gpu_service_, surface_handle_,
CreateSafeCallback(client_thread_task_runner_,
did_swap_buffer_complete_callback),
CreateSafeCallback(client_thread_task_runner_, buffer_presented_callback),
CreateSafeCallback(client_thread_task_runner_, context_lost_callback));
context_lost_callback =
CreateSafeCallback(client_thread_task_runner_, context_lost_callback);
if (task_executor_) {
impl_on_gpu_ = std::make_unique<SkiaOutputSurfaceImplOnGpu>(
task_executor_.get(), std::move(gl_surface_),
std::move(shared_context_state_), sequence_->GetSequenceId(),
did_swap_buffer_complete_callback, buffer_presented_callback,
context_lost_callback);
} else {
impl_on_gpu_ = std::make_unique<SkiaOutputSurfaceImplOnGpu>(
gpu_service_, surface_handle_, did_swap_buffer_complete_callback,
buffer_presented_callback, context_lost_callback);
}
capabilities_ = impl_on_gpu_->capabilities();
}
......@@ -734,9 +772,13 @@ void SkiaOutputSurfaceImpl::ContextLost() {
void SkiaOutputSurfaceImpl::ScheduleGpuTask(
base::OnceClosure callback,
std::vector<gpu::SyncToken> sync_tokens) {
auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
sequence_id, std::move(callback), std::move(sync_tokens)));
if (gpu_service_) {
auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
sequence_id, std::move(callback), std::move(sync_tokens)));
} else {
sequence_->ScheduleTask(std::move(callback), std::move(sync_tokens));
}
}
} // namespace viz
......@@ -22,6 +22,15 @@ namespace base {
class WaitableEvent;
}
namespace gl {
class GLSurface;
}
namespace gpu {
class CommandBufferTaskExecutor;
class SharedContextState;
} // namespace gpu
namespace viz {
class GpuServiceImpl;
......@@ -44,6 +53,10 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
gpu::SurfaceHandle surface_handle,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
bool show_overdraw_feedback);
SkiaOutputSurfaceImpl(
scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor,
scoped_refptr<gl::GLSurface> gl_surface,
scoped_refptr<gpu::SharedContextState> shared_context_state);
~SkiaOutputSurfaceImpl() override;
// OutputSurface implementation:
......@@ -121,7 +134,15 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
std::vector<gpu::SyncToken> sync_tokens);
uint64_t sync_fence_release_ = 0;
GpuServiceImpl* const gpu_service_;
// Stuffs for running with |task_executor_| instead of |gpu_service_|.
scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor_;
scoped_refptr<gl::GLSurface> gl_surface_;
scoped_refptr<gpu::SharedContextState> shared_context_state_;
std::unique_ptr<gpu::CommandBufferTaskExecutor::Sequence> sequence_;
const bool is_using_vulkan_;
const gpu::SurfaceHandle surface_handle_;
SyntheticBeginFrameSource* const synthetic_begin_frame_source_;
......
......@@ -43,6 +43,7 @@ class GLSurface;
}
namespace gpu {
class CommandBufferTaskExecutor;
class SyncPointClientState;
class SharedImageRepresentationSkia;
......@@ -89,6 +90,15 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback,
const BufferPresentedCallback& buffer_presented_callback,
const ContextLostCallback& context_lost_callback);
SkiaOutputSurfaceImplOnGpu(
gpu::CommandBufferTaskExecutor* task_executor,
scoped_refptr<gl::GLSurface> gl_surface,
scoped_refptr<gpu::SharedContextState> shared_context_state,
gpu::SequenceId sequence_id,
const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback,
const BufferPresentedCallback& buffer_presented_callback,
const ContextLostCallback& context_lost_callback);
~SkiaOutputSurfaceImplOnGpu() override;
gpu::CommandBufferId command_buffer_id() const {
......@@ -111,12 +121,13 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
void FinishPaintCurrentFrame(
std::unique_ptr<SkDeferredDisplayList> ddl,
std::unique_ptr<SkDeferredDisplayList> overdraw_ddl,
std::vector<gpu::SyncToken> sync_tokens,
uint64_t sync_fence_release);
void SwapBuffers(OutputSurfaceFrame frame);
void FinishPaintRenderPass(
RenderPassId id,
std::unique_ptr<SkDeferredDisplayList> ddl,
uint64_t sync_fence_release);
void FinishPaintRenderPass(RenderPassId id,
std::unique_ptr<SkDeferredDisplayList> ddl,
std::vector<gpu::SyncToken> sync_tokens,
uint64_t sync_fence_release);
void RemoveRenderPassResource(std::vector<RenderPassId> ids);
void CopyOutput(RenderPassId id,
const gfx::Rect& copy_rect,
......@@ -159,7 +170,11 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
void AddFilter(IPC::MessageFilter* message_filter) override;
int32_t GetRouteID() const override;
void InitializeForGL(GpuServiceImpl* gpu_service);
void InitializeForGL();
void InitializeForGLWithGpuService(GpuServiceImpl* gpu_service);
void InitializeForGLWithTaskExecutor(
gpu::CommandBufferTaskExecutor* task_executor,
scoped_refptr<gl::GLSurface> gl_surface);
void InitializeForVulkan(GpuServiceImpl* gpu_service);
void BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base);
......@@ -167,12 +182,17 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
// Generage the next swap ID and push it to our pending swap ID queues.
void OnSwapBuffers();
void CreateSkSurfaceForGL();
void CreateSkSurfaceForVulkan();
// Make context current for GL, and return false if the context is lost.
// It will do nothing when Vulkan is used.
bool MakeCurrent();
void PullTextureUpdates(std::vector<gpu::SyncToken> sync_token);
void ReleaseFenceSyncAndPushTextureUpdates(uint64_t sync_fence_release);
GrContext* gr_context() { return context_state_->gr_context(); }
SkColorType FramebufferColorType() {
......@@ -199,7 +219,10 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
#endif
gpu::GpuPreferences gpu_preferences_;
gfx::Size size_;
gfx::ColorSpace color_space_;
scoped_refptr<gl::GLSurface> gl_surface_;
unsigned int backing_framebuffer_object_ = 0;
sk_sp<SkSurface> sk_surface_;
scoped_refptr<gpu::SharedContextState> context_state_;
const gl::GLVersionInfo* gl_version_info_ = nullptr;
......
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