| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "GLRenderer" |
| |
| #include "jni.h" |
| #include <nativehelper/JNIHelp.h> |
| #include <android_runtime/AndroidRuntime.h> |
| |
| #include <EGL/egl.h> |
| #include <EGL/eglext.h> |
| #include <EGL/egl_cache.h> |
| |
| #include <utils/Timers.h> |
| |
| #include <private/hwui/DrawGlInfo.h> |
| |
| #include <Caches.h> |
| #include <Extensions.h> |
| #include <LayerRenderer.h> |
| #include <RenderNode.h> |
| |
| #ifdef USE_OPENGL_RENDERER |
| EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface); |
| #endif |
| |
| namespace android { |
| |
| /** |
| * Note: OpenGLRenderer JNI layer is generated and compiled only on supported |
| * devices. This means all the logic must be compiled only when the |
| * preprocessor variable USE_OPENGL_RENDERER is defined. |
| */ |
| #ifdef USE_OPENGL_RENDERER |
| |
| // ---------------------------------------------------------------------------- |
| // Defines |
| // ---------------------------------------------------------------------------- |
| |
| // Debug |
| #define DEBUG_RENDERER 0 |
| |
| // Debug |
| #if DEBUG_RENDERER |
| #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__) |
| #else |
| #define RENDERER_LOGD(...) |
| #endif |
| |
| // ---------------------------------------------------------------------------- |
| // Surface and display management |
| // ---------------------------------------------------------------------------- |
| |
| static jboolean android_view_GLRenderer_preserveBackBuffer(JNIEnv* env, jobject clazz) { |
| EGLDisplay display = eglGetCurrentDisplay(); |
| EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); |
| |
| eglGetError(); |
| eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); |
| |
| EGLint error = eglGetError(); |
| if (error != EGL_SUCCESS) { |
| RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error); |
| } |
| |
| return error == EGL_SUCCESS; |
| } |
| |
| static jboolean android_view_GLRenderer_isBackBufferPreserved(JNIEnv* env, jobject clazz) { |
| EGLDisplay display = eglGetCurrentDisplay(); |
| EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); |
| EGLint value; |
| |
| eglGetError(); |
| eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &value); |
| |
| EGLint error = eglGetError(); |
| if (error != EGL_SUCCESS) { |
| RENDERER_LOGD("Could not query buffer preserved swap behavior (%x)", error); |
| } |
| |
| return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Tracing and debugging |
| // ---------------------------------------------------------------------------- |
| |
| static bool android_view_GLRenderer_loadProperties(JNIEnv* env, jobject clazz) { |
| if (uirenderer::Caches::hasInstance()) { |
| return uirenderer::Caches::getInstance().initProperties(); |
| } |
| return false; |
| } |
| |
| static void android_view_GLRenderer_beginFrame(JNIEnv* env, jobject clazz, |
| jintArray size) { |
| |
| EGLDisplay display = eglGetCurrentDisplay(); |
| EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); |
| |
| if (size) { |
| EGLint value; |
| jint* storage = env->GetIntArrayElements(size, NULL); |
| |
| eglQuerySurface(display, surface, EGL_WIDTH, &value); |
| storage[0] = value; |
| |
| eglQuerySurface(display, surface, EGL_HEIGHT, &value); |
| storage[1] = value; |
| |
| env->ReleaseIntArrayElements(size, storage, 0); |
| } |
| |
| eglBeginFrame(display, surface); |
| } |
| |
| static jlong android_view_GLRenderer_getSystemTime(JNIEnv* env, jobject clazz) { |
| if (uirenderer::Extensions::getInstance().hasNvSystemTime()) { |
| return eglGetSystemTimeNV(); |
| } |
| return systemTime(SYSTEM_TIME_MONOTONIC); |
| } |
| |
| static void android_view_GLRenderer_destroyLayer(JNIEnv* env, jobject clazz, |
| jlong layerPtr) { |
| using namespace android::uirenderer; |
| Layer* layer = reinterpret_cast<Layer*>(layerPtr); |
| LayerRenderer::destroyLayer(layer); |
| } |
| |
| static void android_view_GLRenderer_prepareTree(JNIEnv* env, jobject clazz, |
| jlong renderNodePtr) { |
| using namespace android::uirenderer; |
| RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); |
| TreeInfo ignoredInfo; |
| renderNode->prepareTree(ignoredInfo); |
| } |
| |
| static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz, |
| jlong functorPtr, jboolean hasContext) { |
| using namespace android::uirenderer; |
| Functor* functor = reinterpret_cast<Functor*>(functorPtr); |
| DrawGlInfo::Mode mode = hasContext ? DrawGlInfo::kModeProcess : DrawGlInfo::kModeProcessNoContext; |
| (*functor)(mode, NULL); |
| } |
| |
| #endif // USE_OPENGL_RENDERER |
| |
| // ---------------------------------------------------------------------------- |
| // Shaders |
| // ---------------------------------------------------------------------------- |
| |
| static void android_view_GLRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, |
| jstring diskCachePath) { |
| |
| const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); |
| egl_cache_t::get()->setCacheFilename(cacheArray); |
| env->ReleaseStringUTFChars(diskCachePath, cacheArray); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // JNI Glue |
| // ---------------------------------------------------------------------------- |
| |
| const char* const kClassPathName = "android/view/GLRenderer"; |
| |
| static JNINativeMethod gMethods[] = { |
| #ifdef USE_OPENGL_RENDERER |
| { "isBackBufferPreserved", "()Z", (void*) android_view_GLRenderer_isBackBufferPreserved }, |
| { "preserveBackBuffer", "()Z", (void*) android_view_GLRenderer_preserveBackBuffer }, |
| { "loadProperties", "()Z", (void*) android_view_GLRenderer_loadProperties }, |
| |
| { "beginFrame", "([I)V", (void*) android_view_GLRenderer_beginFrame }, |
| |
| { "getSystemTime", "()J", (void*) android_view_GLRenderer_getSystemTime }, |
| { "nDestroyLayer", "(J)V", (void*) android_view_GLRenderer_destroyLayer }, |
| { "nPrepareTree", "(J)V", (void*) android_view_GLRenderer_prepareTree }, |
| { "nInvokeFunctor", "(JZ)V", (void*) android_view_GLRenderer_invokeFunctor }, |
| #endif |
| |
| { "setupShadersDiskCache", "(Ljava/lang/String;)V", |
| (void*) android_view_GLRenderer_setupShadersDiskCache }, |
| }; |
| |
| int register_android_view_GLRenderer(JNIEnv* env) { |
| return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); |
| } |
| |
| }; |