• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 <EGL/egl.h>
18 #include <EGL/eglext.h>
19 #include <GLES2/gl2.h>
20 #include <GLES2/gl2ext.h>
21 #include <GLES3/gl3.h>
22 #include <GLES3/gl3ext.h>
23 #include <android/hardware_buffer_jni.h>
24 
25 #include <jni.h>
26 
27 namespace {
28 
29 const char kClassName[] = "com/android/car/internal/evs/GLES20CarEvsBufferRenderer";
30 
31 EGLImageKHR gKHRImage = EGL_NO_IMAGE_KHR;
32 
nativeUpdateTexture(JNIEnv * env,jobject,jobject hardwareBufferObj,jint textureId)33 jboolean nativeUpdateTexture(JNIEnv* env, jobject /*thiz*/, jobject hardwareBufferObj,
34                              jint textureId) {
35     EGLDisplay eglCurrentDisplay = eglGetCurrentDisplay();
36     if (gKHRImage != EGL_NO_IMAGE_KHR) {
37         // Release a previous EGL image
38         eglDestroyImageKHR(eglCurrentDisplay, gKHRImage);
39         gKHRImage = EGL_NO_IMAGE_KHR;
40     }
41 
42     // Get a native hardware buffer
43     AHardwareBuffer* nativeBuffer = AHardwareBuffer_fromHardwareBuffer(env, hardwareBufferObj);
44     if (!nativeBuffer) {
45         return JNI_FALSE;
46     }
47 
48     // Create EGL image from a native hardware buffer
49     EGLClientBuffer eglBuffer = eglGetNativeClientBufferANDROID(nativeBuffer);
50     EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
51     gKHRImage = eglCreateImageKHR(eglCurrentDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
52                                   eglBuffer, eglImageAttributes);
53     if (gKHRImage == EGL_NO_IMAGE_KHR) {
54         return JNI_FALSE;
55     }
56 
57     // Update the texture handle we already created to refer to this buffer
58     glActiveTexture(GL_TEXTURE0);
59     glBindTexture(GL_TEXTURE_2D, textureId);
60 
61     // Map texture
62     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast<GLeglImageOES>(gKHRImage));
63 
64     // Initialize the sampling properties
65     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
66     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
67     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
68     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
69 
70     return JNI_TRUE;
71 }
72 
73 }  // namespace
74 
JNI_OnLoad(JavaVM * vm,void *)75 JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) {
76     JNIEnv* env;
77     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
78         return JNI_ERR;
79     }
80 
81     // Registers native methods
82     static const JNINativeMethod methods[] = {
83             {"nUpdateTexture", "(Landroid/hardware/HardwareBuffer;I)Z",
84              reinterpret_cast<void*>(nativeUpdateTexture)},
85     };
86 
87     jclass clazz = env->FindClass(kClassName);
88     if (!clazz) {
89         return JNI_ERR;
90     }
91 
92     int result = env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
93     env->DeleteLocalRef(clazz);
94     if (result != 0) {
95         return JNI_ERR;
96     }
97 
98     return JNI_VERSION_1_6;
99 }
100 
JNI_OnUnload(JavaVM * vm,void *)101 JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* /*reserved*/) {
102     JNIEnv* env;
103     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
104         return;
105     }
106 
107     gKHRImage = EGL_NO_IMAGE_KHR;
108 }
109