xref: /aosp_15_r20/frameworks/base/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2010 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 #define ATRACE_TAG ATRACE_TAG_VIEW
18 
19 #include <GraphicsJNI.h>
20 #include <RootRenderNode.h>
21 #include <TreeInfo.h>
22 #include <android-base/unique_fd.h>
23 #include <android/native_window.h>
24 #include <nativehelper/JNIPlatformHelp.h>
25 #include <renderthread/CanvasContext.h>
26 #include <renderthread/RenderProxy.h>
27 #include <renderthread/RenderThread.h>
28 
29 #include "HardwareBufferHelpers.h"
30 #include "JvmErrorReporter.h"
31 
32 namespace android {
33 
34 using namespace android::uirenderer;
35 using namespace android::uirenderer::renderthread;
36 
37 struct {
38     jclass clazz;
39     jmethodID invokeRenderCallback;
40 } gHardwareBufferRendererClassInfo;
41 
createRenderCallback(JNIEnv * env,jobject releaseCallback)42 static RenderCallback createRenderCallback(JNIEnv* env, jobject releaseCallback) {
43     if (releaseCallback == nullptr) return nullptr;
44 
45     JavaVM* vm = nullptr;
46     LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
47     auto globalCallbackRef =
48             std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(releaseCallback));
49     return [globalCallbackRef](android::base::unique_fd&& fd, int status) {
50         globalCallbackRef->env()->CallStaticVoidMethod(
51                 gHardwareBufferRendererClassInfo.clazz,
52                 gHardwareBufferRendererClassInfo.invokeRenderCallback, globalCallbackRef->object(),
53                 reinterpret_cast<jint>(fd.release()), reinterpret_cast<jint>(status));
54     };
55 }
56 
android_graphics_HardwareBufferRenderer_createRootNode(JNIEnv * env,jobject)57 static long android_graphics_HardwareBufferRenderer_createRootNode(JNIEnv* env, jobject) {
58     auto* node = new RootRenderNode(std::make_unique<JvmErrorReporter>(env));
59     node->incStrong(nullptr);
60     node->setName("RootRenderNode");
61     return reinterpret_cast<jlong>(node);
62 }
63 
android_graphics_hardwareBufferRenderer_destroyRootNode(JNIEnv *,jobject,jlong renderNodePtr)64 static void android_graphics_hardwareBufferRenderer_destroyRootNode(JNIEnv*, jobject,
65                                                                     jlong renderNodePtr) {
66     auto* node = reinterpret_cast<RootRenderNode*>(renderNodePtr);
67     node->destroy();
68 }
69 
android_graphics_HardwareBufferRenderer_create(JNIEnv * env,jobject,jobject buffer,jlong renderNodePtr)70 static long android_graphics_HardwareBufferRenderer_create(JNIEnv* env, jobject, jobject buffer,
71                                                            jlong renderNodePtr) {
72     auto* hardwareBuffer = HardwareBufferHelpers::AHardwareBuffer_fromHardwareBuffer(env, buffer);
73     auto* rootRenderNode = reinterpret_cast<RootRenderNode*>(renderNodePtr);
74     ContextFactoryImpl factory(rootRenderNode);
75     auto* proxy = new RenderProxy(false, rootRenderNode, &factory);
76     proxy->setHardwareBuffer(hardwareBuffer);
77     return (jlong)proxy;
78 }
79 
HardwareBufferRenderer_destroy(jlong renderProxy)80 static void HardwareBufferRenderer_destroy(jlong renderProxy) {
81     auto* proxy = reinterpret_cast<RenderProxy*>(renderProxy);
82     delete proxy;
83 }
84 
createMatrixFromBufferTransform(SkScalar width,SkScalar height,int transform)85 static SkMatrix createMatrixFromBufferTransform(SkScalar width, SkScalar height, int transform) {
86     switch (transform) {
87         case ANATIVEWINDOW_TRANSFORM_ROTATE_90:
88             return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
89         case ANATIVEWINDOW_TRANSFORM_ROTATE_180:
90             return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
91         case ANATIVEWINDOW_TRANSFORM_ROTATE_270:
92             return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
93         default:
94             ALOGE("Invalid transform provided. Transform should be validated from"
95                   "the java side. Leveraging identity transform as a fallback");
96             [[fallthrough]];
97         case ANATIVEWINDOW_TRANSFORM_IDENTITY:
98             return SkMatrix::I();
99     }
100 }
101 
android_graphics_HardwareBufferRenderer_render(JNIEnv * env,jobject,jlong renderProxy,jint transform,jint width,jint height,jlong colorspacePtr,jobject consumer)102 static int android_graphics_HardwareBufferRenderer_render(JNIEnv* env, jobject, jlong renderProxy,
103                                                           jint transform, jint width, jint height,
104                                                           jlong colorspacePtr, jobject consumer) {
105     auto* proxy = reinterpret_cast<RenderProxy*>(renderProxy);
106     auto skWidth = static_cast<SkScalar>(width);
107     auto skHeight = static_cast<SkScalar>(height);
108     auto matrix = createMatrixFromBufferTransform(skWidth, skHeight, transform);
109     auto colorSpace = GraphicsJNI::getNativeColorSpace(colorspacePtr);
110     proxy->setHardwareBufferRenderParams(HardwareBufferRenderParams(
111             width, height, matrix, colorSpace, createRenderCallback(env, consumer)));
112     nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
113     UiFrameInfoBuilder(proxy->frameInfo())
114                 .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
115                     UiFrameInfoBuilder::UNKNOWN_DEADLINE,
116                     UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL)
117                 .addFlag(FrameInfoFlags::SurfaceCanvas);
118     return proxy->syncAndDrawFrame();
119 }
120 
android_graphics_HardwareBufferRenderer_setLightGeometry(JNIEnv *,jobject,jlong renderProxyPtr,jfloat lightX,jfloat lightY,jfloat lightZ,jfloat lightRadius)121 static void android_graphics_HardwareBufferRenderer_setLightGeometry(JNIEnv*, jobject,
122                                                                      jlong renderProxyPtr,
123                                                                      jfloat lightX, jfloat lightY,
124                                                                      jfloat lightZ,
125                                                                      jfloat lightRadius) {
126     auto* proxy = reinterpret_cast<RenderProxy*>(renderProxyPtr);
127     proxy->setLightGeometry((Vector3){lightX, lightY, lightZ}, lightRadius);
128 }
129 
android_graphics_HardwareBufferRenderer_setLightAlpha(JNIEnv * env,jobject,jlong renderProxyPtr,jfloat ambientShadowAlpha,jfloat spotShadowAlpha)130 static void android_graphics_HardwareBufferRenderer_setLightAlpha(JNIEnv* env, jobject,
131                                                                   jlong renderProxyPtr,
132                                                                   jfloat ambientShadowAlpha,
133                                                                   jfloat spotShadowAlpha) {
134     auto* proxy = reinterpret_cast<RenderProxy*>(renderProxyPtr);
135     proxy->setLightAlpha((uint8_t)(255 * ambientShadowAlpha), (uint8_t)(255 * spotShadowAlpha));
136 }
137 
android_graphics_HardwareBufferRenderer_getFinalizer(CRITICAL_JNI_PARAMS)138 static jlong android_graphics_HardwareBufferRenderer_getFinalizer(CRITICAL_JNI_PARAMS) {
139     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&HardwareBufferRenderer_destroy));
140 }
141 
142 // ----------------------------------------------------------------------------
143 // JNI Glue
144 // ----------------------------------------------------------------------------
145 
146 const char* const kClassPathName = "android/graphics/HardwareBufferRenderer";
147 
148 static const JNINativeMethod gMethods[] = {
149         {"nCreateHardwareBufferRenderer", "(Landroid/hardware/HardwareBuffer;J)J",
150          (void*)android_graphics_HardwareBufferRenderer_create},
151         {"nRender", "(JIIIJLjava/util/function/Consumer;)I",
152          (void*)android_graphics_HardwareBufferRenderer_render},
153         {"nCreateRootRenderNode", "()J",
154          (void*)android_graphics_HardwareBufferRenderer_createRootNode},
155         {"nSetLightGeometry", "(JFFFF)V",
156          (void*)android_graphics_HardwareBufferRenderer_setLightGeometry},
157         {"nSetLightAlpha", "(JFF)V", (void*)android_graphics_HardwareBufferRenderer_setLightAlpha},
158         {"nGetFinalizer", "()J", (void*)android_graphics_HardwareBufferRenderer_getFinalizer},
159         {"nDestroyRootRenderNode", "(J)V",
160          (void*)android_graphics_hardwareBufferRenderer_destroyRootNode}};
161 
register_android_graphics_HardwareBufferRenderer(JNIEnv * env)162 int register_android_graphics_HardwareBufferRenderer(JNIEnv* env) {
163     jclass hardwareBufferRendererClazz =
164             FindClassOrDie(env, "android/graphics/HardwareBufferRenderer");
165     gHardwareBufferRendererClassInfo.clazz =
166             reinterpret_cast<jclass>(env->NewGlobalRef(hardwareBufferRendererClazz));
167     gHardwareBufferRendererClassInfo.invokeRenderCallback =
168             GetStaticMethodIDOrDie(env, hardwareBufferRendererClazz, "invokeRenderCallback",
169                                    "(Ljava/util/function/Consumer;II)V");
170     HardwareBufferHelpers::init();
171     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
172 }
173 
174 }  // namespace android