EXTERN_C_ENTER

JNIEXPORT void JNICALL Java_org_lwjgl_opengl_NVTransformFeedback_glBeginTransformFeedbackNV(JNIEnv *__env, jclass clazz, jint primitiveMode) {
    glBeginTransformFeedbackNVPROC glBeginTransformFeedbackNV = (glBeginTransformFeedbackNVPROC)tlsGetFunction(2144);
    UNUSED_PARAM(clazz)
    glBeginTransformFeedbackNV(primitiveMode);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
	void GLRenderToVertexBuffer::update(SceneManager* sceneMgr)
	{
		checkGLError(true, false, "start of GLRenderToVertexBuffer::update");

		size_t bufSize = mVertexData->vertexDeclaration->getVertexSize(0) * mMaxVertexCount;
		if (mVertexBuffers[0].isNull() || mVertexBuffers[0]->getSizeInBytes() != bufSize)
		{
			//Buffers don't match. Need to reallocate.
			mResetRequested = true;
		}
		
		//Single pass only for now
		Ogre::Pass* r2vbPass = mMaterial->getBestTechnique()->getPass(0);
		//Set pass before binding buffers to activate the GPU programs
		sceneMgr->_setPass(r2vbPass);
		
		checkGLError(true, false);

		bindVerticesOutput(r2vbPass);

		RenderOperation renderOp;
		size_t targetBufferIndex;
		if (mResetRequested || mResetsEveryUpdate)
		{
			//Use source data to render to first buffer
			mSourceRenderable->getRenderOperation(renderOp);
			targetBufferIndex = 0;
		}
		else
		{
			//Use current front buffer to render to back buffer
			this->getRenderOperation(renderOp);
			targetBufferIndex = 1 - mFrontBufferIndex;
		}

		if (mVertexBuffers[targetBufferIndex].isNull() || 
			mVertexBuffers[targetBufferIndex]->getSizeInBytes() != bufSize)
		{
			reallocateBuffer(targetBufferIndex);
		}

		GLHardwareVertexBuffer* vertexBuffer = static_cast<GLHardwareVertexBuffer*>(mVertexBuffers[targetBufferIndex].getPointer());
		GLuint bufferId = vertexBuffer->getGLBufferId();

		//Bind the target buffer
		glBindBufferOffsetNV(GL_TRANSFORM_FEEDBACK_BUFFER_NV, 0, bufferId, 0);

		glBeginTransformFeedbackNV(getR2VBPrimitiveType(mOperationType));

		glEnable(GL_RASTERIZER_DISCARD_NV);    // disable rasterization

		glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV, mPrimitivesDrawnQuery);

		RenderSystem* targetRenderSystem = Root::getSingleton().getRenderSystem();
		//Draw the object
		targetRenderSystem->_setWorldMatrix(Matrix4::IDENTITY);
		targetRenderSystem->_setViewMatrix(Matrix4::IDENTITY);
		targetRenderSystem->_setProjectionMatrix(Matrix4::IDENTITY);
		if (r2vbPass->hasVertexProgram())
		{
			targetRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM, 
				r2vbPass->getVertexProgramParameters(), GPV_ALL);
		}
		if (r2vbPass->hasGeometryProgram())
		{
			targetRenderSystem->bindGpuProgramParameters(GPT_GEOMETRY_PROGRAM,
				r2vbPass->getGeometryProgramParameters(), GPV_ALL);
		}
		targetRenderSystem->_render(renderOp);
		
		//Finish the query
		glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV);
		glDisable(GL_RASTERIZER_DISCARD_NV);
		glEndTransformFeedbackNV();

		//read back query results
		GLuint primitivesWritten;
		glGetQueryObjectuiv(mPrimitivesDrawnQuery, GL_QUERY_RESULT, &primitivesWritten);
		mVertexData->vertexCount = primitivesWritten * getVertexCountPerPrimitive(mOperationType);

		checkGLError(true, true, "GLRenderToVertexBuffer::update");

		//Switch the vertex binding if neccesary
		if (targetBufferIndex != mFrontBufferIndex)
		{
			mVertexData->vertexBufferBinding->unsetAllBindings();
			mVertexData->vertexBufferBinding->setBinding(0, mVertexBuffers[targetBufferIndex]);
			mFrontBufferIndex = targetBufferIndex;
		}

		glDisable(GL_RASTERIZER_DISCARD_NV);    // enable rasterization

		//Clear the reset flag
		mResetRequested = false;
	}