1a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy/*
2a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * Copyright (C) 2010 The Android Open Source Project
3a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy *
4a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * you may not use this file except in compliance with the License.
6a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * You may obtain a copy of the License at
7a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy *
8a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy *
10a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * Unless required by applicable law or agreed to in writing, software
11a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * See the License for the specific language governing permissions and
14a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy * limitations under the License.
15a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy */
16a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
17a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy#define LOG_TAG "HardwareRenderer"
18a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
19a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy#include "jni.h"
20a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy#include <nativehelper/JNIHelp.h>
21a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy#include <android_runtime/AndroidRuntime.h>
22a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
236db53c34a7fe8fdc2a8775dc5a400776e2716d38Romain Guy#include <EGL/egl_cache.h>
246db53c34a7fe8fdc2a8775dc5a400776e2716d38Romain Guy
25244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#ifdef USE_OPENGL_RENDERER
26244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
27244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#endif
28b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis
29a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guynamespace android {
30a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
31244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy/**
32244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
33244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy *       devices. This means all the logic must be compiled only when the
34244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy *       preprocessor variable USE_OPENGL_RENDERER is defined.
35244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy */
36244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#ifdef USE_OPENGL_RENDERER
37244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
38a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy// ----------------------------------------------------------------------------
39244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// Defines
40a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy// ----------------------------------------------------------------------------
41a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
42244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// Debug
43244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#define DEBUG_RENDERER 0
44a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
45244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// Debug
46244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#if DEBUG_RENDERER
47244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__)
48244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#else
49244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    #define RENDERER_LOGD(...)
50244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#endif
51244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
52244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// ----------------------------------------------------------------------------
53244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// Surface and display management
54244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// ----------------------------------------------------------------------------
55244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
56244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guystatic jboolean android_view_HardwareRenderer_preserveBackBuffer(JNIEnv* env, jobject clazz) {
57244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLDisplay display = eglGetCurrentDisplay();
58244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
59244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
60244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    eglGetError();
61244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
62244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
63244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLint error = eglGetError();
64244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    if (error != EGL_SUCCESS) {
65244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy        RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error);
66244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    }
67244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
68244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    return error == EGL_SUCCESS;
69a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy}
70a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
71244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guystatic jboolean android_view_HardwareRenderer_isBackBufferPreserved(JNIEnv* env, jobject clazz) {
72244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLDisplay display = eglGetCurrentDisplay();
73244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
74244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLint value;
75244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
76244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    eglGetError();
77244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &value);
78244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
79244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLint error = eglGetError();
80244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    if (error != EGL_SUCCESS) {
81244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy        RENDERER_LOGD("Could not query buffer preserved swap behavior (%x)", error);
82244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    }
83244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
84244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED;
85244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy}
86244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
87244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guystatic void android_view_HardwareRenderer_disableVsync(JNIEnv* env, jobject clazz) {
88244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLDisplay display = eglGetCurrentDisplay();
89244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
90244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    eglGetError();
91244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    eglSwapInterval(display, 0);
92244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
93244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    EGLint error = eglGetError();
94244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    if (error != EGL_SUCCESS) {
95244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy        RENDERER_LOGD("Could not disable v-sync (%x)", error);
96244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    }
97244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy}
98244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
99244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// ----------------------------------------------------------------------------
100244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// Tracing and debugging
101244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// ----------------------------------------------------------------------------
102244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
1037687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guystatic void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz,
1047687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        jintArray size) {
1057687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
1067687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    EGLDisplay display = eglGetCurrentDisplay();
1077687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
1087687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
1097687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    if (size) {
1107687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        EGLint value;
1117687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        jint* storage = env->GetIntArrayElements(size, NULL);
1127687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
1137687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        eglQuerySurface(display, surface, EGL_WIDTH, &value);
1147687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        storage[0] = value;
1157687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
1167687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        eglQuerySurface(display, surface, EGL_HEIGHT, &value);
1177687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        storage[1] = value;
1187687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
1197687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy        env->ReleaseIntArrayElements(size, storage, 0);
1207687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    }
1217687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
1227687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    eglBeginFrame(display, surface);
123b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis}
124b335fad4705348ff78d764fb4be53dcbe6b67abeJamie Gennis
125244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#endif // USE_OPENGL_RENDERER
126244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
127244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// ----------------------------------------------------------------------------
128244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// Shaders
129244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy// ----------------------------------------------------------------------------
130244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
131244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guystatic void android_view_HardwareRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
132244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy        jstring diskCachePath) {
133244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
134244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
135244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    egl_cache_t::get()->setCacheFilename(cacheArray);
136244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    env->ReleaseStringUTFChars(diskCachePath, cacheArray);
137244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy}
138244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
139a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy// ----------------------------------------------------------------------------
140a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy// JNI Glue
141a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy// ----------------------------------------------------------------------------
142a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
143a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guyconst char* const kClassPathName = "android/view/HardwareRenderer";
144a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
145a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guystatic JNINativeMethod gMethods[] = {
146244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#ifdef USE_OPENGL_RENDERER
1477687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    { "nIsBackBufferPreserved", "()Z",   (void*) android_view_HardwareRenderer_isBackBufferPreserved },
1487687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    { "nPreserveBackBuffer",    "()Z",   (void*) android_view_HardwareRenderer_preserveBackBuffer },
1497687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    { "nDisableVsync",          "()V",   (void*) android_view_HardwareRenderer_disableVsync },
1507687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy
1517687882800f49e3fc3a14f1d7540412f77d6bd4dRomain Guy    { "nBeginFrame",            "([I)V", (void*) android_view_HardwareRenderer_beginFrame },
152244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy#endif
153244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy
154244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy    { "nSetupShadersDiskCache", "(Ljava/lang/String;)V",
155244ada1d35419b7be9de0fc833bb03955b725ffaRomain Guy            (void*) android_view_HardwareRenderer_setupShadersDiskCache },
156a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy};
157a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
158a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guyint register_android_view_HardwareRenderer(JNIEnv* env) {
159a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
160a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy}
161a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy
162a95826582773a194ed7fb66bc29c9b82fe9bb8d1Romain Guy};
163