opengl es – android ANativeWindow_lock api doesn't work for GLSurfaceView-ThrowExceptions

Exception or error:

I’m finding methods to get drawing buffers very quickly from Android GLSurfaceView.

eventhough I know glreadpixel can do this job, glreadpixel is too slow to get drawing buffer.

I want to read buffers maintaining 30 fps.

ANativeWindow api seems like what I am looking for..

ANativeWindow api performance

I couldn’t found any example of ANativeWindow api for GLSurfaceView.

My procedure :

  1. Send GLSurfaceView surface to jni code.(using GLSurfaceView.getHolder().getSurface())**
  2. Get Window handle using ANativeWindow_fromSurface method.**
  3. Set Window Buffer**
  4. Lock surface and get window buffer**
  5. Do something using this buffer**
  6. UnlockAndPost window**

I tried below jni code using Android “BasicGLSurfaceView” example.

JNIEXPORT void JNICALL Java_com_example_android_basicglsurfaceview_BasicGLSurfaceViewActivity_readSurface(JNIEnv* jenv, jobject obj, jobject surface)
{

LOG_INFO("Java_com_example_android_basicglsurfaceview_BasicGLSurfaceViewActivity_readSurface");
if (surface != 0) {
    ANativeWindow *window = ANativeWindow_fromSurface(jenv, surface);
    LOG_INFO("Got window %p", window);
    if(window > 0)
    {
        int width = ANativeWindow_getWidth(window);
        int height = ANativeWindow_getHeight(window);

        LOG_INFO("Got window %d %d", width,height);

        ANativeWindow_setBuffersGeometry(window,0,0,WINDOW_FORMAT_RGBA_8888);

        ANativeWindow_Buffer buffer;
        memset((void*)&buffer,0,sizeof(buffer));

        int lockResult = -22;

            lockResult = ANativeWindow_lock(window, &buffer, NULL);
            if (lockResult == 0) {    \
              LOG_INFO("ANativeWindow_locked");
              ANativeWindow_unlockAndPost(window);
            }
            else
            {
                LOG_INFO("ANativeWindow_lock failed error %d",lockResult);
            }

        LOG_INFO("Releasing window");

        ANativeWindow_release(window);
    }


} else {
     LOG_INFO("surface is null");
}

return;

}

ANativeWindow_fromSurface and getHeight, setBuffersGeometry api work well.

But ANativeWindow_lock api always fails returning -22 value.

Error Message

[Surfaceview] connect: already connected(cur=1, req=2)

I tried this code at onDrawFrame in Renderer or main Thread or onSurfaceChanged.

but Always It return -22 value.

I am calling this api at wrong place?

is it possible to use ANativeWindow_lock for GLSurfaceView?

Here is my example code

Any help will be really appreciated~

How to solve:

Try doing this instead:

http://forums.arm.com/index.php?/topic/15782-glreadpixels/

Hopefully you can use an ANativeWindow for the buffer so you don’t have to call gralloc directly…

###

I’m not sure that the memset operation is needed.

This worked for me:

ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
if(window > 0){
    unsigned char *data = ... // an RGBA(8888) image
    int32_t w = ANativeWindow_getWidth(window);
    int32_t h = ANativeWindow_getHeight(window);
    ANativeWindow_setBuffersGeometry(window, w, h, WINDOW_FORMAT_RGBA_8888);
    ANativeWindow_Buffer buffer;
    int lockResult = -1;
    lockResult = ANativeWindow_lock(window, &buffer, NULL);
    if(lockResult == 0){
        //write data
        memcpy(buffer.bits, data,  w * h * 4);
        ANativeWindow_unlockAndPost(window);
    }
    //free data...
    ANativeWindow_release(window);
}

###

When you encountered the same error message,

[Surfaceview] connect: already connected

You can resolve this by GLSurface.onPause() before calling the native part.
You can render the by ANativeWindow_lock, write frame buffer, ANativeWindow_unlockAndPost in native code.

// Java
SurfaceHolder holder  = mGLSurfaceView.getHolder();
mPreviewSurface  = holder.getSurface();
mGLSurfaceView.onPause();
camera.nativeSetPreviewDisplay(mPreviewSurface);

I call GLSurfaceView onPause() only for release EGL context. The GLSurfaceView will be rendered by native code.

GLSurfaceView

At least I think this can be the answer for the question “is it possible to use ANativeWindow_lock for GLSurfaceView?”.
Yes it is.

But in this way, you can render the view only using window buffer. You cannot use opengl api because GLSurfaceView.Renderer onDrawFrame() is not called after GLSurfaceView paused. It still show the better performance than using but it is useless if you need opengl api.

Shader calls should be within a GL thread that is onSurfaceChanged(), onSurfaceCreated() or onDrawFrame()

Leave a Reply

Your email address will not be published. Required fields are marked *