1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "draw_fn.h"
18 
19 #include <jni.h>
20 #include <private/hwui/WebViewFunctor.h>
21 #include <utils/Log.h>
22 
23 #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
24 #define COMPILE_ASSERT(expr, err) \
25 __unused static const char (err)[(expr) ? 1 : -1] = "";
26 
27 namespace android {
28 namespace {
29 
30 struct SupportData {
31   void* const data;
32   AwDrawFnFunctorCallbacks callbacks;
33 };
34 
onSync(int functor,void * data,const uirenderer::WebViewSyncData & syncData)35 void onSync(int functor, void* data,
36             const uirenderer::WebViewSyncData& syncData) {
37   AwDrawFn_OnSyncParams params = {
38       .version = kAwDrawFnVersion,
39       .apply_force_dark = syncData.applyForceDark,
40   };
41   SupportData* support = static_cast<SupportData*>(data);
42   support->callbacks.on_sync(functor, support->data, &params);
43 }
44 
onContextDestroyed(int functor,void * data)45 void onContextDestroyed(int functor, void* data) {
46   SupportData* support = static_cast<SupportData*>(data);
47   support->callbacks.on_context_destroyed(functor, support->data);
48 }
49 
onDestroyed(int functor,void * data)50 void onDestroyed(int functor, void* data) {
51   SupportData* support = static_cast<SupportData*>(data);
52   support->callbacks.on_destroyed(functor, support->data);
53   delete support;
54 }
55 
draw_gl(int functor,void * data,const uirenderer::DrawGlInfo & draw_gl_params)56 void draw_gl(int functor, void* data,
57              const uirenderer::DrawGlInfo& draw_gl_params) {
58   float gabcdef[7];
59   draw_gl_params.color_space_ptr->transferFn(gabcdef);
60   AwDrawFn_DrawGLParams params = {
61       .version = kAwDrawFnVersion,
62       .clip_left = draw_gl_params.clipLeft,
63       .clip_top = draw_gl_params.clipTop,
64       .clip_right = draw_gl_params.clipRight,
65       .clip_bottom = draw_gl_params.clipBottom,
66       .width = draw_gl_params.width,
67       .height = draw_gl_params.height,
68       .deprecated_0 = false,
69       .transfer_function_g = gabcdef[0],
70       .transfer_function_a = gabcdef[1],
71       .transfer_function_b = gabcdef[2],
72       .transfer_function_c = gabcdef[3],
73       .transfer_function_d = gabcdef[4],
74       .transfer_function_e = gabcdef[5],
75       .transfer_function_f = gabcdef[6],
76   };
77   COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_gl_params.transform),
78                  mismatched_transform_matrix_sizes);
79   for (int i = 0; i < NELEM(params.transform); ++i) {
80     params.transform[i] = draw_gl_params.transform[i];
81   }
82   COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3),
83                  gamut_transform_size_mismatch);
84   draw_gl_params.color_space_ptr->toXYZD50(
85       reinterpret_cast<skcms_Matrix3x3*>(&params.color_space_toXYZD50));
86 
87   SupportData* support = static_cast<SupportData*>(data);
88   support->callbacks.draw_gl(functor, support->data, &params);
89 }
90 
initializeVk(int functor,void * data,const uirenderer::VkFunctorInitParams & init_vk_params)91 void initializeVk(int functor, void* data,
92                   const uirenderer::VkFunctorInitParams& init_vk_params) {
93   SupportData* support = static_cast<SupportData*>(data);
94   VkPhysicalDeviceFeatures2 device_features_2;
95   if (init_vk_params.device_features_2)
96     device_features_2 = *init_vk_params.device_features_2;
97 
98   AwDrawFn_InitVkParams params{
99       .version = kAwDrawFnVersion,
100       .instance = init_vk_params.instance,
101       .physical_device = init_vk_params.physical_device,
102       .device = init_vk_params.device,
103       .queue = init_vk_params.queue,
104       .graphics_queue_index = init_vk_params.graphics_queue_index,
105       .api_version = init_vk_params.api_version,
106       .enabled_instance_extension_names =
107           init_vk_params.enabled_instance_extension_names,
108       .enabled_instance_extension_names_length =
109           init_vk_params.enabled_instance_extension_names_length,
110       .enabled_device_extension_names =
111           init_vk_params.enabled_device_extension_names,
112       .enabled_device_extension_names_length =
113           init_vk_params.enabled_device_extension_names_length,
114       .device_features = nullptr,
115       .device_features_2 =
116           init_vk_params.device_features_2 ? &device_features_2 : nullptr,
117   };
118   support->callbacks.init_vk(functor, support->data, &params);
119 }
120 
drawVk(int functor,void * data,const uirenderer::VkFunctorDrawParams & draw_vk_params)121 void drawVk(int functor, void* data, const uirenderer::VkFunctorDrawParams& draw_vk_params) {
122   SupportData* support = static_cast<SupportData*>(data);
123   float gabcdef[7];
124   draw_vk_params.color_space_ptr->transferFn(gabcdef);
125   AwDrawFn_DrawVkParams params{
126       .version = kAwDrawFnVersion,
127       .width = draw_vk_params.width,
128       .height = draw_vk_params.height,
129       .deprecated_0 = false,
130       .secondary_command_buffer = draw_vk_params.secondary_command_buffer,
131       .color_attachment_index = draw_vk_params.color_attachment_index,
132       .compatible_render_pass = draw_vk_params.compatible_render_pass,
133       .format = draw_vk_params.format,
134       .transfer_function_g = gabcdef[0],
135       .transfer_function_a = gabcdef[1],
136       .transfer_function_b = gabcdef[2],
137       .transfer_function_c = gabcdef[3],
138       .transfer_function_d = gabcdef[4],
139       .transfer_function_e = gabcdef[5],
140       .transfer_function_f = gabcdef[6],
141       .clip_left = draw_vk_params.clip_left,
142       .clip_top = draw_vk_params.clip_top,
143       .clip_right = draw_vk_params.clip_right,
144       .clip_bottom = draw_vk_params.clip_bottom,
145   };
146   COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3),
147                  gamut_transform_size_mismatch);
148   draw_vk_params.color_space_ptr->toXYZD50(
149       reinterpret_cast<skcms_Matrix3x3*>(&params.color_space_toXYZD50));
150   COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_vk_params.transform),
151                  mismatched_transform_matrix_sizes);
152   for (int i = 0; i < NELEM(params.transform); ++i) {
153     params.transform[i] = draw_vk_params.transform[i];
154   }
155   support->callbacks.draw_vk(functor, support->data, &params);
156 }
157 
postDrawVk(int functor,void * data)158 void postDrawVk(int functor, void* data) {
159   SupportData* support = static_cast<SupportData*>(data);
160   AwDrawFn_PostDrawVkParams params{.version = kAwDrawFnVersion};
161   support->callbacks.post_draw_vk(functor, support->data, &params);
162 }
163 
CreateFunctor(void * data,AwDrawFnFunctorCallbacks * functor_callbacks)164 int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
165   static bool callbacks_initialized = false;
166   static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = {
167       .onSync = &onSync,
168       .onContextDestroyed = &onContextDestroyed,
169       .onDestroyed = &onDestroyed,
170   };
171   if (!callbacks_initialized) {
172     switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
173       case uirenderer::RenderMode::OpenGL_ES:
174         webview_functor_callbacks.gles.draw = &draw_gl;
175         break;
176       case uirenderer::RenderMode::Vulkan:
177         webview_functor_callbacks.vk.initialize = &initializeVk;
178         webview_functor_callbacks.vk.draw = &drawVk;
179         webview_functor_callbacks.vk.postDraw = &postDrawVk;
180         break;
181     }
182     callbacks_initialized = true;
183   }
184   SupportData* support = new SupportData{
185       .data = data,
186       .callbacks = *functor_callbacks,
187   };
188   int functor = uirenderer::WebViewFunctor_create(
189       support, webview_functor_callbacks,
190       uirenderer::WebViewFunctor_queryPlatformRenderMode());
191   if (functor <= 0) delete support;
192   return functor;
193 }
194 
ReleaseFunctor(int functor)195 void ReleaseFunctor(int functor) {
196   uirenderer::WebViewFunctor_release(functor);
197 }
198 
QueryRenderMode(void)199 AwDrawFnRenderMode QueryRenderMode(void) {
200   switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
201     case uirenderer::RenderMode::OpenGL_ES:
202       return AW_DRAW_FN_RENDER_MODE_OPENGL_ES;
203     case uirenderer::RenderMode::Vulkan:
204       return AW_DRAW_FN_RENDER_MODE_VULKAN;
205   }
206 }
207 
GetDrawFnFunctionTable()208 jlong GetDrawFnFunctionTable() {
209   static AwDrawFnFunctionTable function_table = {
210     .version = kAwDrawFnVersion,
211     .query_render_mode = &QueryRenderMode,
212     .create_functor = &CreateFunctor,
213     .release_functor = &ReleaseFunctor,
214   };
215   return reinterpret_cast<intptr_t>(&function_table);
216 }
217 
218 const char kClassName[] = "com/android/webview/chromium/DrawFunctor";
219 const JNINativeMethod kJniMethods[] = {
220     {"nativeGetFunctionTable", "()J",
221      reinterpret_cast<void*>(GetDrawFnFunctionTable)},
222 };
223 
224 }  // namespace
225 
RegisterDrawFunctor(JNIEnv * env)226 void RegisterDrawFunctor(JNIEnv* env) {
227   jclass clazz = env->FindClass(kClassName);
228   LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName);
229 
230   int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods));
231   LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res);
232 }
233 
234 }  // namespace android
235