Android NativeActivity Стандартное приложение OpenGL-ES: как получить менее полноэкранную поверхность - PullRequest
1 голос
/ 04 ноября 2011

У меня есть нативное приложение для Android, использующее оболочку Google native_app_glue.Я хотел бы получить менее чем полноэкранную поверхность для рендеринга GLES в.В приложениях GLES, использующих уровень Java, полученный из Activity, это достигается с помощью getWindow (). SetLayer () на уровне Java.Однако ситуация в моем проекте не позволяет мне использовать это решение.

С уровнем nativeActivtiy и native_app_glue я могу использовать JNI для получения классов Java и обратного вызова в Java, но не могу изменять иерархию View.При обратном вызове setLayers () из моего C-кода через JNI я получаю эту ошибку, поскольку NativeActivity не находится в том же потоке, в котором была создана иерархия View.

E / AndroidRuntime (21503): android.view.ViewRoot $ CalledFromWrongThreadException: только исходный поток, создавший иерархию представлений, может касаться его представлений.

И вот мой код для этого:

// Call Java to set  Window size
//-----------------------------------------------------------------------------
int CallJavaWindowSize(struct android_app* state, jint width, jint height)
//-----------------------------------------------------------------------------
{
    JNIEnv *env;
    jclass nativeActivityClass;
    jobject nativeActivityObj;
    jmethodID mid;
    jobject windowObj;
    bool didAttachment = false;
    int ret = -1;
    JavaVMAttachArgs JVMAttachArgs;

    jint result = state->activity->vm->GetEnv((void**) &env, JNI_VERSION_1_6); 

    if (!env  && result == JNI_EDETACHED)
    {
        JVMAttachArgs.version = JNI_VERSION_1_6;
        JVMAttachArgs.name = "NativeThread";
        JVMAttachArgs.group = NULL;
        if (state->activity->vm->AttachCurrentThread(&env, NULL) < 0)
        {
            __android_log_print(ANDROID_LOG_ERROR, "PowerLift", "CallJavaWindowSize() Failed to attach to thread");
            return ret;
        }
        __android_log_print(ANDROID_LOG_DEBUG, "PowerLift", "CallJavaWindowSize() attached to Thread");
        didAttachment = true;
    }
    else if (result < 0)
    {
            __android_log_print(ANDROID_LOG_ERROR, "PowerLift", "CallJavaWindowSize() Failed to GetEnv()");
            return ret;
    }

    // retrieves NativeActivity class
    nativeActivityObj = state->activity->clazz;
    //nativeActivityClass = env->FindClass("android/app/NativeActivity");
    nativeActivityClass = env->GetObjectClass(nativeActivityObj);
    if (!nativeActivityClass)
    {
        __android_log_print(ANDROID_LOG_ERROR, "PowerLift", "CallJavaWindowSize() Failed to Find NativeActivity class");
        return ret;
    }

    //Run getWindow().setLayout(width,height)
    mid = env->GetMethodID(nativeActivityClass, "getWindow", "()Landroid/view/Window;");
    if (mid == 0)
    {
        __android_log_print(ANDROID_LOG_ERROR, "PowerLift", "CallJavaWindowSize() Failed to get method getWindow() with signature = ()Landroid/view/Window;");
        return ret;
    }

    windowObj = env->CallObjectMethod(nativeActivityObj, mid);
    if (windowObj == 0)
    {
        __android_log_print(ANDROID_LOG_ERROR, "PowerLift", "CallJavaWindowSize() Failed to CallObjectMethod for mid getWindow()");
        return ret;
    }

    jclass classWindow = env->FindClass("android/view/Window");
    mid = env->GetMethodID(classWindow, "setLayout", "(II)V");
    env->CallVoidMethod(windowObj, mid, width, height);


    if (didAttachment)
        state->activity->vm->DetachCurrentThread();

    return 0;
}

Решение, которое некоторые из вас могутПредлагаю использовать glViewport (), чтобы рисовать меньше, чем в полноэкранном режиме.Это решение работает визуально, но имеет низкую производительность, поскольку драйвер EGL по-прежнему обрабатывает полноэкранные поверхности.

Мне интересно, является ли этот подход лучшим решением, поскольку он архитектурно довольно отличается от использования встроенной оболочки приложения: a) ditch nativeприложение склеивает оболочку и запускает собственный код (или, по крайней мере, его часть) в том же потоке, что и JVM; б) наследует от NativeActivity класс Java, который создает иерархию View через setContentView () c) в собственном коде, который выполняется в том же потоке, что иJava использует JNI для вызова setLayout () d) остальная часть нативного кода может выполняться в другом потоке по мере необходимости

Я не уверен, выполним ли описанный выше подход, если я столкнусь с препятствием с этим.

1 Ответ

0 голосов
/ 29 марта 2013

Если вы пытаетесь выполнить рендеринг из пиксельного буфера, вы можете использовать glSubTexImage2D().

...