开发者

Passing java.nio.IntBuffer to C function in an Android game

I'd like to be able to add a little native C code in my Android app. I have an IntBuffer which I use as a parameter to OpenGL's glColorPointer method. This is populated/used something like this:

private IntBuffer mColourBuffer;
int[] colours = new int[10 * 4];   // 10 dots, 4 colour components per dot


ByteBuffer vbb3 = ByteBuffer.allocateDirect(10 * 4 * 4);   
vbb3.order(ByteOrder.nativeOrder());
mColourBuffer = vbb3.asIntBuffer();
mColourBuffer.put(colours);
mColourBuffer.position(0);

gl.glColorPointer(4, GL10.GL_FIXED, 0, mColourBuffer); 

I'd like to make changes to this buffer but it's too slow from Java, so I'd like to do it with native code. I've been looking for a simple example but I can't find anything which I can make sense of, or which works. A lot of the documentation I've seen talks about passing elements over, but surely all I want is a pointer. Passing a pointer and operating on the memory it points to should be extremely efficient; passing loads of memory between Java and C would kill any speed improvements made possibly by being able to operate on the memory from C.

So far I've come up with this:

void Java_com_poldie_myTouch2_myclass_mymethod( JNIEnv* env, jobject thiz, jintArray arr, int n )
{
    jint *c_array;

    c_array = (*env)->GetIntArrayElements(env, arr, NULL);

    (*env)->ReleaseIntArrayElements(env, arr, c_array, 0);


 return;


}

Which I can call like this:

public native void  mymethod(IntBuffer intbuf, int n);

mymethod(mColourBuffer , n);

Which at least runs and seems to do the call, but any attempt to operate on c_array (either as a dereferenced pointer or an array) causes the program to exit immediately.

Am I on the right track here? Can I pass a pointer to the memory behind mColourB开发者_StackOverflow社区uffer to my C code and operate on it upon return to my Java code?


Answering my own question here, it appears the answer is to take your array of vertices (which you're manipulating each frame using Java) and write them into a Direct Buffer.

In my example above, I'd want to somehow populate the Direct Buffer mColourBuffer each frame with whatever is in the local array 'colours'. Turns out you'd want something like:

JNIfastPutf(mfColourBuffer, colours, nCount); 

where nCount is the number of bytes to copy. The (Native, C) function JNIfastPutf looks like this:

void Java_com_a_b_c_JNIfastPutf(JNIEnv* env, jobject thiz, jobject jo, jfloatArray jfa, int n)
{
    float* pDst = (float*) (*env)->GetDirectBufferAddress(env, jo);
    float* pSrc = (float*) (*env)->GetPrimitiveArrayCritical(env, jfa, 0);              
    memcpy( pDst, pSrc, n  );

   (*env)->ReleasePrimitiveArrayCritical(env, jfa, pSrc, 0);
}

I found the following link very helpful (my function is a slightly modified C version of their C++ example):

http://www.badlogicgames.com/wiki/index.php/Direct_Bulk_FloatBuffer.put_is_slow

They explain that you really need this sort of approach if you're working with floats; using ints is supposedly much faster, although that's where I started, and in any event, their native code shows in the region of a 20 -> 100% speed increase over the 'fast' int version, so there would appear to be little reason not to do it!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜