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

#ifdef	ARCH_WINDOWING_SUPPORTED

GLOBAL_STRING(gl_context_name,"WGL context")

void V_GLOBAL
vglSwap(void)
{
	CALLER_NAME(vglSwap)
	gl_context_p ctx;
	IF_NO_GLCONTEXT(ctx)
		return;
	SwapBuffers(ctx->wnd->dc);
}

V_LOCAL u32_t V_CALL
win32_destroy_context(vhandle_t handle)
{
	gl_context_p ctx = (gl_context_p)handle;
	UNREF_EXIT(ctx);
	wglMakeCurrent(NULL, NULL);
	if(ctx->wgl_context)
		wglDeleteContext(ctx->wgl_context);
	ARCH_CLEAR_COMMON_GL_CONTEXT_FIELDS(ctx);
	memFreeObject(ctx);
	return 0;
}

void V_GLOBAL
vglDestroy(void)
{
	CALLER_NAME(vglDestroy)
	thread_data_p td = GetThreadData();
	vhandle_t ctx = td->gl_context;
	td->gl_context = NULL;
	if(ctx != LIBV_INVALID_HANDLE)
		libvCloseHandle(ctx,caller_name,gl_context_name,GL_CONTEXT_MAGIC);
}

V_LOCAL gl_context_p
alloc_context(void)
{
	gl_context_p ctx;
	ALLOC_OBJECT(ctx,gl_context_t,0,GL_CONTEXT_MAGIC);
	return ctx;
}

vboolean
vglInit(
	char *caption,
	int x, int y, int width, int height,
	vboolean fullscreen,
	vboolean can_resize,
	vboolean need_depth,
	vboolean need_stencil,
	vboolean need_dst_alpha)
{
	ARCH_CALLER_NAME(vglInit)
	PIXELFORMATDESCRIPTOR pfd;
	gl_context_p ctx;
	u32_t bpp;
	int i, pixfmt;
	GLfloat aspect;
	vglDestroy();
	ctx = alloc_context();
	if(ctx == LIBV_INVALID_HANDLE)
		return false;
	ctx->base.destroy = win32_destroy_context;
	ctx->wnd = archWinOpenNP(NULL, NULL,
		caption, x, y, width, height, !fullscreen, can_resize);
	if(!ctx->wnd)
		goto err_exit;
	width = ctx->wnd->width;
	height = ctx->wnd->height;
	archWinShow(ctx->wnd, true);
	bpp = GetDeviceCaps(ctx->wnd->dc, BITSPIXEL);
	if(bpp <= 8)
	{
		if(!fullscreen)
		{
			ARCH_ERROR("true or high color mode required");
			goto err_exit;
		}
		else
			bpp = 16;
	}
	if(fullscreen)
	{
		for(i = 0; i < ctx->wnd->num_vidmodes; i++)
		{
			vidmode_p mode = ctx->wnd->vidmodes + i;
			if((int)mode->width == width &&
					(int)mode->height == height && mode->bpp == bpp)
			{
				if(!archWinSetVidMode(ctx->wnd, i))
				{
					ARCH_ERROR("archWinSetVidMode() failed");
					goto err_exit;
				}
				break;
			}
		}
		if(i == ctx->wnd->num_vidmodes)
		{
			ARCH_ERROR("required video mode not found");
			goto err_exit;
		}
	}
#ifdef __BORLANDC__
	_control87(MCW_EM,MCW_EM);
#endif
	memZero(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pfd.nVersion = 1;
    pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.iLayerType = PFD_MAIN_PLANE;
	pfd.cColorBits = 16;
    if(need_depth)
		pfd.cDepthBits = 16;
    if(need_stencil)
		pfd.cStencilBits = 1;
    if(need_dst_alpha)
		pfd.cAlphaBits = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER
		| PFD_SUPPORT_OPENGL;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pixfmt = ChoosePixelFormat(ctx->wnd->dc, &pfd);
	if(!pixfmt)
	{
		SYSCALL_FAILED("ChoosePixelFormat");
		goto err_exit;
	}
	memZero(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	if(!DescribePixelFormat(ctx->wnd->dc, pixfmt, pfd.nSize, &pfd))
	{
		SYSCALL_FAILED("DescribePixelFormat");
		goto err_exit;
	}
	if(need_depth && !pfd.cDepthBits)
	{
		ARCH_ERROR("renderer doesn't support Z-buffering");
		goto err_exit;
	}
	if(need_dst_alpha && !pfd.cAlphaBits)
	{
		ARCH_ERROR("renderer doesn't support dst alpha");
		goto err_exit;
	}
	if(need_stencil && !pfd.cStencilBits)
	{
		ARCH_ERROR("renderer doesn't support stencil");
		goto err_exit;
	}
	if(!SetPixelFormat(ctx->wnd->dc, pixfmt, &pfd))
	{
		SYSCALL_FAILED("SetPixelFormat");
		goto err_exit;
	}
	ctx->wgl_context = wglCreateContext(ctx->wnd->dc);
	if(!ctx->wgl_context)
	{
		SYSCALL_FAILED("wglCreateContext");
		goto err_exit;
	}
	if(!wglMakeCurrent(ctx->wnd->dc, ctx->wgl_context))
	{
		SYSCALL_FAILED("wglMakeCurrent");
		goto err_exit;
	}
	ctx->vendor = strDup((char_p)glGetString(GL_VENDOR));
	ctx->renderer = strDup((char_p)glGetString(GL_RENDERER));
	ctx->version = strDup((char_p)glGetString(GL_VERSION));
	ctx->extensions = strDup((char_p)glGetString(GL_EXTENSIONS));
#ifdef	ARCH_VERBOSE
	conlPrintf(LOG_TRACE,"%s(): PFD %d, %s OpenGL on %s ver. %s.\n",
		arch_caller_name,pixfmt,ctx->vendor,ctx->renderer,ctx->version);
#endif	/* ARCH_VERBOSE */
	archWinPoll(ctx->wnd, false);
	aspect = (GLfloat)ctx->wnd->width /
		(GLfloat)ctx->wnd->height;
	glViewport(0, 0, ctx->wnd->width, ctx->wnd->height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-aspect, aspect, -1, 1, 1, 3);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	GetThreadData()->gl_context = ctx;
	return true;

err_exit:;
	win32_destroy_context(ctx);
	return false;
}

#endif	/* ARCH_WINDOWING_SUPPORTED */
