Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c96812cb authored by Jack Palevich's avatar Jack Palevich
Browse files

Allow pre-Donut apps to use indirect Buffers in GL11 Pointer methods.

Apps targeting Donut and newer will throw an exception.

We use a heuristic to determine whether an app is pre-Donut or not:
We take the address space's __progname, and use that as the application's
package name. For simple applications this is correct.
parent c2fb706a
Loading
Loading
Loading
Loading
+17 −0
Original line number Original line Diff line number Diff line
@@ -4,14 +4,31 @@ set -e
rm -rf out generated
rm -rf out generated


mkdir out
mkdir out

# Create dummy Java files for Android APIs that are used by the code we generate.
# This allows us to test the generated code without building the rest of Android.

mkdir -p out/javax/microedition/khronos/opengles
mkdir -p out/javax/microedition/khronos/opengles
mkdir -p out/com/google/android/gles_jni
mkdir -p out/com/google/android/gles_jni
mkdir -p out/android/app
mkdir -p out/android/graphics
mkdir -p out/android/graphics
mkdir -p out/android/opengl
mkdir -p out/android/opengl
mkdir -p out/android/content
mkdir -p out/android/content/pm
mkdir -p out/android/os
mkdir -p out/android/util


echo "package android.graphics;" > out/android/graphics/Canvas.java
echo "package android.graphics;" > out/android/graphics/Canvas.java
echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
echo "public interface Canvas {}" >> out/android/graphics/Canvas.java


echo "package android.app; import android.content.pm.IPackageManager; public class ActivityThread { public static final ActivityThread currentActivityThread() { return null; } public static final String currentPackageName(){ return null; } public static IPackageManager getPackageManager() { return null;} }" > out/android/app/ActivityThread.java
# echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;};	}" > out/android/os/Build.java
echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java

GLFILE=out/javax/microedition/khronos/opengles/GL.java
GLFILE=out/javax/microedition/khronos/opengles/GL.java
cp stubs/jsr239/GLHeader.java-if $GLFILE
cp stubs/jsr239/GLHeader.java-if $GLFILE


+40 −5
Original line number Original line Diff line number Diff line
@@ -44,9 +44,11 @@ static jclass OOMEClass;
static jclass UOEClass;
static jclass UOEClass;
static jclass IAEClass;
static jclass IAEClass;
static jclass AIOOBEClass;
static jclass AIOOBEClass;
static jclass G11ImplClass;
static jmethodID getBasePointerID;
static jmethodID getBasePointerID;
static jmethodID getBaseArrayID;
static jmethodID getBaseArrayID;
static jmethodID getBaseArrayOffsetID;
static jmethodID getBaseArrayOffsetID;
static jmethodID allowIndirectBuffersID;
static jfieldID positionID;
static jfieldID positionID;
static jfieldID limitID;
static jfieldID limitID;
static jfieldID elementSizeShiftID;
static jfieldID elementSizeShiftID;
@@ -62,13 +64,17 @@ nativeClassInitBuffer(JNIEnv *_env)
    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);


    jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
    G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);

    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
            "getBasePointer", "(Ljava/nio/Buffer;)J");
            "getBasePointer", "(Ljava/nio/Buffer;)J");
    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");

    allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal,
            "allowIndirectBuffers", "(Ljava/lang/String;)Z");
    positionID = _env->GetFieldID(bufferClass, "position", "I");
    positionID = _env->GetFieldID(bufferClass, "position", "I");
    limitID = _env->GetFieldID(bufferClass, "limit", "I");
    limitID = _env->GetFieldID(bufferClass, "limit", "I");
    elementSizeShiftID =
    elementSizeShiftID =
@@ -118,6 +124,9 @@ getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
    
    
    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
            getBaseArrayID, buffer);
            getBaseArrayID, buffer);
    if (*array == NULL) {
        return (void*) NULL;
    }
    offset = _env->CallStaticIntMethod(nioAccessClass,
    offset = _env->CallStaticIntMethod(nioAccessClass,
            getBaseArrayOffsetID, buffer);
            getBaseArrayOffsetID, buffer);
    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
@@ -132,17 +141,43 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
					   commit ? 0 : JNI_ABORT);
					   commit ? 0 : JNI_ABORT);
}
}


extern "C" {
extern char*  __progname;
}

static bool
allowIndirectBuffers(JNIEnv *_env) {
    static jint sIndirectBufferCompatability;
    if (sIndirectBufferCompatability == 0) {
        jobject appName = _env->NewStringUTF(::__progname);
        sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1;
    }
    return sIndirectBufferCompatability == 2;
}

static void *
static void *
getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
    char* buf = (char*) _env->GetDirectBufferAddress(buffer);
    if (!buffer) {
        return NULL;
    }
    void* buf = _env->GetDirectBufferAddress(buffer);
    if (buf) {
    if (buf) {
        jint position = _env->GetIntField(buffer, positionID);
        jint position = _env->GetIntField(buffer, positionID);
        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
        buf += position << elementSizeShift;
        buf = ((char*) buf) + (position << elementSizeShift);
    } else {
        if (allowIndirectBuffers(_env)) {
            jarray array = 0;
            jint remaining;
            buf = getPointer(_env, buffer, &array, &remaining);
            if (array) {
                releasePointer(_env, array, buf, 0);
            }
        } else {
        } else {
            _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
            _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
        }
        }
    return (void*) buf;
    }
    return buf;
}
}


static int
static int
+30 −3
Original line number Original line Diff line number Diff line
@@ -18,6 +18,12 @@


package com.google.android.gles_jni;
package com.google.android.gles_jni;


import android.app.ActivityThread;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.os.Build;
import android.util.Log;

import java.nio.Buffer;
import java.nio.Buffer;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL10Ext;
import javax.microedition.khronos.opengles.GL10Ext;
@@ -46,3 +52,24 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
        throw new UnsupportedOperationException("glGetPointerv");
        throw new UnsupportedOperationException("glGetPointerv");
    }
    }


    private static boolean allowIndirectBuffers(String appName) {
        boolean result = false;
        int version = 0;
        IPackageManager pm = ActivityThread.getPackageManager();
        try {
            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
            if (applicationInfo != null) {
                version = applicationInfo.targetSdkVersion;
            }
        } catch (android.os.RemoteException e) {
            // ignore
        }
        Log.e("OpenGLES", String.format(
            "Application %s (SDK target %d) called a GL11 Pointer method with an indirect Buffer.",
            appName, version));
        if (version <= Build.VERSION_CODES.CUPCAKE) {
            result = true;
        }
        return result;
    }