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 LOG_TAG "HardwareRenderer" 18 19 #include "jni.h" 20 #include <nativehelper/JNIHelp.h> 21 #include <android_runtime/AndroidRuntime.h> 22 23 #include <EGL/egl.h> 24 #include <EGL/eglext.h> 25 #include <EGL/egl_cache.h> 26 27 #include <utils/Timers.h> 28 29 #include <Caches.h> 30 #include <Extensions.h> 31 32 #ifdef USE_OPENGL_RENDERER 33 EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface); 34 #endif 35 36 namespace android { 37 38 /** 39 * Note: OpenGLRenderer JNI layer is generated and compiled only on supported 40 * devices. This means all the logic must be compiled only when the 41 * preprocessor variable USE_OPENGL_RENDERER is defined. 42 */ 43 #ifdef USE_OPENGL_RENDERER 44 45 // ---------------------------------------------------------------------------- 46 // Defines 47 // ---------------------------------------------------------------------------- 48 49 // Debug 50 #define DEBUG_RENDERER 0 51 52 // Debug 53 #if DEBUG_RENDERER 54 #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__) 55 #else 56 #define RENDERER_LOGD(...) 57 #endif 58 59 // ---------------------------------------------------------------------------- 60 // Surface and display management 61 // ---------------------------------------------------------------------------- 62 63 static jboolean android_view_HardwareRenderer_preserveBackBuffer(JNIEnv* env, jobject clazz) { 64 EGLDisplay display = eglGetCurrentDisplay(); 65 EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); 66 67 eglGetError(); 68 eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); 69 70 EGLint error = eglGetError(); 71 if (error != EGL_SUCCESS) { 72 RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error); 73 } 74 75 return error == EGL_SUCCESS; 76 } 77 78 static jboolean android_view_HardwareRenderer_isBackBufferPreserved(JNIEnv* env, jobject clazz) { 79 EGLDisplay display = eglGetCurrentDisplay(); 80 EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); 81 EGLint value; 82 83 eglGetError(); 84 eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &value); 85 86 EGLint error = eglGetError(); 87 if (error != EGL_SUCCESS) { 88 RENDERER_LOGD("Could not query buffer preserved swap behavior (%x)", error); 89 } 90 91 return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED; 92 } 93 94 // ---------------------------------------------------------------------------- 95 // Tracing and debugging 96 // ---------------------------------------------------------------------------- 97 98 static bool android_view_HardwareRenderer_loadProperties(JNIEnv* env, jobject clazz) { 99 if (uirenderer::Caches::hasInstance()) { 100 return uirenderer::Caches::getInstance().initProperties(); 101 } 102 return false; 103 } 104 105 static void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz, 106 jintArray size) { 107 108 EGLDisplay display = eglGetCurrentDisplay(); 109 EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); 110 111 if (size) { 112 EGLint value; 113 jint* storage = env->GetIntArrayElements(size, NULL); 114 115 eglQuerySurface(display, surface, EGL_WIDTH, &value); 116 storage[0] = value; 117 118 eglQuerySurface(display, surface, EGL_HEIGHT, &value); 119 storage[1] = value; 120 121 env->ReleaseIntArrayElements(size, storage, 0); 122 } 123 124 eglBeginFrame(display, surface); 125 } 126 127 static jlong android_view_HardwareRenderer_getSystemTime(JNIEnv* env, jobject clazz) { 128 if (uirenderer::Extensions::getInstance().hasNvSystemTime()) { 129 return eglGetSystemTimeNV(); 130 } 131 return systemTime(SYSTEM_TIME_MONOTONIC); 132 } 133 134 #endif // USE_OPENGL_RENDERER 135 136 // ---------------------------------------------------------------------------- 137 // Shaders 138 // ---------------------------------------------------------------------------- 139 140 static void android_view_HardwareRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, 141 jstring diskCachePath) { 142 143 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); 144 egl_cache_t::get()->setCacheFilename(cacheArray); 145 env->ReleaseStringUTFChars(diskCachePath, cacheArray); 146 } 147 148 // ---------------------------------------------------------------------------- 149 // JNI Glue 150 // ---------------------------------------------------------------------------- 151 152 const char* const kClassPathName = "android/view/HardwareRenderer"; 153 154 static JNINativeMethod gMethods[] = { 155 #ifdef USE_OPENGL_RENDERER 156 { "nIsBackBufferPreserved", "()Z", (void*) android_view_HardwareRenderer_isBackBufferPreserved }, 157 { "nPreserveBackBuffer", "()Z", (void*) android_view_HardwareRenderer_preserveBackBuffer }, 158 { "nLoadProperties", "()Z", (void*) android_view_HardwareRenderer_loadProperties }, 159 160 { "nBeginFrame", "([I)V", (void*) android_view_HardwareRenderer_beginFrame }, 161 162 { "nGetSystemTime", "()J", (void*) android_view_HardwareRenderer_getSystemTime }, 163 #endif 164 165 { "nSetupShadersDiskCache", "(Ljava/lang/String;)V", 166 (void*) android_view_HardwareRenderer_setupShadersDiskCache }, 167 }; 168 169 int register_android_view_HardwareRenderer(JNIEnv* env) { 170 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 171 } 172 173 }; 174