#include <../arch/arch.h>
#include <dlfcn.h>

#ifdef	ARCH_WINDOWING_SUPPORTED

/* see ../../TODO */

static void *libgl_handle = NULL;

static char *libgl_name = "libGL.so";

V_LOCAL vboolean V_CALL
vgl_load_proc_init(char *proc_name,void **ptr_ret,vboolean *terminate);

vboolean V_CALL (*vgl_load_proc)(char *proc_name,
	void **ptr_ret,vboolean *terminate) = vgl_load_proc_init;

#ifdef	BASEGL11_DYNAMIC

vboolean V_CALL (*vgl_load_base_proc)(char *proc_name,
	void **ptr_ret,vboolean *terminate) = vgl_load_proc_init;

#endif	/* BASEGL11_DYNAMIC */

V_LOCAL vboolean V_CALL
vgl_load_proc_real(char *proc_name,void **ptr_ret,vboolean *terminate)
{
	/*
	 * At this moment LibV global lock must be hold.
	 */
	ARCH_CALLER_NAME(vgl_load_proc)
	void *proc = (void*)dlsym(libgl_handle,proc_name);
	if(*ptr_ret && (*ptr_ret != proc))
	{
		/*
		 * This should never happen under X11 + GLX.
		 */
		ARCH_ERROR("different retval of glsym(): libGL.so broken ?");
		*terminate = true;
		return false;
	}
	if(proc)
	{
		*ptr_ret = (void*)proc;
		return true;
	}
	return false;
}

V_LOCAL vboolean V_CALL
vgl_load_proc_init(char *proc_name,void **ptr_ret,vboolean *terminate)
{
	ARCH_CALLER_NAME(vgl_load_proc)
	vboolean result = false;
	char libglsopath[_MAX_PATH];
	char libglsodir[_MAX_PATH], libglsoname[_MAX_PATH], libglsoext[_MAX_PATH];
	V_ASSERT(!libgl_handle);
	fsSplitPath(libgl_name,libglsodir,libglsoname,libglsoext);
	libvLockGlobal();
	for(;;)
	{
		if(strlen(libglsodir))
		{
			/*
			 * Full qualified path: no heuristics, please.
			 */
			libgl_handle = dlopen(libgl_name,RTLD_LAZY);
		}
		else
		{
			/*
			 * Try to open it from current directory first.
			 */
			fsMakePath(libglsopath,"./",libglsoname,libglsoext);
			libgl_handle = dlopen(libglsopath,RTLD_LAZY);
			if(!libgl_handle)
				libgl_handle = dlopen(libgl_name,RTLD_LAZY);
		}
		if(!libgl_handle)
		{
			SYSCALL_FAILED_1STR("dlopen(): ", strSafe(dlerror()));
			break;
		}
		vgl_load_proc = vgl_load_proc_real;
#ifdef	BASEGL11_DYNAMIC
		vgl_load_base_proc = vgl_load_proc_real;
#endif	/* BASEGL11_DYNAMIC */
		result = (*vgl_load_proc)(proc_name, ptr_ret, terminate);
		break;
	}
	libvUnlockGlobal();
	return result;
}

#if 0

void (*(*glx_get_proc_address)(const GLubyte *procname))(void) = NULL;

static void *libgl_handle = NULL;

V_LOCAL vboolean V_CALL
vgl_load_proc_init(char *proc_name,void **ptr_ret,vboolean *terminate);

vboolean V_CALL (*vgl_load_proc)(char *proc_name,void **ptr_ret,vboolean *terminate) = vgl_load_proc_init;

V_LOCAL vboolean V_CALL
vgl_load_proc_real(char *proc_name,void **ptr_ret,vboolean *terminate)
{
	/* NOTE: at this point LibV global lock must be hold */
	ARCH_CALLER_NAME(vgl_load_proc)
	void *proc = (void*)glx_get_proc_address((const GLubyte *)proc_name);
	void *proc = (void*)dlsym(libgl_handle,proc_name);

	if(*ptr_ret && (*ptr_ret != proc))
	{
		/*
		 * This should never happen under X11 + GLX.
		 */
		ARCH_ERROR("different retval of glXGetProcAddress(): GLX broken ?");
		*terminate = true;
		return false;
	}
	if(proc)
	{
		*ptr_ret = (void*)proc;
		return true;
	}
	return false;
}

V_LOCAL vboolean V_CALL
vgl_load_proc_init(char *proc_name,void **ptr_ret,vboolean *terminate)
{
	ARCH_CALLER_NAME(vgl_load_proc)
	vboolean result = false;
	V_ASSERT(!libgl_handle);
	libvLockGlobal();
	for(;;)
	{
		libgl_handle = dlopen("libGL.so",RTLD_LAZY);
		if(!libgl_handle)
		{
			SYSCALL_FAILED_1STR("glopen(\"libGL.so\"): ", strSafe(dlerror()));
			break;
		}
		*((void**)&glx_get_proc_address) = dlsym(libgl_handle, "glXGetProcAddress");
		if(!glx_get_proc_address)
			*((void**)&glx_get_proc_address) = dlsym(libgl_handle, "glXGetProcAddressARB");
		if(!glx_get_proc_address)
		{
			ARCH_ERROR("no glXGetProcAddress[ARB]() in libGL.so");
			dlclose(libgl_handle);
			libgl_handle = NULL;
			break;
		}
		vgl_load_proc = vgl_load_proc_real;
		result = vgl_load_proc(proc_name, ptr_ret, terminate);
		break;
	}
	libvUnlockGlobal();
	return result;
}

#ifdef	BASEGL11_DYNAMIC

#error	Currently dynamic BaseGL not supported with glXGetProcAddress()

#endif	/* BASEGL11_DYNAMIC */

#endif /* 0 */

#endif	/* ARCH_WINDOWING_SUPPORTED */

