EXTERN_C_ENTER

JNIEXPORT void JNICALL Java_org_lwjgl_opengles_NVReadBuffer_glReadBufferNV(JNIEnv *__env, jclass clazz, jint mode) {
    glReadBufferNVPROC glReadBufferNV = (glReadBufferNVPROC)tlsGetFunction(745);
    UNUSED_PARAM(clazz)
    glReadBufferNV(mode);
}
bool SurfaceTextureBuffer::MakeCurrent(uint8 nFace)
{
	// Check whether the data is valid and whether there's a texture buffer
	if (m_cTextureBufferHandler.GetResource() && GetTextureBuffer()) {
		// Set target face
		if (GetTextureBuffer()->GetType() == PLRenderer::Resource::TypeTextureBufferCube)
			m_nFace = nFace;
		else
			m_nFace = 0;

		// Cleanup texture buffer handlers
		for (uint32 i=0; i<m_lstTextureBufferHandler.GetNumOfElements(); i++)
			delete m_lstTextureBufferHandler[i];
		m_lstTextureBufferHandler.Clear();

		// Add primary texture buffer handler
		PLRenderer::ResourceHandler *pTextureBufferHandler = new PLRenderer::ResourceHandler();
		pTextureBufferHandler->SetResource(m_cTextureBufferHandler.GetResource());
		m_lstTextureBufferHandler.Add(pTextureBufferHandler);

		// Frame buffer object used?
		if (m_pFrameBufferObject && m_cTextureBufferHandler.GetResource()) {
			m_pFrameBufferObject->SwitchTarget(static_cast<PLRenderer::TextureBuffer&>(*m_cTextureBufferHandler.GetResource()), 0, nFace);
			m_pFrameBufferObject->Bind();

			// Need rendering to depth only
			PLRenderer::TextureBuffer::EPixelFormat nFormat = GetTextureBuffer()->GetFormat();
			const Extensions &cExtensions = static_cast<Renderer&>(GetRenderer()).GetContext().GetExtensions();
			if (nFormat == PLRenderer::TextureBuffer::D16 || nFormat == PLRenderer::TextureBuffer::D24 || nFormat == PLRenderer::TextureBuffer::D32) {
				// "GL_NV_read_buffer"-extension available?
				if (cExtensions.IsGL_NV_read_buffer())
					glReadBufferNV(GL_NONE);
			} else {
				// "GL_ARB_draw_buffers" & "GL_NV_fbo_color_attachments" extensions available?
				if (cExtensions.IsGL_ARB_draw_buffers() && cExtensions.IsGL_NV_fbo_color_attachments()) {
					// Set draw buffers
					static const GLenum db[16] = { GL_COLOR_ATTACHMENT0_NV, GL_COLOR_ATTACHMENT1_NV, GL_COLOR_ATTACHMENT2_NV, GL_COLOR_ATTACHMENT3_NV,
												   GL_COLOR_ATTACHMENT4_NV, GL_COLOR_ATTACHMENT5_NV, GL_COLOR_ATTACHMENT6_NV, GL_COLOR_ATTACHMENT7_NV,
												   GL_COLOR_ATTACHMENT8_NV, GL_COLOR_ATTACHMENT9_NV, GL_COLOR_ATTACHMENT10_NV, GL_COLOR_ATTACHMENT11_NV,
												   GL_COLOR_ATTACHMENT12_NV, GL_COLOR_ATTACHMENT13_NV, GL_COLOR_ATTACHMENT14_NV, GL_COLOR_ATTACHMENT15_NV};
					glDrawBuffersARB(m_nMaxColorTargets, db);
				}
			}
		}

		// Enable/disable multisample - "shouldn't" have an effect when render to texture, but safe is safe :D
		GetRenderer().SetRenderState(PLRenderer::RenderState::MultisampleEnable, !(GetFlags() & NoMultisampleAntialiasing));

		// Done
		return true;
	}

	// Error!
	return false;
}
void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
    bindInternal(FramebufferTarget::Read);

    #ifndef MAGNUM_TARGET_GLES2
    glReadBuffer(buffer);
    #elif !defined(CORRADE_TARGET_NACL)
    glReadBufferNV(buffer);
    #else
    static_cast<void>(buffer);
    CORRADE_ASSERT_UNREACHABLE();
    #endif
}
bool SurfaceTextureBuffer::UnmakeCurrent()
{
	// Check whether the data is valid
	if (!m_cTextureBufferHandler.GetResource())
		return false; // Error!
	Renderer &cRenderer = static_cast<Renderer&>(GetRenderer());

	// Frame buffer object used?
	if (m_pFrameBufferObject) {
		m_pFrameBufferObject->Unbind();

		// Try to build mipmaps automatically on the GPU?
		if (GetFlags() & Mipmaps) {
			PLRenderer::TextureBuffer *pTextureBuffer = cRenderer.GetTextureBuffer(0);
			cRenderer.SetTextureBuffer(0, static_cast<PLRenderer::TextureBuffer*>(m_cTextureBufferHandler.GetResource()));
			switch (m_cTextureBufferHandler.GetResource()->GetType()) {
				case PLRenderer::Resource::TypeTextureBuffer2D:
					glGenerateMipmap(GL_TEXTURE_2D);
					break;

				case PLRenderer::Resource::TypeTextureBufferCube:
					glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
					break;
			}
			cRenderer.SetTextureBuffer(0, pTextureBuffer);
		}

		PLRenderer::TextureBuffer::EPixelFormat nFormat = GetTextureBuffer()->GetFormat();
		if (nFormat == PLRenderer::TextureBuffer::D16 || nFormat == PLRenderer::TextureBuffer::D24 || nFormat == PLRenderer::TextureBuffer::D32) {
			// "GL_NV_read_buffer"-extension available?
			if (static_cast<Renderer&>(GetRenderer()).GetContext().GetExtensions().IsGL_NV_read_buffer())
				glReadBufferNV(GL_NONE);
		}

	// Do only use glCopyTexSubImage2D()
	} else if (m_lstTextureBufferHandler.GetNumOfElements()) {
		PLRenderer::TextureBuffer *pTextureBuffer = static_cast<PLRenderer::TextureBuffer*>(m_lstTextureBufferHandler[0]->GetResource());
		if (pTextureBuffer) {
			cRenderer.MakeTextureBufferCurrent(*pTextureBuffer, 0);
			switch (pTextureBuffer->GetType()) {
				case PLRenderer::Resource::TypeTextureBuffer2D:
					glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GetSize().x, GetSize().y);
					break;

				case PLRenderer::Resource::TypeTextureBufferCube:
					glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+m_nFace, 0, 0, 0, 0, 0, GetSize().x, GetSize().y);
					break;
			}
		}
	}

	// Cleanup texture buffer handlers
	for (uint32 i=0; i<m_lstTextureBufferHandler.GetNumOfElements(); i++)
		delete m_lstTextureBufferHandler[i];
	m_lstTextureBufferHandler.Clear();

	// Reset target face
	m_nFace = 0;

	// Done
	return true;
}