Commit 30d67bce authored by Peng Huang's avatar Peng Huang Committed by Chromium LUCI CQ

Support using WebView with passthrough (ANGLE).

To support ANGLE, we need to create ANGLE context and surfaces from the
native EGL context and surfaces with the
EGL_ANGLE_external_context_and_surface extension. And ANGLE will save
and restore during make current or release the current context with
eglMakeCurrent() call. To do that, ScopedAppGLStateRestore will not
create gl::GLContext, save and restore GL state anymore. It only queries
stencil state with native GL binding instead of the ANGLE GL binding,
since ANGLE will not return the GL state from the native GL.
And SkiaRenderer may need the stencil state later. The ANGLE EGL context
will be created in OutputSurfaceProviderWebView, and make current in
HardwareRendererViz.

Bug: 1157501
Change-Id: Ieca9c85855df5ab529846fe2882d7451f50f51bb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2612925
Commit-Queue: Peng Huang <penghuang@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#846201}
parent 23b91ee4
...@@ -62,6 +62,8 @@ source_set("gfx") { ...@@ -62,6 +62,8 @@ source_set("gfx") {
"scoped_app_gl_state_restore.h", "scoped_app_gl_state_restore.h",
"scoped_app_gl_state_restore_impl.cc", "scoped_app_gl_state_restore_impl.cc",
"scoped_app_gl_state_restore_impl.h", "scoped_app_gl_state_restore_impl.h",
"scoped_app_gl_state_restore_impl_angle.cc",
"scoped_app_gl_state_restore_impl_angle.h",
"skia_output_surface_dependency_webview.cc", "skia_output_surface_dependency_webview.cc",
"skia_output_surface_dependency_webview.h", "skia_output_surface_dependency_webview.h",
"surfaces_instance.cc", "surfaces_instance.cc",
......
...@@ -7,14 +7,37 @@ ...@@ -7,14 +7,37 @@
#include <utility> #include <utility>
#include "android_webview/browser/gfx/scoped_app_gl_state_restore.h" #include "android_webview/browser/gfx/scoped_app_gl_state_restore.h"
#include "ui/gl/gl_bindings.h"
#define EGL_EXTERNAL_SURFACE_ANGLE 0x348F
namespace android_webview { namespace android_webview {
AwGLSurface::AwGLSurface() : size_(1, 1) {} AwGLSurface::AwGLSurface() = default;
AwGLSurface::~AwGLSurface() {
Destroy();
}
bool AwGLSurface::Initialize(gl::GLSurfaceFormat format) {
if (!IsANGLEExternalContextAndSurfaceSupported())
return true;
Destroy();
AwGLSurface::~AwGLSurface() {} EGLint attribs[] = {EGL_WIDTH, size_.width(), EGL_HEIGHT,
size_.height(), EGL_NONE, EGL_NONE};
surface_ = eglCreatePbufferFromClientBuffer(
GetDisplay(), EGL_EXTERNAL_SURFACE_ANGLE, nullptr, GetConfig(), attribs);
DCHECK_NE(surface_, EGL_NO_SURFACE);
return surface_ != EGL_NO_SURFACE;
}
void AwGLSurface::Destroy() { void AwGLSurface::Destroy() {
if (surface_) {
eglDestroySurface(GetDisplay(), surface_);
surface_ = nullptr;
}
} }
bool AwGLSurface::IsOffscreen() { bool AwGLSurface::IsOffscreen() {
...@@ -36,11 +59,13 @@ gfx::Size AwGLSurface::GetSize() { ...@@ -36,11 +59,13 @@ gfx::Size AwGLSurface::GetSize() {
} }
void* AwGLSurface::GetHandle() { void* AwGLSurface::GetHandle() {
return NULL; return surface_;
} }
void* AwGLSurface::GetDisplay() { void* AwGLSurface::GetDisplay() {
return NULL; if (!IsANGLEExternalContextAndSurfaceSupported())
return nullptr;
return gl::GLSurfaceEGL::GetDisplay();
} }
gl::GLSurfaceFormat AwGLSurface::GetFormat() { gl::GLSurfaceFormat AwGLSurface::GetFormat() {
...@@ -51,8 +76,11 @@ bool AwGLSurface::Resize(const gfx::Size& size, ...@@ -51,8 +76,11 @@ bool AwGLSurface::Resize(const gfx::Size& size,
float scale_factor, float scale_factor,
const gfx::ColorSpace& color_space, const gfx::ColorSpace& color_space,
bool has_alpha) { bool has_alpha) {
size_ = size; if (size_ == size)
return true; return true;
size_ = size;
return Initialize(gl::GLSurfaceFormat());
} }
void AwGLSurface::SetSize(const gfx::Size& size) { void AwGLSurface::SetSize(const gfx::Size& size) {
......
...@@ -8,18 +8,19 @@ ...@@ -8,18 +8,19 @@
#include "base/macros.h" #include "base/macros.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/transform.h" #include "ui/gfx/transform.h"
#include "ui/gl/gl_surface.h" #include "ui/gl/gl_surface_egl.h"
namespace android_webview { namespace android_webview {
// This surface is used to represent the underlying surface provided by the App // This surface is used to represent the underlying surface provided by the App
// inside a hardware draw. Note that offscreen contexts will not be using this // inside a hardware draw. Note that offscreen contexts will not be using this
// GLSurface. // GLSurface.
class AwGLSurface : public gl::GLSurface { class AwGLSurface : public gl::GLSurfaceEGL {
public: public:
AwGLSurface(); AwGLSurface();
// Implement GLSurface. // Implement GLSurface.
bool Initialize(gl::GLSurfaceFormat format) override;
void Destroy() override; void Destroy() override;
bool IsOffscreen() override; bool IsOffscreen() override;
unsigned int GetBackingFramebufferObject() override; unsigned int GetBackingFramebufferObject() override;
...@@ -45,7 +46,8 @@ class AwGLSurface : public gl::GLSurface { ...@@ -45,7 +46,8 @@ class AwGLSurface : public gl::GLSurface {
private: private:
PresentationCallback pending_presentation_callback_; PresentationCallback pending_presentation_callback_;
gfx::Size size_; gfx::Size size_{1, 1};
EGLSurface surface_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(AwGLSurface); DISALLOW_COPY_AND_ASSIGN(AwGLSurface);
}; };
......
...@@ -47,9 +47,22 @@ ...@@ -47,9 +47,22 @@
#include "ui/gfx/transform.h" #include "ui/gfx/transform.h"
#include "ui/gl/gl_context.h" #include "ui/gl/gl_context.h"
#include "ui/gl/gl_share_group.h" #include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/init/gl_factory.h" #include "ui/gl/init/gl_factory.h"
namespace android_webview { namespace android_webview {
namespace {
class ContextReleaser {
public:
explicit ContextReleaser(gpu::SharedContextState* state) : state_(state) {}
~ContextReleaser() { state_->ReleaseCurrent(nullptr); }
private:
gpu::SharedContextState* const state_;
};
} // namespace
class HardwareRendererViz::OnViz : public viz::DisplayClient { class HardwareRendererViz::OnViz : public viz::DisplayClient {
public: public:
...@@ -298,14 +311,8 @@ void HardwareRendererViz::InitializeOnViz( ...@@ -298,14 +311,8 @@ void HardwareRendererViz::InitializeOnViz(
HardwareRendererViz::~HardwareRendererViz() { HardwareRendererViz::~HardwareRendererViz() {
DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock( VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock(
base::BindOnce(&HardwareRendererViz::DestroyOnViz, base::BindOnce([](std::unique_ptr<OnViz>) {}, std::move(on_viz_)));
base::Unretained(this)));
}
void HardwareRendererViz::DestroyOnViz() {
on_viz_ = nullptr;
} }
bool HardwareRendererViz::IsUsingVulkan() const { bool HardwareRendererViz::IsUsingVulkan() const {
...@@ -320,6 +327,12 @@ void HardwareRendererViz::DrawAndSwap(const HardwareRendererDrawParams& params, ...@@ -320,6 +327,12 @@ void HardwareRendererViz::DrawAndSwap(const HardwareRendererDrawParams& params,
IsUsingVulkan()); IsUsingVulkan());
DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
// Release the context before returning, it is required for the external ANGLE
// context. For non-ANGLE case, fake context and surface are used, so
// releasing current context should be very cheap.
ContextReleaser context_releaser(
output_surface_provider_.shared_context_state().get());
viz::FrameTimingDetailsMap timing_details; viz::FrameTimingDetailsMap timing_details;
gfx::Transform transform(gfx::Transform::kSkipInitialization); gfx::Transform transform(gfx::Transform::kSkipInitialization);
...@@ -354,9 +367,13 @@ void HardwareRendererViz::DrawAndSwap(const HardwareRendererDrawParams& params, ...@@ -354,9 +367,13 @@ void HardwareRendererViz::DrawAndSwap(const HardwareRendererDrawParams& params,
output_surface_provider_.gl_surface()->RecalculateClipAndTransform( output_surface_provider_.gl_surface()->RecalculateClipAndTransform(
&viewport, &clip, &transform); &viewport, &clip, &transform);
// ANGLE will restore GL context state for us, so we don't need to call
// GrContext::resetContext().
if (gl::GLSurfaceEGL::IsANGLEExternalContextAndSurfaceSupported()) {
DCHECK(output_surface_provider_.shared_context_state()); DCHECK(output_surface_provider_.shared_context_state());
output_surface_provider_.shared_context_state() output_surface_provider_.shared_context_state()
->PessimisticallyResetGrContext(); ->PessimisticallyResetGrContext();
}
VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock( VizCompositorThreadRunnerWebView::GetInstance()->ScheduleOnVizAndBlock(
base::BindOnce(&HardwareRendererViz::OnViz::DrawAndSwapOnViz, base::BindOnce(&HardwareRendererViz::OnViz::DrawAndSwapOnViz,
......
...@@ -35,7 +35,6 @@ class HardwareRendererViz : public HardwareRenderer { ...@@ -35,7 +35,6 @@ class HardwareRendererViz : public HardwareRenderer {
class OnViz; class OnViz;
void InitializeOnViz(RootFrameSinkGetter root_frame_sink_getter); void InitializeOnViz(RootFrameSinkGetter root_frame_sink_getter);
void DestroyOnViz();
bool IsUsingVulkan() const; bool IsUsingVulkan() const;
// Information about last delegated frame. // Information about last delegated frame.
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "ui/base/ui_base_switches.h" #include "ui/base/ui_base_switches.h"
#include "ui/gl/gl_context.h" #include "ui/gl/gl_context.h"
#include "ui/gl/gl_share_group.h" #include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/init/gl_factory.h" #include "ui/gl/init/gl_factory.h"
namespace android_webview { namespace android_webview {
...@@ -80,7 +81,15 @@ OutputSurfaceProviderWebView::~OutputSurfaceProviderWebView() { ...@@ -80,7 +81,15 @@ OutputSurfaceProviderWebView::~OutputSurfaceProviderWebView() {
void OutputSurfaceProviderWebView::InitializeContext() { void OutputSurfaceProviderWebView::InitializeContext() {
DCHECK(!gl_surface_) << "InitializeContext() called twice"; DCHECK(!gl_surface_) << "InitializeContext() called twice";
// If EGL supports EGL_ANGLE_external_context_and_surface, then we will create
// an ANGLE context for the current native GL context.
const bool is_angle =
gl::GLSurfaceEGL::IsANGLEExternalContextAndSurfaceSupported();
// TODO(penghuang): should we support GLRenderer?
if (is_angle) {
CHECK(renderer_settings_.use_skia_renderer)
<< "GLRenderer doesn't work with ANGLE.";
}
if (renderer_settings_.use_skia_renderer && !enable_vulkan_) { if (renderer_settings_.use_skia_renderer && !enable_vulkan_) {
// We need to draw to FBO for External Stencil support with SkiaRenderer // We need to draw to FBO for External Stencil support with SkiaRenderer
gl_surface_ = base::MakeRefCounted<AwGLSurfaceExternalStencil>(); gl_surface_ = base::MakeRefCounted<AwGLSurfaceExternalStencil>();
...@@ -89,14 +98,21 @@ void OutputSurfaceProviderWebView::InitializeContext() { ...@@ -89,14 +98,21 @@ void OutputSurfaceProviderWebView::InitializeContext() {
gl_surface_ = base::MakeRefCounted<AwGLSurface>(); gl_surface_ = base::MakeRefCounted<AwGLSurface>();
} }
bool result = gl_surface_->Initialize(gl::GLSurfaceFormat());
DCHECK(result);
if (renderer_settings_.use_skia_renderer) { if (renderer_settings_.use_skia_renderer) {
auto share_group = base::MakeRefCounted<gl::GLShareGroup>(); auto share_group = base::MakeRefCounted<gl::GLShareGroup>();
gpu::GpuDriverBugWorkarounds workarounds( gpu::GpuDriverBugWorkarounds workarounds(
GpuServiceWebView::GetInstance() GpuServiceWebView::GetInstance()
->gpu_feature_info() ->gpu_feature_info()
.enabled_gpu_driver_bug_workarounds); .enabled_gpu_driver_bug_workarounds);
auto gl_context = gl::init::CreateGLContext( gl::GLContextAttribs attribs;
share_group.get(), gl_surface_.get(), gl::GLContextAttribs()); // For ANGLE EGL, we need to create ANGLE context from the current native
// EGL context.
attribs.angle_create_from_external_context = is_angle;
auto gl_context = gl::init::CreateGLContext(share_group.get(),
gl_surface_.get(), attribs);
gl_context->MakeCurrent(gl_surface_.get()); gl_context->MakeCurrent(gl_surface_.get());
shared_context_state_ = base::MakeRefCounted<gpu::SharedContextState>( shared_context_state_ = base::MakeRefCounted<gpu::SharedContextState>(
......
...@@ -7,7 +7,9 @@ ...@@ -7,7 +7,9 @@
#include <string> #include <string>
#include "android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h" #include "android_webview/browser/gfx/scoped_app_gl_state_restore_impl.h"
#include "android_webview/browser/gfx/scoped_app_gl_state_restore_impl_angle.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "ui/gl/gl_surface_egl.h"
namespace android_webview { namespace android_webview {
...@@ -29,8 +31,13 @@ ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode, ...@@ -29,8 +31,13 @@ ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode,
g_current_instance = this; g_current_instance = this;
TRACE_EVENT0("android_webview", "AppGLStateSave"); TRACE_EVENT0("android_webview", "AppGLStateSave");
impl_ = std::make_unique<internal::ScopedAppGLStateRestoreImpl>(mode, if (gl::GLSurfaceEGL::IsANGLEExternalContextAndSurfaceSupported()) {
save_restore); impl_ = std::make_unique<internal::ScopedAppGLStateRestoreImplAngle>(
mode, save_restore);
} else {
impl_ = std::make_unique<internal::ScopedAppGLStateRestoreImpl>(
mode, save_restore);
}
} }
ScopedAppGLStateRestore::~ScopedAppGLStateRestore() { ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// 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/scoped_app_gl_state_restore_impl_angle.h"
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include "base/native_library.h"
#include "base/threading/thread_restrictions.h"
#include "ui/gl/gl_context.h"
namespace android_webview {
namespace {
namespace os {
// TODO(penghuang): remove this typedef when egl headers are updated to 1.5.
typedef __eglMustCastToProperFunctionPointerType(
EGLAPIENTRYP PFNEGLGETPROCADDRESSPROC)(const char* procname);
typedef EGLContext(EGLAPIENTRYP PFNEGLGETCURRENTCONTEXTPROC)(void);
PFNEGLGETPROCADDRESSPROC eglGetProcAddressFn = nullptr;
PFNGLGETBOOLEANVPROC glGetBooleanvFn = nullptr;
PFNGLGETINTEGERVPROC glGetIntegervFn = nullptr;
#if DCHECK_IS_ON()
PFNEGLGETCURRENTCONTEXTPROC eglGetCurrentContextFn = nullptr;
#endif
template <typename T>
void AssignProc(T& fn, const char* name) {
fn = reinterpret_cast<T>(eglGetProcAddressFn(name));
CHECK(fn) << "Failed to get " << name;
}
void InitializeGLBindings() {
if (eglGetProcAddressFn)
return;
base::NativeLibraryLoadError error;
base::FilePath filename("libEGL.so");
base::NativeLibrary egl_library = base::LoadNativeLibrary(filename, &error);
CHECK(egl_library) << "Failed to load " << filename.MaybeAsASCII() << ": "
<< error.ToString();
eglGetProcAddressFn = reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(
base::GetFunctionPointerFromNativeLibrary(egl_library,
"eglGetProcAddress"));
CHECK(eglGetProcAddressFn) << "Failed to get eglGetProcAddress.";
AssignProc(glGetBooleanvFn, "glGetBooleanv");
AssignProc(glGetIntegervFn, "glGetIntegerv");
#if DCHECK_IS_ON()
AssignProc(eglGetCurrentContextFn, "eglGetCurrentContext");
#endif
}
} // namespace os
} // namespace
namespace internal {
ScopedAppGLStateRestoreImplAngle::ScopedAppGLStateRestoreImplAngle(
ScopedAppGLStateRestore::CallMode mode,
bool save_restore) {
os::InitializeGLBindings();
#if DCHECK_IS_ON()
egl_context_ = os::eglGetCurrentContextFn();
DCHECK_NE(egl_context_, EGL_NO_CONTEXT) << " no native context is current.";
#endif
// Query |stencil_state_| with native GL API.
// Android should have made a native EGL context current, so we can call GL
// directly.
os::glGetBooleanvFn(GL_STENCIL_TEST, &stencil_state_.stencil_test_enabled);
os::glGetIntegervFn(GL_STENCIL_FUNC, &stencil_state_.stencil_front_func);
os::glGetIntegervFn(GL_STENCIL_VALUE_MASK,
&stencil_state_.stencil_front_mask);
os::glGetIntegervFn(GL_STENCIL_REF, &stencil_state_.stencil_front_ref);
os::glGetIntegervFn(GL_STENCIL_BACK_FUNC, &stencil_state_.stencil_back_func);
os::glGetIntegervFn(GL_STENCIL_BACK_VALUE_MASK,
&stencil_state_.stencil_back_mask);
os::glGetIntegervFn(GL_STENCIL_BACK_REF, &stencil_state_.stencil_back_ref);
os::glGetIntegervFn(GL_STENCIL_CLEAR_VALUE, &stencil_state_.stencil_clear);
os::glGetIntegervFn(GL_STENCIL_WRITEMASK,
&stencil_state_.stencil_front_writemask);
os::glGetIntegervFn(GL_STENCIL_BACK_WRITEMASK,
&stencil_state_.stencil_back_writemask);
os::glGetIntegervFn(GL_STENCIL_FAIL, &stencil_state_.stencil_front_fail_op);
os::glGetIntegervFn(GL_STENCIL_PASS_DEPTH_FAIL,
&stencil_state_.stencil_front_z_fail_op);
os::glGetIntegervFn(GL_STENCIL_PASS_DEPTH_PASS,
&stencil_state_.stencil_front_z_pass_op);
os::glGetIntegervFn(GL_STENCIL_BACK_FAIL,
&stencil_state_.stencil_back_fail_op);
os::glGetIntegervFn(GL_STENCIL_BACK_PASS_DEPTH_FAIL,
&stencil_state_.stencil_back_z_fail_op);
os::glGetIntegervFn(GL_STENCIL_BACK_PASS_DEPTH_PASS,
&stencil_state_.stencil_back_z_pass_op);
// ANGLE can wrap current native FBO to an EGLSurface which will be used
// later, so with that EGLSurface as render target, the framebuffer binding is
// always 0.
framebuffer_binding_ext_ = 0;
// There should be no gl::GLContext current.
DCHECK(!gl::GLContext::GetCurrent());
}
ScopedAppGLStateRestoreImplAngle::~ScopedAppGLStateRestoreImplAngle() {
// There should be no gl::GLContext current.
DCHECK(!gl::GLContext::GetCurrent());
#if DCHECK_IS_ON()
DCHECK_EQ(egl_context_, os::eglGetCurrentContextFn())
<< " the native context is changed.";
#endif
}
} // namespace internal
} // namespace android_webview
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_WEBVIEW_BROWSER_GFX_SCOPED_APP_GL_STATE_RESTORE_IMPL_ANGLE_H_
#define ANDROID_WEBVIEW_BROWSER_GFX_SCOPED_APP_GL_STATE_RESTORE_IMPL_ANGLE_H_
#include <EGL/egl.h>
#include "android_webview/browser/gfx/scoped_app_gl_state_restore.h"
#include "base/dcheck_is_on.h"
#include "base/macros.h"
namespace android_webview {
namespace internal {
class ScopedAppGLStateRestoreImplAngle : public ScopedAppGLStateRestore::Impl {
public:
ScopedAppGLStateRestoreImplAngle(ScopedAppGLStateRestore::CallMode mode,
bool save_restore);
~ScopedAppGLStateRestoreImplAngle() override;
protected:
#if DCHECK_IS_ON()
EGLContext egl_context_ = EGL_NO_CONTEXT;
#endif
DISALLOW_COPY_AND_ASSIGN(ScopedAppGLStateRestoreImplAngle);
};
} // namespace internal
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_GFX_SCOPED_APP_GL_STATE_RESTORE_IMPL_ANGLE_H_
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