How contexts work in JNI?

Started by lemmy101, September 14, 2013, 14:24:29

Previous topic - Next topic

lemmy101

Hey all, I'm trying to optimize some areas of the code, and wanted to try writing some native code to handle the high traffic areas that I'm finding it difficult to speed up within java any more. Obviously I need to get into native code with an active context.

Problem is when I go through jni into native code, any opengl call causes illegal access exceptions. Is the native code not on the same thread as the java code that calls it? Should I not have an active opengl context or is there something I have to do to pass / use it?

I'm using GLEW in native code incidentally, I'm not sure if that's causing the problem but it's the only way I can seem to get at the VBO functions as they don't seem to be appear in my VS library headers, which seem to consist of only GL.h and GLU.h neither of which contain the relevant functions.

Has anyone had any success with doing this?

thanks!

chris

spasi

I haven't used GLEW, but it looks like you have to call glewInit() after making an LWJGL context current.

lemmy101

Thanks! I tried glewInit before and after that it got through some initial calls:

glewInit();

bufferSize = (256 * 256);
GLuint buffer = 0;
   
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

But then...

>> EXCEPTION glBufferDataARB(GL_ARRAY_BUFFER_ARB, bufferSize, &buffer, GL_STREAM_DRAW_ARB);

I still get an access violation error deep inside the opengl code, (which from my ancient C++ knowledge means probably an illegal memory overwrite) on creating VBOs in for no apparent reason. Unless I'm doing something really stupid but the calls mirror exactly what java was doing.

I assumed that glewInit made a new context, which is what documentation I read seemed to suggest, which obviously is not what I want. I know the LWJGL context is current in the thread at the point that java calls the jni, and that the native callstack is deep with jvm.dll calls, so seems to share the same thread from what I can see, so I would assume that context is still valid in the native code. That is a big assumption though as I really don't know how the jvm/jni works with the computer architecture. Is there any way to get some nice passable integer handle in lwjgl to pass and point it there in native, and is there much overhead for this? as if it's not a negligible hit when called many thousands of times a frame (or not necessary at all) it may invalidate the entire point of doing stuff in native.

I dunno maybe it's something else I'm doing wrong, blergh. Will fire up the laptop and check for more specific information.

spasi

Nope, glewInit() does not create a new context, it simply uses whatever context is current in the current thread to initialize its function pointers and whatever other internal state it needs.

You also don't need to pass a context handle to your native code. OpenGL functions implicitly use the thread's current context, unlike OpenCL for example, which uses the function arguments to determine the queue -> context -> device.

If glEnableClientState works, there's no reason for glBufferDataARB to fail, unless there's a bug in your code or GLEW has not initialized it for some reason. Have you tried the core version (glBufferData) by any chance?

lemmy101

Thanks :)

Update after going on laptop: It's not actually crashing in the glGenBuffer at all, so yeah I get the feeling glewInit has done its job. However it's crashing in a subsequent new call, which informs me the heap has been corrupted. Literal code is as follows and I guess it's likely I'm doing something daft:

       glewInit();

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	bufferSizeInVertices = bufferSize / SpriteRenderer::VERTEX_SIZE;
	indexBufferSize = bufferSizeInVertices * 3;	

	vbo = new GLVertexBufferObject*[numBuffers];
	ibo = new GLVertexBufferObject*[numBuffers];
	for (int i = 0; i < numBuffers; i ++) {
		vbo[i] = new GLVertexBufferObject(bufferSize, GL_ARRAY_BUFFER_ARB, GL_STREAM_DRAW_ARB);
		vbo[i]->create();
		ibo[i] = new GLVertexBufferObject(indexBufferSize, GL_ELEMENT_ARRAY_BUFFER_ARB, GL_STREAM_DRAW_ARB);
		ibo[i]->create();
	}


And the create function:

void GLVertexBufferObject::create()
{
	id = this->IDMAX++;;
	glGenBuffersARB(id, &buffer);

}


glGenBuffers has exactly the same problem, btw.

(constructor its failing to new on. nothing untoward afaik):

GLVertexBufferObject::GLVertexBufferObject( long size, int type, int usage )
{

	this->size = size;
	this->type = type;
	this->usage = usage;
}


The for loop for buffers goes around once without a hitch, and on the 2rd iteration crashes on this line's new with a corrupted heap exception:

for (int i = 0; i < numBuffers; i ++) {
>>>>>>>>>       vbo[i] = new GLVertexBufferObject(bufferSize, GL_ARRAY_BUFFER_ARB, GL_STREAM_DRAW_ARB);
		vbo[i]->create();
		ibo[i] = new GLVertexBufferObject(indexBufferSize, GL_ELEMENT_ARRAY_BUFFER_ARB, GL_STREAM_DRAW_ARB);
		ibo[i]->create();
	}


If I comment out the two create lines that do gen buffer call, it doesn't crash out on the news, no matter how many I create, so I can only assume something about the glGenBuffersARB is corrupting memory or else my 10 year absence from C++ is making me do something frightfully embarrassing and dumb :/

lemmy101

So it turns out I WAS doing something stupid.

Params for glGenBuffersARB were wrong, was passing in an ID instead of the # buffers I wanted to create.

Speaking of which, why in holy hell when searching for this:

http://lmgtfy.com/?q=glGenBuffersARB+opengl+reference

Do I not actually get to an OpenGL code reference, or have one as an option in the results? Is there really no complete OpenGL reference on the entire internet? Or am I missing something?

Madness!