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
GetOverlaysMode(uirenderer::OverlaysMode overlays_mode)35 AwDrawFnOverlaysMode GetOverlaysMode(uirenderer::OverlaysMode overlays_mode) {
36 switch (overlays_mode) {
37 case uirenderer::OverlaysMode::Disabled:
38 return AW_DRAW_FN_OVERLAYS_MODE_DISABLED;
39 case uirenderer::OverlaysMode::Enabled:
40 return AW_DRAW_FN_OVERLAYS_MODE_ENABLED;
41 }
42 }
43
onSync(int functor,void * data,const uirenderer::WebViewSyncData & syncData)44 void onSync(int functor, void* data,
45 const uirenderer::WebViewSyncData& syncData) {
46 AwDrawFn_OnSyncParams params = {
47 .version = kAwDrawFnVersion,
48 .apply_force_dark = syncData.applyForceDark,
49 };
50 SupportData* support = static_cast<SupportData*>(data);
51 support->callbacks.on_sync(functor, support->data, ¶ms);
52 }
53
onContextDestroyed(int functor,void * data)54 void onContextDestroyed(int functor, void* data) {
55 SupportData* support = static_cast<SupportData*>(data);
56 support->callbacks.on_context_destroyed(functor, support->data);
57 }
58
onDestroyed(int functor,void * data)59 void onDestroyed(int functor, void* data) {
60 SupportData* support = static_cast<SupportData*>(data);
61 support->callbacks.on_destroyed(functor, support->data);
62 delete support;
63 }
64
removeOverlays(int functor,void * data,AwDrawFn_MergeTransaction merge_transaction)65 void removeOverlays(int functor, void* data,
66 AwDrawFn_MergeTransaction merge_transaction) {
67 AwDrawFn_RemoveOverlaysParams params = {
68 .version = kAwDrawFnVersion,
69 .merge_transaction = merge_transaction
70 };
71 SupportData* support = static_cast<SupportData*>(data);
72 if (support->callbacks.remove_overlays)
73 support->callbacks.remove_overlays(functor, support->data, ¶ms);
74 }
75
draw_gl(int functor,void * data,const uirenderer::DrawGlInfo & draw_gl_params,const uirenderer::WebViewOverlayData & overlay_params)76 void draw_gl(int functor, void* data,
77 const uirenderer::DrawGlInfo& draw_gl_params,
78 const uirenderer::WebViewOverlayData& overlay_params) {
79 float gabcdef[7];
80 if (draw_gl_params.color_space_ptr) {
81 draw_gl_params.color_space_ptr->transferFn(gabcdef);
82 } else {
83 // Assume sRGB.
84 gabcdef[0] = SkNamedTransferFn::kSRGB.g;
85 gabcdef[1] = SkNamedTransferFn::kSRGB.a;
86 gabcdef[2] = SkNamedTransferFn::kSRGB.b;
87 gabcdef[3] = SkNamedTransferFn::kSRGB.c;
88 gabcdef[4] = SkNamedTransferFn::kSRGB.d;
89 gabcdef[5] = SkNamedTransferFn::kSRGB.e;
90 gabcdef[6] = SkNamedTransferFn::kSRGB.f;
91 }
92 AwDrawFn_DrawGLParams params = {
93 .version = kAwDrawFnVersion,
94 .clip_left = draw_gl_params.clipLeft,
95 .clip_top = draw_gl_params.clipTop,
96 .clip_right = draw_gl_params.clipRight,
97 .clip_bottom = draw_gl_params.clipBottom,
98 .width = draw_gl_params.width,
99 .height = draw_gl_params.height,
100 .deprecated_0 = false,
101 .transfer_function_g = gabcdef[0],
102 .transfer_function_a = gabcdef[1],
103 .transfer_function_b = gabcdef[2],
104 .transfer_function_c = gabcdef[3],
105 .transfer_function_d = gabcdef[4],
106 .transfer_function_e = gabcdef[5],
107 .transfer_function_f = gabcdef[6],
108 .overlays_mode = GetOverlaysMode(overlay_params.overlaysMode),
109 .get_surface_control = overlay_params.getSurfaceControl,
110 .merge_transaction = overlay_params.mergeTransaction
111 };
112 COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_gl_params.transform),
113 mismatched_transform_matrix_sizes);
114 for (int i = 0; i < NELEM(params.transform); ++i) {
115 params.transform[i] = draw_gl_params.transform[i];
116 }
117 COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3),
118 gamut_transform_size_mismatch);
119 if (draw_gl_params.color_space_ptr) {
120 draw_gl_params.color_space_ptr->toXYZD50(
121 reinterpret_cast<skcms_Matrix3x3*>(¶ms.color_space_toXYZD50));
122 } else {
123 // Assume sRGB.
124 memcpy(¶ms.color_space_toXYZD50, &SkNamedGamut::kSRGB,
125 sizeof(params.color_space_toXYZD50));
126 }
127
128 SupportData* support = static_cast<SupportData*>(data);
129 support->callbacks.draw_gl(functor, support->data, ¶ms);
130 }
131
initializeVk(int functor,void * data,const uirenderer::VkFunctorInitParams & init_vk_params)132 void initializeVk(int functor, void* data,
133 const uirenderer::VkFunctorInitParams& init_vk_params) {
134 SupportData* support = static_cast<SupportData*>(data);
135 VkPhysicalDeviceFeatures2 device_features_2;
136 if (init_vk_params.device_features_2)
137 device_features_2 = *init_vk_params.device_features_2;
138
139 AwDrawFn_InitVkParams params{
140 .version = kAwDrawFnVersion,
141 .instance = init_vk_params.instance,
142 .physical_device = init_vk_params.physical_device,
143 .device = init_vk_params.device,
144 .queue = init_vk_params.queue,
145 .graphics_queue_index = init_vk_params.graphics_queue_index,
146 .api_version = init_vk_params.api_version,
147 .enabled_instance_extension_names =
148 init_vk_params.enabled_instance_extension_names,
149 .enabled_instance_extension_names_length =
150 init_vk_params.enabled_instance_extension_names_length,
151 .enabled_device_extension_names =
152 init_vk_params.enabled_device_extension_names,
153 .enabled_device_extension_names_length =
154 init_vk_params.enabled_device_extension_names_length,
155 .device_features = nullptr,
156 .device_features_2 =
157 init_vk_params.device_features_2 ? &device_features_2 : nullptr,
158 };
159 support->callbacks.init_vk(functor, support->data, ¶ms);
160 }
161
drawVk(int functor,void * data,const uirenderer::VkFunctorDrawParams & draw_vk_params,const uirenderer::WebViewOverlayData & overlay_params)162 void drawVk(int functor, void* data,
163 const uirenderer::VkFunctorDrawParams& draw_vk_params,
164 const uirenderer::WebViewOverlayData& overlay_params) {
165 SupportData* support = static_cast<SupportData*>(data);
166 float gabcdef[7];
167 if (draw_vk_params.color_space_ptr) {
168 draw_vk_params.color_space_ptr->transferFn(gabcdef);
169 } else {
170 // Assume sRGB.
171 gabcdef[0] = SkNamedTransferFn::kSRGB.g;
172 gabcdef[1] = SkNamedTransferFn::kSRGB.a;
173 gabcdef[2] = SkNamedTransferFn::kSRGB.b;
174 gabcdef[3] = SkNamedTransferFn::kSRGB.c;
175 gabcdef[4] = SkNamedTransferFn::kSRGB.d;
176 gabcdef[5] = SkNamedTransferFn::kSRGB.e;
177 gabcdef[6] = SkNamedTransferFn::kSRGB.f;
178 }
179 AwDrawFn_DrawVkParams params{
180 .version = kAwDrawFnVersion,
181 .width = draw_vk_params.width,
182 .height = draw_vk_params.height,
183 .deprecated_0 = false,
184 .secondary_command_buffer = draw_vk_params.secondary_command_buffer,
185 .color_attachment_index = draw_vk_params.color_attachment_index,
186 .compatible_render_pass = draw_vk_params.compatible_render_pass,
187 .format = draw_vk_params.format,
188 .transfer_function_g = gabcdef[0],
189 .transfer_function_a = gabcdef[1],
190 .transfer_function_b = gabcdef[2],
191 .transfer_function_c = gabcdef[3],
192 .transfer_function_d = gabcdef[4],
193 .transfer_function_e = gabcdef[5],
194 .transfer_function_f = gabcdef[6],
195 .clip_left = draw_vk_params.clip_left,
196 .clip_top = draw_vk_params.clip_top,
197 .clip_right = draw_vk_params.clip_right,
198 .clip_bottom = draw_vk_params.clip_bottom,
199 .overlays_mode = GetOverlaysMode(overlay_params.overlaysMode),
200 .get_surface_control = overlay_params.getSurfaceControl,
201 .merge_transaction = overlay_params.mergeTransaction
202 };
203 COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3),
204 gamut_transform_size_mismatch);
205 if (draw_vk_params.color_space_ptr) {
206 draw_vk_params.color_space_ptr->toXYZD50(
207 reinterpret_cast<skcms_Matrix3x3*>(¶ms.color_space_toXYZD50));
208 } else {
209 // Assume sRGB.
210 memcpy(¶ms.color_space_toXYZD50, &SkNamedGamut::kSRGB,
211 sizeof(params.color_space_toXYZD50));
212 }
213 COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_vk_params.transform),
214 mismatched_transform_matrix_sizes);
215 for (int i = 0; i < NELEM(params.transform); ++i) {
216 params.transform[i] = draw_vk_params.transform[i];
217 }
218 support->callbacks.draw_vk(functor, support->data, ¶ms);
219 }
220
postDrawVk(int functor,void * data)221 void postDrawVk(int functor, void* data) {
222 SupportData* support = static_cast<SupportData*>(data);
223 AwDrawFn_PostDrawVkParams params{.version = kAwDrawFnVersion};
224 support->callbacks.post_draw_vk(functor, support->data, ¶ms);
225 }
226
CreateFunctor_v3(void * data,int version,AwDrawFnFunctorCallbacks * functor_callbacks)227 int CreateFunctor_v3(void* data, int version,
228 AwDrawFnFunctorCallbacks* functor_callbacks) {
229 static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = [] {
230 uirenderer::WebViewFunctorCallbacks ret = {
231 .onSync = &onSync,
232 .onContextDestroyed = &onContextDestroyed,
233 .onDestroyed = &onDestroyed,
234 .removeOverlays = &removeOverlays,
235 };
236 switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
237 case uirenderer::RenderMode::OpenGL_ES:
238 ret.gles.draw = &draw_gl;
239 break;
240 case uirenderer::RenderMode::Vulkan:
241 ret.vk.initialize = &initializeVk;
242 ret.vk.draw = &drawVk;
243 ret.vk.postDraw = &postDrawVk;
244 break;
245 }
246 return ret;
247 }();
248 SupportData* support = new SupportData{
249 .data = data,
250 };
251
252 // These callbacks are available on all versions.
253 support->callbacks = {
254 .on_sync = functor_callbacks->on_sync,
255 .on_context_destroyed = functor_callbacks->on_context_destroyed,
256 .on_destroyed = functor_callbacks->on_destroyed,
257 .draw_gl = functor_callbacks->draw_gl,
258 .init_vk = functor_callbacks->init_vk,
259 .draw_vk = functor_callbacks->draw_vk,
260 .post_draw_vk = functor_callbacks->post_draw_vk,
261 };
262
263 if (version >= 3) {
264 support->callbacks.remove_overlays = functor_callbacks->remove_overlays;
265 }
266
267 int functor = uirenderer::WebViewFunctor_create(
268 support, webview_functor_callbacks,
269 uirenderer::WebViewFunctor_queryPlatformRenderMode());
270 if (functor <= 0) delete support;
271 return functor;
272 }
273
CreateFunctor(void * data,AwDrawFnFunctorCallbacks * functor_callbacks)274 int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
275 const int kVersionForDeprecatedCreateFunctor = 2;
276 return CreateFunctor_v3(data, kVersionForDeprecatedCreateFunctor,
277 functor_callbacks);
278 }
279
ReleaseFunctor(int functor)280 void ReleaseFunctor(int functor) {
281 uirenderer::WebViewFunctor_release(functor);
282 }
283
QueryRenderMode(void)284 AwDrawFnRenderMode QueryRenderMode(void) {
285 switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
286 case uirenderer::RenderMode::OpenGL_ES:
287 return AW_DRAW_FN_RENDER_MODE_OPENGL_ES;
288 case uirenderer::RenderMode::Vulkan:
289 return AW_DRAW_FN_RENDER_MODE_VULKAN;
290 }
291 }
292
GetDrawFnFunctionTable()293 jlong GetDrawFnFunctionTable() {
294 static AwDrawFnFunctionTable function_table = {
295 .version = kAwDrawFnVersion,
296 .query_render_mode = &QueryRenderMode,
297 .create_functor = &CreateFunctor,
298 .release_functor = &ReleaseFunctor,
299 .create_functor_v3 = &CreateFunctor_v3,
300 };
301 return reinterpret_cast<intptr_t>(&function_table);
302 }
303
304 const char kClassName[] = "com/android/webview/chromium/DrawFunctor";
305 const JNINativeMethod kJniMethods[] = {
306 {"nativeGetFunctionTable", "()J",
307 reinterpret_cast<void*>(GetDrawFnFunctionTable)},
308 };
309
310 } // namespace
311
RegisterDrawFunctor(JNIEnv * env)312 void RegisterDrawFunctor(JNIEnv* env) {
313 jclass clazz = env->FindClass(kClassName);
314 LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName);
315
316 int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods));
317 LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res);
318 }
319
320 } // namespace android
321