output_surface_provider_webview.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "android_webview/browser/gfx/output_surface_provider_webview.h"
  5. #include <utility>
  6. #include "android_webview/browser/gfx/aw_gl_surface_external_stencil.h"
  7. #include "android_webview/browser/gfx/aw_vulkan_context_provider.h"
  8. #include "android_webview/browser/gfx/deferred_gpu_command_service.h"
  9. #include "android_webview/browser/gfx/gpu_service_webview.h"
  10. #include "android_webview/browser/gfx/skia_output_surface_dependency_webview.h"
  11. #include "android_webview/browser/gfx/task_queue_webview.h"
  12. #include "base/callback_helpers.h"
  13. #include "base/command_line.h"
  14. #include "base/feature_list.h"
  15. #include "base/logging.h"
  16. #include "base/memory/weak_ptr.h"
  17. #include "base/no_destructor.h"
  18. #include "components/viz/common/features.h"
  19. #include "components/viz/service/display_embedder/skia_output_surface_impl.h"
  20. #include "gpu/command_buffer/service/single_task_sequence.h"
  21. #include "gpu/config/gpu_finch_features.h"
  22. #include "gpu/config/gpu_switches.h"
  23. #include "ui/base/ui_base_switches.h"
  24. #include "ui/gfx/geometry/size.h"
  25. #include "ui/gl/gl_bindings.h"
  26. #include "ui/gl/gl_context.h"
  27. #include "ui/gl/gl_share_group.h"
  28. #include "ui/gl/gl_surface_egl.h"
  29. #include "ui/gl/gl_utils.h"
  30. #include "ui/gl/init/gl_factory.h"
  31. namespace android_webview {
  32. namespace {
  33. using GLSurfaceContextPair =
  34. std::pair<scoped_refptr<gl::GLSurface>, scoped_refptr<gl::GLContext>>;
  35. GLSurfaceContextPair GetRealContextForVulkan() {
  36. // TODO(crbug.com/1143279): Remove all of this after code no longer expects
  37. // GL to be present (eg for getting capabilities or calling glGetError).
  38. static base::NoDestructor<base::WeakPtr<gl::GLSurface>> cached_surface;
  39. static base::NoDestructor<base::WeakPtr<gl::GLContext>> cached_context;
  40. scoped_refptr<gl::GLSurface> surface = cached_surface.get()->get();
  41. scoped_refptr<gl::GLContext> context = cached_context.get()->get();
  42. if (surface && context)
  43. return std::make_pair(std::move(surface), std::move(context));
  44. surface = gl::init::CreateOffscreenGLSurface(gl::GetDefaultDisplayEGL(),
  45. gfx::Size(1, 1));
  46. DCHECK(surface);
  47. // Allow context and surface to be null and just fallback to
  48. // not having any real EGL context in that case instead of crashing.
  49. if (surface) {
  50. gl::GLContextAttribs attribs;
  51. context = gl::init::CreateGLContext(nullptr, surface.get(), attribs);
  52. }
  53. DCHECK(context);
  54. if (surface)
  55. *cached_surface.get() = surface->AsWeakPtr();
  56. if (context)
  57. *cached_context.get() = context->AsWeakPtr();
  58. return std::make_pair(std::move(surface), std::move(context));
  59. }
  60. void OnContextLost(std::unique_ptr<bool> expect_loss, bool synthetic_loss) {
  61. if (expect_loss && *expect_loss)
  62. return;
  63. // TODO(https://crbug.com/1112841): Debugging contexts losts. WebView will
  64. // intentionally crash in HardwareRendererViz::OnViz::DisplayOutputSurface
  65. // that will happen after this callback. That crash happens on viz thread and
  66. // doesn't have any useful information. Crash here on RenderThread to
  67. // understand the reason of context losts.
  68. // If this implementation changes, need to ensure `expect_loss` access from
  69. // MarkExpectContextLoss is still valid.
  70. LOG(FATAL) << "Non owned context lost!";
  71. }
  72. } // namespace
  73. OutputSurfaceProviderWebView::OutputSurfaceProviderWebView(
  74. AwVulkanContextProvider* vulkan_context_provider)
  75. : vulkan_context_provider_(vulkan_context_provider) {
  76. // Should be kept in sync with compositor_impl_android.cc.
  77. renderer_settings_.allow_antialiasing = false;
  78. renderer_settings_.highp_threshold_min = 2048;
  79. // Webview does not own the surface so should not clear it.
  80. renderer_settings_.should_clear_root_render_pass = false;
  81. enable_vulkan_ = features::IsUsingVulkan();
  82. DCHECK(!enable_vulkan_ || vulkan_context_provider_);
  83. auto* command_line = base::CommandLine::ForCurrentProcess();
  84. debug_settings_.tint_composited_content =
  85. command_line->HasSwitch(switches::kTintCompositedContent);
  86. InitializeContext();
  87. }
  88. OutputSurfaceProviderWebView::~OutputSurfaceProviderWebView() {
  89. // We must to destroy |gl_surface_| before |shared_context_state_|, so we will
  90. // still have context. NOTE: |shared_context_state_| holds ref to surface, but
  91. // it loses it before context.
  92. gl_surface_.reset();
  93. }
  94. void OutputSurfaceProviderWebView::InitializeContext() {
  95. DCHECK(!gl_surface_) << "InitializeContext() called twice";
  96. gl::GLDisplayEGL* display = gl::GLSurfaceEGL::GetGLDisplayEGL();
  97. // If EGL supports EGL_ANGLE_external_context_and_surface, then we will create
  98. // an ANGLE context for the current native GL context.
  99. const bool is_angle =
  100. !enable_vulkan_ && display->ext->b_EGL_ANGLE_external_context_and_surface;
  101. GLSurfaceContextPair real_context;
  102. if (enable_vulkan_) {
  103. DCHECK(!is_angle);
  104. real_context = GetRealContextForVulkan();
  105. gl_surface_ = base::MakeRefCounted<AwGLSurface>(
  106. display, std::move(real_context.first));
  107. } else {
  108. // We need to draw to FBO for External Stencil support with SkiaRenderer
  109. gl_surface_ =
  110. base::MakeRefCounted<AwGLSurfaceExternalStencil>(display, is_angle);
  111. }
  112. bool result = gl_surface_->Initialize(gl::GLSurfaceFormat());
  113. DCHECK(result);
  114. scoped_refptr<gl::GLContext> gl_context;
  115. gpu::GpuDriverBugWorkarounds workarounds(
  116. GpuServiceWebView::GetInstance()
  117. ->gpu_feature_info()
  118. .enabled_gpu_driver_bug_workarounds);
  119. // If failed to create real context for vulkan, just fallback to using
  120. // GLNonOwnedContext instead of crashing.
  121. if (enable_vulkan_ && real_context.second) {
  122. gl_context = std::move(real_context.second);
  123. } else {
  124. auto share_group = base::MakeRefCounted<gl::GLShareGroup>();
  125. gl::GLContextAttribs attribs;
  126. // For ANGLE EGL, we need to create ANGLE context from the current native
  127. // EGL context.
  128. attribs.angle_create_from_external_context = is_angle;
  129. // Skip validation when dcheck is off.
  130. #if DCHECK_IS_ON()
  131. attribs.can_skip_validation = false;
  132. #else
  133. attribs.can_skip_validation = true;
  134. #endif
  135. gl_context = gl::init::CreateGLContext(share_group.get(), gl_surface_.get(),
  136. attribs);
  137. gl_context->MakeCurrent(gl_surface_.get());
  138. }
  139. auto* share_group = gl_context->share_group();
  140. auto expect_context_loss_ptr = std::make_unique<bool>(false);
  141. expect_context_loss_ = expect_context_loss_ptr.get();
  142. shared_context_state_ = base::MakeRefCounted<gpu::SharedContextState>(
  143. share_group, gl_surface_, std::move(gl_context),
  144. false /* use_virtualized_gl_contexts */,
  145. base::BindOnce(&OnContextLost, std::move(expect_context_loss_ptr)),
  146. GpuServiceWebView::GetInstance()->gpu_preferences().gr_context_type,
  147. vulkan_context_provider_);
  148. if (!enable_vulkan_) {
  149. auto feature_info = base::MakeRefCounted<gpu::gles2::FeatureInfo>(
  150. workarounds, GpuServiceWebView::GetInstance()->gpu_feature_info());
  151. shared_context_state_->InitializeGL(
  152. GpuServiceWebView::GetInstance()->gpu_preferences(),
  153. std::move(feature_info));
  154. }
  155. shared_context_state_->InitializeGrContext(
  156. GpuServiceWebView::GetInstance()->gpu_preferences(), workarounds,
  157. nullptr /* gr_shader_cache */);
  158. }
  159. std::unique_ptr<viz::DisplayCompositorMemoryAndTaskController>
  160. OutputSurfaceProviderWebView::CreateDisplayController() {
  161. DCHECK(gl_surface_)
  162. << "InitializeContext() must be called before CreateOutputSurface()";
  163. auto skia_dependency = std::make_unique<SkiaOutputSurfaceDependencyWebView>(
  164. TaskQueueWebView::GetInstance(), GpuServiceWebView::GetInstance(),
  165. shared_context_state_.get(), gl_surface_.get(), vulkan_context_provider_);
  166. return std::make_unique<viz::DisplayCompositorMemoryAndTaskController>(
  167. std::move(skia_dependency));
  168. }
  169. std::unique_ptr<viz::OutputSurface>
  170. OutputSurfaceProviderWebView::CreateOutputSurface(
  171. viz::DisplayCompositorMemoryAndTaskController*
  172. display_compositor_controller) {
  173. DCHECK(gl_surface_)
  174. << "InitializeContext() must be called before CreateOutputSurface()";
  175. DCHECK(display_compositor_controller)
  176. << "CreateDisplayController() must be called before "
  177. "CreateOutputSurface()";
  178. return viz::SkiaOutputSurfaceImpl::Create(
  179. display_compositor_controller, renderer_settings_, debug_settings());
  180. }
  181. void OutputSurfaceProviderWebView::MarkExpectContextLoss() {
  182. // This is safe because either the OnContextLost callback has run and we've
  183. // already crashed or it has not run and this pointer is still valid.
  184. if (expect_context_loss_)
  185. *expect_context_loss_ = true;
  186. expect_context_loss_ = nullptr;
  187. }
  188. } // namespace android_webview