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, ¶ms);
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*>(¶ms.color_space_toXYZD50));
86
87 SupportData* support = static_cast<SupportData*>(data);
88 support->callbacks.draw_gl(functor, support->data, ¶ms);
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, ¶ms);
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*>(¶ms.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, ¶ms);
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, ¶ms);
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