Loading core/java/android/view/GLES20Canvas.java +0 −43 Original line number Diff line number Diff line Loading @@ -214,49 +214,6 @@ class GLES20Canvas extends HardwareCanvas { private static native void nSetViewport(int renderer, int width, int height); /** * Preserves the back buffer of the current surface after a buffer swap. * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT. * * @return True if the swap behavior was successfully changed, * false otherwise. * * @hide */ public static boolean preserveBackBuffer() { return nPreserveBackBuffer(); } private static native boolean nPreserveBackBuffer(); /** * Indicates whether the current surface preserves its back buffer * after a buffer swap. * * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED, * false otherwise * * @hide */ public static boolean isBackBufferPreserved() { return nIsBackBufferPreserved(); } private static native boolean nIsBackBufferPreserved(); /** * Disables v-sync. For performance testing only. * * @hide */ public static void disableVsync() { nDisableVsync(); } private static native void nDisableVsync(); @Override public void onPreDraw(Rect dirty) { if (dirty != null) { Loading core/java/android/view/HardwareRenderer.java +42 −6 Original line number Diff line number Diff line Loading @@ -281,6 +281,43 @@ public abstract class HardwareRenderer { private static native void nBeginFrame(); /** * Preserves the back buffer of the current surface after a buffer swap. * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT. * * @return True if the swap behavior was successfully changed, * false otherwise. */ static boolean preserveBackBuffer() { return nPreserveBackBuffer(); } private static native boolean nPreserveBackBuffer(); /** * Indicates whether the current surface preserves its back buffer * after a buffer swap. * * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED, * false otherwise */ static boolean isBackBufferPreserved() { return nIsBackBufferPreserved(); } private static native boolean nIsBackBufferPreserved(); /** * Disables v-sync. For performance testing only. */ static void disableVsync() { nDisableVsync(); } private static native void nDisableVsync(); /** * Interface used to receive callbacks whenever a view is drawn by * a hardware renderer instance. Loading Loading @@ -777,7 +814,7 @@ public abstract class HardwareRenderer { // If mDirtyRegions is set, this means we have an EGL configuration // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set if (sDirtyRegions) { if (!(mDirtyRegionsEnabled = GLES20Canvas.preserveBackBuffer())) { if (!(mDirtyRegionsEnabled = preserveBackBuffer())) { Log.w(LOG_TAG, "Backbuffer cannot be preserved"); } } else if (sDirtyRegionsRequested) { Loading @@ -787,7 +824,7 @@ public abstract class HardwareRenderer { // want to set mDirtyRegions. We try to do this only if dirty // regions were initially requested as part of the device // configuration (see RENDER_DIRTY_REGIONS) mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved(); mDirtyRegionsEnabled = isBackBufferPreserved(); } } Loading Loading @@ -926,7 +963,6 @@ public abstract class HardwareRenderer { } beginFrame(); onPreDraw(dirty); HardwareCanvas canvas = mCanvas; Loading Loading @@ -1203,7 +1239,7 @@ public abstract class HardwareRenderer { void setup(int width, int height) { super.setup(width, height); if (mVsyncDisabled) { GLES20Canvas.disableVsync(); disableVsync(); } } Loading core/jni/android_view_GLES20Canvas.cpp +5 −52 Original line number Diff line number Diff line Loading @@ -62,9 +62,9 @@ using namespace uirenderer; */ #ifdef USE_OPENGL_RENDERER /////////////////////////////////////////////////////////////////////////////// // ---------------------------------------------------------------------------- // Defines /////////////////////////////////////////////////////////////////////////////// // ---------------------------------------------------------------------------- // Debug #define DEBUG_RENDERER 0 Loading @@ -87,52 +87,9 @@ static struct { } gRectClassInfo; // ---------------------------------------------------------------------------- // Misc // Caching // ---------------------------------------------------------------------------- static jboolean android_view_GLES20Canvas_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_GLES20Canvas_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; } static void android_view_GLES20Canvas_disableVsync(JNIEnv* env, jobject clazz) { EGLDisplay display = eglGetCurrentDisplay(); eglGetError(); eglSwapInterval(display, 0); EGLint error = eglGetError(); if (error != EGL_SUCCESS) { RENDERER_LOGD("Could not disable v-sync (%x)", error); } } static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz, Caches::FlushMode mode) { if (Caches::hasInstance()) { Loading Loading @@ -853,9 +810,6 @@ static JNINativeMethod gMethods[] = { { "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable }, #ifdef USE_OPENGL_RENDERER { "nIsBackBufferPreserved", "()Z", (void*) android_view_GLES20Canvas_isBackBufferPreserved }, { "nPreserveBackBuffer", "()Z", (void*) android_view_GLES20Canvas_preserveBackBuffer }, { "nDisableVsync", "()V", (void*) android_view_GLES20Canvas_disableVsync }, { "nFlushCaches", "(I)V", (void*) android_view_GLES20Canvas_flushCaches }, { "nInitCaches", "()V", (void*) android_view_GLES20Canvas_initCaches }, { "nTerminateCaches", "()V", (void*) android_view_GLES20Canvas_terminateCaches }, Loading @@ -869,8 +823,7 @@ static JNINativeMethod gMethods[] = { { "nGetStencilSize", "()I", (void*) android_view_GLES20Canvas_getStencilSize }, { "nCallDrawGLFunction", "(II)I", (void*) android_view_GLES20Canvas_callDrawGLFunction }, { "nCallDrawGLFunction", "(II)I", (void*) android_view_GLES20Canvas_callDrawGLFunction }, { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save }, { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore }, Loading core/jni/android_view_HardwareRenderer.cpp +96 −11 Original line number Diff line number Diff line Loading @@ -20,30 +20,105 @@ #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> #ifdef USE_OPENGL_RENDERER #include <EGL/egl_cache.h> 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 // ---------------------------------------------------------------------------- // Misc // Defines // ---------------------------------------------------------------------------- static void android_view_HardwareRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, jstring diskCachePath) { // Debug #define DEBUG_RENDERER 0 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); egl_cache_t::get()->setCacheFilename(cacheArray); env->ReleaseStringUTFChars(diskCachePath, cacheArray); // Debug #if DEBUG_RENDERER #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__) #else #define RENDERER_LOGD(...) #endif // ---------------------------------------------------------------------------- // Surface and display management // ---------------------------------------------------------------------------- static jboolean android_view_HardwareRenderer_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_HardwareRenderer_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; } static void android_view_HardwareRenderer_disableVsync(JNIEnv* env, jobject clazz) { EGLDisplay display = eglGetCurrentDisplay(); eglGetError(); eglSwapInterval(display, 0); EGLint error = eglGetError(); if (error != EGL_SUCCESS) { RENDERER_LOGD("Could not disable v-sync (%x)", error); } } // ---------------------------------------------------------------------------- // Tracing and debugging // ---------------------------------------------------------------------------- static void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz) { EGLDisplay dpy = eglGetCurrentDisplay(); EGLSurface surf = eglGetCurrentSurface(EGL_DRAW); eglBeginFrame(dpy, surf); } #endif // USE_OPENGL_RENDERER // ---------------------------------------------------------------------------- // Shaders // ---------------------------------------------------------------------------- static void android_view_HardwareRenderer_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 // ---------------------------------------------------------------------------- Loading @@ -51,10 +126,20 @@ static void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz) const char* const kClassPathName = "android/view/HardwareRenderer"; static JNINativeMethod gMethods[] = { { "nSetupShadersDiskCache", "(Ljava/lang/String;)V", (void*) android_view_HardwareRenderer_setupShadersDiskCache }, #ifdef USE_OPENGL_RENDERER { "nIsBackBufferPreserved", "()Z", (void*) android_view_HardwareRenderer_isBackBufferPreserved }, { "nPreserveBackBuffer", "()Z", (void*) android_view_HardwareRenderer_preserveBackBuffer }, { "nDisableVsync", "()V", (void*) android_view_HardwareRenderer_disableVsync }, { "nBeginFrame", "()V", (void*) android_view_HardwareRenderer_beginFrame }, #endif { "nSetupShadersDiskCache", "(Ljava/lang/String;)V", (void*) android_view_HardwareRenderer_setupShadersDiskCache }, }; int register_android_view_HardwareRenderer(JNIEnv* env) { Loading Loading
core/java/android/view/GLES20Canvas.java +0 −43 Original line number Diff line number Diff line Loading @@ -214,49 +214,6 @@ class GLES20Canvas extends HardwareCanvas { private static native void nSetViewport(int renderer, int width, int height); /** * Preserves the back buffer of the current surface after a buffer swap. * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT. * * @return True if the swap behavior was successfully changed, * false otherwise. * * @hide */ public static boolean preserveBackBuffer() { return nPreserveBackBuffer(); } private static native boolean nPreserveBackBuffer(); /** * Indicates whether the current surface preserves its back buffer * after a buffer swap. * * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED, * false otherwise * * @hide */ public static boolean isBackBufferPreserved() { return nIsBackBufferPreserved(); } private static native boolean nIsBackBufferPreserved(); /** * Disables v-sync. For performance testing only. * * @hide */ public static void disableVsync() { nDisableVsync(); } private static native void nDisableVsync(); @Override public void onPreDraw(Rect dirty) { if (dirty != null) { Loading
core/java/android/view/HardwareRenderer.java +42 −6 Original line number Diff line number Diff line Loading @@ -281,6 +281,43 @@ public abstract class HardwareRenderer { private static native void nBeginFrame(); /** * Preserves the back buffer of the current surface after a buffer swap. * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT. * * @return True if the swap behavior was successfully changed, * false otherwise. */ static boolean preserveBackBuffer() { return nPreserveBackBuffer(); } private static native boolean nPreserveBackBuffer(); /** * Indicates whether the current surface preserves its back buffer * after a buffer swap. * * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED, * false otherwise */ static boolean isBackBufferPreserved() { return nIsBackBufferPreserved(); } private static native boolean nIsBackBufferPreserved(); /** * Disables v-sync. For performance testing only. */ static void disableVsync() { nDisableVsync(); } private static native void nDisableVsync(); /** * Interface used to receive callbacks whenever a view is drawn by * a hardware renderer instance. Loading Loading @@ -777,7 +814,7 @@ public abstract class HardwareRenderer { // If mDirtyRegions is set, this means we have an EGL configuration // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set if (sDirtyRegions) { if (!(mDirtyRegionsEnabled = GLES20Canvas.preserveBackBuffer())) { if (!(mDirtyRegionsEnabled = preserveBackBuffer())) { Log.w(LOG_TAG, "Backbuffer cannot be preserved"); } } else if (sDirtyRegionsRequested) { Loading @@ -787,7 +824,7 @@ public abstract class HardwareRenderer { // want to set mDirtyRegions. We try to do this only if dirty // regions were initially requested as part of the device // configuration (see RENDER_DIRTY_REGIONS) mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved(); mDirtyRegionsEnabled = isBackBufferPreserved(); } } Loading Loading @@ -926,7 +963,6 @@ public abstract class HardwareRenderer { } beginFrame(); onPreDraw(dirty); HardwareCanvas canvas = mCanvas; Loading Loading @@ -1203,7 +1239,7 @@ public abstract class HardwareRenderer { void setup(int width, int height) { super.setup(width, height); if (mVsyncDisabled) { GLES20Canvas.disableVsync(); disableVsync(); } } Loading
core/jni/android_view_GLES20Canvas.cpp +5 −52 Original line number Diff line number Diff line Loading @@ -62,9 +62,9 @@ using namespace uirenderer; */ #ifdef USE_OPENGL_RENDERER /////////////////////////////////////////////////////////////////////////////// // ---------------------------------------------------------------------------- // Defines /////////////////////////////////////////////////////////////////////////////// // ---------------------------------------------------------------------------- // Debug #define DEBUG_RENDERER 0 Loading @@ -87,52 +87,9 @@ static struct { } gRectClassInfo; // ---------------------------------------------------------------------------- // Misc // Caching // ---------------------------------------------------------------------------- static jboolean android_view_GLES20Canvas_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_GLES20Canvas_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; } static void android_view_GLES20Canvas_disableVsync(JNIEnv* env, jobject clazz) { EGLDisplay display = eglGetCurrentDisplay(); eglGetError(); eglSwapInterval(display, 0); EGLint error = eglGetError(); if (error != EGL_SUCCESS) { RENDERER_LOGD("Could not disable v-sync (%x)", error); } } static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz, Caches::FlushMode mode) { if (Caches::hasInstance()) { Loading Loading @@ -853,9 +810,6 @@ static JNINativeMethod gMethods[] = { { "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable }, #ifdef USE_OPENGL_RENDERER { "nIsBackBufferPreserved", "()Z", (void*) android_view_GLES20Canvas_isBackBufferPreserved }, { "nPreserveBackBuffer", "()Z", (void*) android_view_GLES20Canvas_preserveBackBuffer }, { "nDisableVsync", "()V", (void*) android_view_GLES20Canvas_disableVsync }, { "nFlushCaches", "(I)V", (void*) android_view_GLES20Canvas_flushCaches }, { "nInitCaches", "()V", (void*) android_view_GLES20Canvas_initCaches }, { "nTerminateCaches", "()V", (void*) android_view_GLES20Canvas_terminateCaches }, Loading @@ -869,8 +823,7 @@ static JNINativeMethod gMethods[] = { { "nGetStencilSize", "()I", (void*) android_view_GLES20Canvas_getStencilSize }, { "nCallDrawGLFunction", "(II)I", (void*) android_view_GLES20Canvas_callDrawGLFunction }, { "nCallDrawGLFunction", "(II)I", (void*) android_view_GLES20Canvas_callDrawGLFunction }, { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save }, { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore }, Loading
core/jni/android_view_HardwareRenderer.cpp +96 −11 Original line number Diff line number Diff line Loading @@ -20,30 +20,105 @@ #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> #ifdef USE_OPENGL_RENDERER #include <EGL/egl_cache.h> 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 // ---------------------------------------------------------------------------- // Misc // Defines // ---------------------------------------------------------------------------- static void android_view_HardwareRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz, jstring diskCachePath) { // Debug #define DEBUG_RENDERER 0 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL); egl_cache_t::get()->setCacheFilename(cacheArray); env->ReleaseStringUTFChars(diskCachePath, cacheArray); // Debug #if DEBUG_RENDERER #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__) #else #define RENDERER_LOGD(...) #endif // ---------------------------------------------------------------------------- // Surface and display management // ---------------------------------------------------------------------------- static jboolean android_view_HardwareRenderer_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_HardwareRenderer_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; } static void android_view_HardwareRenderer_disableVsync(JNIEnv* env, jobject clazz) { EGLDisplay display = eglGetCurrentDisplay(); eglGetError(); eglSwapInterval(display, 0); EGLint error = eglGetError(); if (error != EGL_SUCCESS) { RENDERER_LOGD("Could not disable v-sync (%x)", error); } } // ---------------------------------------------------------------------------- // Tracing and debugging // ---------------------------------------------------------------------------- static void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz) { EGLDisplay dpy = eglGetCurrentDisplay(); EGLSurface surf = eglGetCurrentSurface(EGL_DRAW); eglBeginFrame(dpy, surf); } #endif // USE_OPENGL_RENDERER // ---------------------------------------------------------------------------- // Shaders // ---------------------------------------------------------------------------- static void android_view_HardwareRenderer_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 // ---------------------------------------------------------------------------- Loading @@ -51,10 +126,20 @@ static void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz) const char* const kClassPathName = "android/view/HardwareRenderer"; static JNINativeMethod gMethods[] = { { "nSetupShadersDiskCache", "(Ljava/lang/String;)V", (void*) android_view_HardwareRenderer_setupShadersDiskCache }, #ifdef USE_OPENGL_RENDERER { "nIsBackBufferPreserved", "()Z", (void*) android_view_HardwareRenderer_isBackBufferPreserved }, { "nPreserveBackBuffer", "()Z", (void*) android_view_HardwareRenderer_preserveBackBuffer }, { "nDisableVsync", "()V", (void*) android_view_HardwareRenderer_disableVsync }, { "nBeginFrame", "()V", (void*) android_view_HardwareRenderer_beginFrame }, #endif { "nSetupShadersDiskCache", "(Ljava/lang/String;)V", (void*) android_view_HardwareRenderer_setupShadersDiskCache }, }; int register_android_view_HardwareRenderer(JNIEnv* env) { Loading