aw_draw_fn_impl.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. // Copyright 2016 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/aw_draw_fn_impl.h"
  5. #include <utility>
  6. #include "android_webview/browser/gfx/aw_vulkan_context_provider.h"
  7. #include "android_webview/browser_jni_headers/AwDrawFnImpl_jni.h"
  8. #include "base/android/build_info.h"
  9. #include "base/trace_event/trace_event.h"
  10. #include "content/public/browser/browser_task_traits.h"
  11. #include "content/public/browser/browser_thread.h"
  12. #include "gpu/config/gpu_finch_features.h"
  13. #include "gpu/config/gpu_switches.h"
  14. #include "third_party/skia/include/core/SkRefCnt.h"
  15. #include "third_party/skia/include/gpu/GrDirectContext.h"
  16. #include "third_party/skia/src/gpu/vk/GrVkSecondaryCBDrawContext.h"
  17. #include "ui/gfx/color_space.h"
  18. using base::android::JavaParamRef;
  19. using content::BrowserThread;
  20. namespace android_webview {
  21. namespace {
  22. AwDrawFnFunctionTable* g_draw_fn_function_table = nullptr;
  23. void OnSyncWrapper(int functor, void* data, AwDrawFn_OnSyncParams* params) {
  24. TRACE_EVENT1("android_webview,toplevel", "DrawFn_OnSync", "functor", functor);
  25. CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
  26. static_cast<AwDrawFnImpl*>(data)->OnSync(params);
  27. }
  28. void OnContextDestroyedWrapper(int functor, void* data) {
  29. TRACE_EVENT1("android_webview,toplevel", "DrawFn_OnContextDestroyed",
  30. "functor", functor);
  31. CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
  32. static_cast<AwDrawFnImpl*>(data)->OnContextDestroyed();
  33. }
  34. void OnDestroyedWrapper(int functor, void* data) {
  35. TRACE_EVENT1("android_webview,toplevel", "DrawFn_OnDestroyed", "functor",
  36. functor);
  37. CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
  38. delete static_cast<AwDrawFnImpl*>(data);
  39. }
  40. void DrawGLWrapper(int functor, void* data, AwDrawFn_DrawGLParams* params) {
  41. TRACE_EVENT1("android_webview,toplevel", "DrawFn_DrawGL", "functor", functor);
  42. CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
  43. static_cast<AwDrawFnImpl*>(data)->DrawGL(params);
  44. }
  45. void InitVkWrapper(int functor, void* data, AwDrawFn_InitVkParams* params) {
  46. TRACE_EVENT1("android_webview,toplevel", "DrawFn_InitVk", "functor", functor);
  47. CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
  48. static_cast<AwDrawFnImpl*>(data)->InitVk(params);
  49. }
  50. void DrawVkWrapper(int functor, void* data, AwDrawFn_DrawVkParams* params) {
  51. TRACE_EVENT1("android_webview,toplevel", "DrawFn_DrawVk", "functor", functor);
  52. CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
  53. static_cast<AwDrawFnImpl*>(data)->DrawVk(params);
  54. }
  55. void PostDrawVkWrapper(int functor,
  56. void* data,
  57. AwDrawFn_PostDrawVkParams* params) {
  58. TRACE_EVENT1("android_webview,toplevel", "DrawFn_PostDrawVk", "functor",
  59. functor);
  60. CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
  61. static_cast<AwDrawFnImpl*>(data)->PostDrawVk(params);
  62. }
  63. void RemoveOverlaysWrapper(int functor,
  64. void* data,
  65. AwDrawFn_RemoveOverlaysParams* params) {
  66. TRACE_EVENT1("android_webview,toplevel", "DrawFn_RemoveOverlays", "functor",
  67. functor);
  68. CHECK_EQ(static_cast<AwDrawFnImpl*>(data)->functor_handle(), functor);
  69. static_cast<AwDrawFnImpl*>(data)->RemoveOverlays(params);
  70. }
  71. sk_sp<GrVkSecondaryCBDrawContext> CreateDrawContext(
  72. GrDirectContext* gr_context,
  73. AwDrawFn_DrawVkParams* params,
  74. sk_sp<SkColorSpace> color_space) {
  75. // Create a GrVkSecondaryCBDrawContext to render our AHB w/ Vulkan.
  76. // TODO(ericrk): Handle non-RGBA.
  77. SkImageInfo info =
  78. SkImageInfo::MakeN32Premul(params->width, params->height, color_space);
  79. VkRect2D draw_bounds;
  80. GrVkDrawableInfo drawable_info{
  81. .fSecondaryCommandBuffer = params->secondary_command_buffer,
  82. .fColorAttachmentIndex = params->color_attachment_index,
  83. .fCompatibleRenderPass = params->compatible_render_pass,
  84. .fFormat = params->format,
  85. .fDrawBounds = &draw_bounds,
  86. };
  87. SkSurfaceProps props{0, kUnknown_SkPixelGeometry};
  88. sk_sp<GrVkSecondaryCBDrawContext> context =
  89. GrVkSecondaryCBDrawContext::Make(gr_context, info, drawable_info, &props);
  90. LOG_IF(FATAL, !context)
  91. << "Failed GrVkSecondaryCBDrawContext::Make"
  92. << " fSecondaryCommandBuffer:" << params->secondary_command_buffer
  93. << " fColorAttachmentIndex:" << params->color_attachment_index
  94. << " fCompatibleRenderPass:" << params->compatible_render_pass
  95. << " fFormat:" << params->format << " width:" << params->width
  96. << " height:" << params->height
  97. << " is_srgb:" << (color_space == SkColorSpace::MakeSRGB());
  98. return context;
  99. }
  100. OverlaysParams::Mode GetOverlaysMode(AwDrawFnOverlaysMode mode) {
  101. switch (mode) {
  102. case AW_DRAW_FN_OVERLAYS_MODE_DISABLED:
  103. return OverlaysParams::Mode::Disabled;
  104. case AW_DRAW_FN_OVERLAYS_MODE_ENABLED:
  105. return OverlaysParams::Mode::Enabled;
  106. default:
  107. NOTREACHED();
  108. return OverlaysParams::Mode::Disabled;
  109. }
  110. }
  111. template <typename T>
  112. HardwareRendererDrawParams CreateHRDrawParams(T* params,
  113. SkColorSpace* color_space) {
  114. struct HardwareRendererDrawParams hr_params {};
  115. hr_params.clip_left = params->clip_left;
  116. hr_params.clip_top = params->clip_top;
  117. hr_params.clip_right = params->clip_right;
  118. hr_params.clip_bottom = params->clip_bottom;
  119. hr_params.width = params->width;
  120. hr_params.height = params->height;
  121. if (color_space)
  122. hr_params.color_space = gfx::ColorSpace(*color_space);
  123. static_assert(std::size(decltype(params->transform){}) ==
  124. std::size(hr_params.transform),
  125. "transform size mismatch");
  126. for (size_t i = 0; i < std::size(hr_params.transform); ++i) {
  127. hr_params.transform[i] = params->transform[i];
  128. }
  129. return hr_params;
  130. }
  131. template <class T>
  132. OverlaysParams CreateOverlaysParams(T* draw_params) {
  133. OverlaysParams params;
  134. if (draw_params->version >= 3) {
  135. params.overlays_mode = GetOverlaysMode(draw_params->overlays_mode);
  136. params.get_surface_control = draw_params->get_surface_control;
  137. params.merge_transaction = draw_params->merge_transaction;
  138. }
  139. return params;
  140. }
  141. template <typename T>
  142. sk_sp<SkColorSpace> CreateColorSpace(T* params) {
  143. skcms_TransferFunction transfer_fn{
  144. params->transfer_function_g, params->transfer_function_a,
  145. params->transfer_function_b, params->transfer_function_c,
  146. params->transfer_function_d, params->transfer_function_e,
  147. params->transfer_function_f};
  148. skcms_Matrix3x3 to_xyz;
  149. static_assert(sizeof(to_xyz.vals) == sizeof(params->color_space_toXYZD50),
  150. "Color space matrix sizes do not match");
  151. memcpy(&to_xyz.vals[0][0], &params->color_space_toXYZD50[0],
  152. sizeof(to_xyz.vals));
  153. return SkColorSpace::MakeRGB(transfer_fn, to_xyz);
  154. }
  155. } // namespace
  156. static void JNI_AwDrawFnImpl_SetDrawFnFunctionTable(JNIEnv* env,
  157. jlong function_table) {
  158. g_draw_fn_function_table =
  159. reinterpret_cast<AwDrawFnFunctionTable*>(function_table);
  160. }
  161. // static
  162. bool AwDrawFnImpl::IsUsingVulkan() {
  163. return g_draw_fn_function_table &&
  164. g_draw_fn_function_table->query_render_mode() ==
  165. AW_DRAW_FN_RENDER_MODE_VULKAN;
  166. }
  167. AwDrawFnImpl::AwDrawFnImpl()
  168. : is_interop_mode_(!features::IsUsingVulkan()),
  169. render_thread_manager_(content::GetUIThreadTaskRunner({})) {
  170. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  171. DCHECK(g_draw_fn_function_table);
  172. static AwDrawFnFunctorCallbacks g_functor_callbacks{
  173. &OnSyncWrapper, &OnContextDestroyedWrapper,
  174. &OnDestroyedWrapper, &DrawGLWrapper,
  175. &InitVkWrapper, &DrawVkWrapper,
  176. &PostDrawVkWrapper, &RemoveOverlaysWrapper};
  177. if (g_draw_fn_function_table->version >= 3) {
  178. functor_handle_ = g_draw_fn_function_table->create_functor_v3(
  179. this, kAwDrawFnVersion, &g_functor_callbacks);
  180. } else {
  181. functor_handle_ =
  182. g_draw_fn_function_table->create_functor(this, &g_functor_callbacks);
  183. }
  184. }
  185. AwDrawFnImpl::~AwDrawFnImpl() {}
  186. void AwDrawFnImpl::ReleaseHandle(
  187. JNIEnv* env,
  188. const base::android::JavaParamRef<jobject>& obj) {
  189. render_thread_manager_.RemoveFromCompositorFrameProducerOnUI();
  190. g_draw_fn_function_table->release_functor(functor_handle_);
  191. }
  192. jint AwDrawFnImpl::GetFunctorHandle(
  193. JNIEnv* env,
  194. const base::android::JavaParamRef<jobject>& obj) {
  195. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  196. return functor_handle_;
  197. }
  198. jlong AwDrawFnImpl::GetCompositorFrameConsumer(
  199. JNIEnv* env,
  200. const base::android::JavaParamRef<jobject>& obj) {
  201. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  202. return reinterpret_cast<intptr_t>(GetCompositorFrameConsumer());
  203. }
  204. static jlong JNI_AwDrawFnImpl_Create(JNIEnv* env) {
  205. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  206. return reinterpret_cast<intptr_t>(new AwDrawFnImpl());
  207. }
  208. void AwDrawFnImpl::OnSync(AwDrawFn_OnSyncParams* params) {
  209. render_thread_manager_.UpdateViewTreeForceDarkStateOnRT(
  210. params->apply_force_dark);
  211. render_thread_manager_.CommitFrameOnRT();
  212. }
  213. void AwDrawFnImpl::OnContextDestroyed() {
  214. if (interop_)
  215. interop_->MakeGLContextCurrentIgnoreFailure();
  216. {
  217. RenderThreadManager::InsideHardwareReleaseReset release_reset(
  218. &render_thread_manager_);
  219. render_thread_manager_.DestroyHardwareRendererOnRT(
  220. false /* save_restore */, false /* abandon_context */);
  221. }
  222. interop_.reset();
  223. vulkan_context_provider_.reset();
  224. }
  225. void AwDrawFnImpl::DrawGL(AwDrawFn_DrawGLParams* params) {
  226. auto color_space = params->version >= 2 ? CreateColorSpace(params) : nullptr;
  227. HardwareRendererDrawParams hr_params =
  228. CreateHRDrawParams(params, color_space.get());
  229. OverlaysParams overlays_params = CreateOverlaysParams(params);
  230. render_thread_manager_.DrawOnRT(/*save_restore=*/false, hr_params,
  231. overlays_params);
  232. }
  233. void AwDrawFnImpl::InitVk(AwDrawFn_InitVkParams* params) {
  234. // We should never have a |vulkan_context_provider_| if we are calling VkInit.
  235. // This means context destroyed was not correctly called.
  236. DCHECK(!vulkan_context_provider_);
  237. vulkan_context_provider_ = AwVulkanContextProvider::Create(params);
  238. DCHECK(vulkan_context_provider_);
  239. if (is_interop_mode_) {
  240. interop_.emplace(&render_thread_manager_, vulkan_context_provider_.get());
  241. } else {
  242. render_thread_manager_.SetVulkanContextProviderOnRT(
  243. vulkan_context_provider_.get());
  244. }
  245. }
  246. void AwDrawFnImpl::DrawVk(AwDrawFn_DrawVkParams* params) {
  247. if (!vulkan_context_provider_)
  248. return;
  249. // Android HWUI has a bug that asks functor to draw into a 8-bit mask for
  250. // functionality that is not related to and not needed by webview.
  251. // GrVkSecondaryCBDrawContext currently does not expect or support R8 format
  252. // so just skip these draw calls before Android side is fixed.
  253. if (params->format == VK_FORMAT_R8_UNORM &&
  254. base::android::BuildInfo::GetInstance()->sdk_int() ==
  255. base::android::SDK_VERSION_S) {
  256. skip_next_post_draw_vk_ = true;
  257. return;
  258. }
  259. auto color_space = CreateColorSpace(params);
  260. if (!color_space) {
  261. // If we weren't passed a valid colorspace, default to sRGB.
  262. LOG(ERROR) << "Received invalid colorspace.";
  263. color_space = SkColorSpace::MakeSRGB();
  264. }
  265. auto draw_context = CreateDrawContext(
  266. vulkan_context_provider_->GetGrContext(), params, color_space);
  267. HardwareRendererDrawParams hr_params =
  268. CreateHRDrawParams(params, color_space.get());
  269. OverlaysParams overlays_params = CreateOverlaysParams(params);
  270. if (is_interop_mode_) {
  271. DCHECK(interop_);
  272. interop_->DrawVk(std::move(draw_context), std::move(color_space), hr_params,
  273. overlays_params);
  274. } else {
  275. DrawVkDirect(std::move(draw_context), std::move(color_space), hr_params,
  276. overlays_params);
  277. }
  278. }
  279. void AwDrawFnImpl::PostDrawVk(AwDrawFn_PostDrawVkParams* params) {
  280. if (!vulkan_context_provider_)
  281. return;
  282. if (skip_next_post_draw_vk_) {
  283. skip_next_post_draw_vk_ = false;
  284. return;
  285. }
  286. if (is_interop_mode_) {
  287. DCHECK(interop_);
  288. interop_->PostDrawVk();
  289. } else {
  290. PostDrawVkDirect(params);
  291. }
  292. }
  293. void AwDrawFnImpl::DrawVkDirect(sk_sp<GrVkSecondaryCBDrawContext> draw_context,
  294. sk_sp<SkColorSpace> color_space,
  295. const HardwareRendererDrawParams& hr_params,
  296. const OverlaysParams& overlays_params) {
  297. DCHECK(!scoped_secondary_cb_draw_);
  298. // Set the draw contexct in |vulkan_context_provider_|, so the SkiaRenderer
  299. // and SkiaOutputSurface* will use it as frame render target.
  300. scoped_secondary_cb_draw_.emplace(vulkan_context_provider_.get(),
  301. std::move(draw_context));
  302. render_thread_manager_.DrawOnRT(false /* save_restore */, hr_params,
  303. overlays_params);
  304. }
  305. void AwDrawFnImpl::PostDrawVkDirect(AwDrawFn_PostDrawVkParams* params) {
  306. if (!vulkan_context_provider_)
  307. return;
  308. DCHECK(scoped_secondary_cb_draw_);
  309. scoped_secondary_cb_draw_.reset();
  310. }
  311. void AwDrawFnImpl::RemoveOverlays(AwDrawFn_RemoveOverlaysParams* params) {
  312. DCHECK(params->merge_transaction);
  313. render_thread_manager_.RemoveOverlaysOnRT(params->merge_transaction);
  314. }
  315. } // namespace android_webview