Blame src/gl.c

deef1d
deef1d
#include "private.h"
deef1d
#include "drawing.h"
deef1d
deef1d
1d641c
HeliGLBlendFuncSeparatePtr       heliGLBlendFuncSeparatePtr;
1d641c
HeliGLStencilOpSeparatePtr       heliGLStencilOpSeparatePtr;
1d641c
HeliGLTexImage2DMultisamplePtr   heliGLTexImage2DMultisamplePtr;
1d641c
HeliGLGenFramebuffersPtr         heliGLGenFramebuffersPtr;
1d641c
HeliGLDeleteFramebuffersPtr      heliGLDeleteFramebuffersPtr;
1d641c
HeliGLBindFramebufferPtr         heliGLBindFramebufferPtr;
1d641c
HeliGLBlitFramebufferPtr         heliGLBlitFramebufferPtr;
1d641c
HeliGLFramebufferRenderbufferPtr heliGLFramebufferRenderbufferPtr;
1d641c
HeliGLFramebufferTexture2DPtr    heliGLFramebufferTexture2DPtr;
909bc2
HeliGLCheckFramebufferStatusPtr  heliGLCheckFramebufferStatusPtr;
1d641c
HeliGLGenRenderbuffersPtr        heliGLGenRenderbuffersPtr;
1d641c
HeliGLDeleteRenderbuffersPtr     heliGLDeleteRenderbuffersPtr;
1d641c
HeliGLBindRenderbufferPtr        heliGLBindRenderbufferPtr;
1d641c
HeliGLRenderbufferStoragePtr     heliGLRenderbufferStoragePtr;
1d641c
HeliGLRenderbufferStorageMultisamplePtr heliGLRenderbufferStorageMultisamplePtr;
1d641c
1d641c
unsigned int heliGLWindowFramebufferReadId = 0;
1d641c
unsigned int heliGLWindowFramebufferDrawId = 0;
1d641c
1d641c
deef1d
double heliGLGetAAResolution() {
deef1d
	if (!heliGLIsIntegerClipping()) return 0;
deef1d
	
deef1d
	double proj[16] = {};
deef1d
	double model[16] = {};
deef1d
	glGetDoublev(GL_PROJECTION_MATRIX, proj);
deef1d
	glGetDoublev(GL_MODELVIEW_MATRIX, model);
deef1d
	
deef1d
	double full[16] = {};
deef1d
	double fullinv[16] = {};
deef1d
	heliMatrix4Mult(full, proj, model);
deef1d
deef1d
	full[8] = 0, full[9] = 0, full[10] = 1, full[11] = 0; // assume z is zero
deef1d
	if (!heliMatrix4Invert(fullinv, full)) return 0;
deef1d
	
deef1d
	if (fabs(fullinv[15]) < HELI_PRECISION_SQR) return 0; // bad perspective
deef1d
	double k = 1/fullinv[15];
deef1d
	
deef1d
	if ( fabs(fullinv[3]*k) > 1e-5
deef1d
	  || fabs(fullinv[7]*k) > 1e-5 ) return 0; // perspective distortion
deef1d
	
deef1d
	int rect[4] = {}; // x, y, w, h
deef1d
	glGetIntegerv(GL_VIEWPORT, rect);
deef1d
	double w = rect[2], h = rect[3];
deef1d
	
deef1d
	double m00 = fullinv[0]*k*2/w, m01 = fullinv[1]*k*2/w,
deef1d
	       m10 = fullinv[4]*k*2/h, m11 = fullinv[5]*k*2/h;
deef1d
	double l0 = sqrt(m00*m00 + m01*m01);
deef1d
	double l1 = sqrt(m10*m10 + m11*m11);
deef1d
	if (l0 > l1) { double l = l0; l0 = l1; l1 = l; }
deef1d
	if (l0 < HELI_PRECISION || l1 < HELI_PRECISION) return 0;
deef1d
	if (l0/l1 < 0.75) return 0; // to big aspect ratio
deef1d
	
deef1d
	return sqrt(l0*l1);
deef1d
}
deef1d
deef1d
deef1d
static int isInteger(double x)
deef1d
	{ return fabs(floor(x + 0.5) - x) > 0.01; }
deef1d
deef1d
int heliGLIsIntegerClipping() {
deef1d
	double proj[16] = {};
deef1d
	double model[16] = {};
deef1d
	double viewproj[16] = {};
deef1d
	double viewmodel[16] = {};
deef1d
	
deef1d
	int rect[4] = {}; // x, y, w, h
deef1d
	glGetIntegerv(GL_VIEWPORT, rect);
deef1d
	double hw = 0.5*rect[2], hh = 0.5*rect[3];
deef1d
	double view[16] = {
deef1d
		hw,  0, 0, 0,
deef1d
		 0,-hh, 0, 0,
deef1d
		 0,  0, 1, 0,
deef1d
		hw, hh, 0, 1 };
deef1d
	
deef1d
	glGetDoublev(GL_PROJECTION_MATRIX, proj);
deef1d
	glGetDoublev(GL_MODELVIEW_MATRIX, model);
deef1d
	heliMatrix4Mult(viewproj, view, proj);
deef1d
	heliMatrix4Mult(viewmodel, viewproj, model);
deef1d
	
deef1d
	int badMatrix = FALSE;
deef1d
	if (fabs(viewmodel[15]) < HELI_PRECISION_SQR) badMatrix = TRUE; // bad perspective
deef1d
	double k = badMatrix ? 0 : 1/viewmodel[15];
deef1d
	if ( fabs(viewmodel[3]*k) > 1e-5
deef1d
	  || fabs(viewmodel[7]*k) > 1e-5 ) badMatrix = TRUE; // perspective distortion
deef1d
	
deef1d
	HeliGLCommonState s;
deef1d
	const int clipCount = (int)(sizeof(s.clipPlanes)/sizeof(*s.clipPlanes));
deef1d
	//glGetIntegerv(GL_MAX_CLIP_PLANES, &clipCount);
deef1d
	double eq[4] = {}, eqv[4] = {};
deef1d
	for(int i = 0; i < clipCount; ++i) {
deef1d
		if (!glIsEnabled(GL_CLIP_PLANE0 + i)) continue;
deef1d
		if (badMatrix) return FALSE;
deef1d
		
deef1d
		glGetClipPlane(GL_CLIP_PLANE0 + i, eq);
deef1d
		heliMatrix4MultVec(eqv, viewproj, eq);
deef1d
		double a = (eqv[0] + eqv[2]*viewmodel[2])*k;
deef1d
		double b = (eqv[1] + eqv[2]*viewmodel[6])*k;
deef1d
		double c = eqv[2]*viewmodel[14]*k + 1;
deef1d
		
deef1d
		if (fabs(a) > 1e-5 && fabs(b) > 1e-5) return FALSE;
deef1d
		if (fabs(a) > 1e-5 && !isInteger(c/a)) return FALSE;
deef1d
		if (fabs(b) > 1e-5 && !isInteger(b/a)) return FALSE;
deef1d
	}
deef1d
	
deef1d
	return TRUE;
deef1d
}
deef1d
deef1d
int heliGLBackTransform(double *x, double *y) {
deef1d
	double proj[16] = {};
deef1d
	double model[16] = {};
deef1d
	double viewproj[16] = {};
deef1d
	double viewmodel[16] = {};
deef1d
	double inv[16] = {};
deef1d
	
deef1d
	double v[2][4] = {
deef1d
		{ *x, *y, 0, 1 },
deef1d
		{ *x, *y, 1, 1 } };
deef1d
	double vv[2][4] = {};
deef1d
	*x = 0; *y = 0;
deef1d
deef1d
	int rect[4] = {}; // x, y, w, h
deef1d
	glGetIntegerv(GL_VIEWPORT, rect);
deef1d
	double hw = 0.5*rect[2], hh = 0.5*rect[3];
deef1d
	double view[16] = {
deef1d
		hw,  0, 0, 0,
deef1d
		 0,-hh, 0, 0,
deef1d
		 0,  0, 1, 0,
deef1d
		hw, hh, 0, 1 };
deef1d
	
deef1d
	glGetDoublev(GL_PROJECTION_MATRIX, proj);
deef1d
	glGetDoublev(GL_MODELVIEW_MATRIX, model);
deef1d
	heliMatrix4Mult(viewproj, view, proj);
deef1d
	heliMatrix4Mult(viewmodel, viewproj, model);
deef1d
	
deef1d
	if (!heliMatrix4Invert(inv, viewmodel)) return FALSE;
deef1d
	heliMatrix4MultVec(vv[0], inv, v[0]);
deef1d
	heliMatrix4MultVec(vv[1], inv, v[1]);
deef1d
	
deef1d
	double l = vv[0][2] - vv[1][2];
deef1d
	if (fabs(l) <= HELI_PRECISION) return FALSE;
deef1d
	l = vv[0][2]/l;
deef1d
	
deef1d
	double kw = vv[0][3] + (vv[1][3] - vv[0][3])*l;
deef1d
	if (fabs(kw) <= HELI_PRECISION) return FALSE;
deef1d
	kw = 1/kw;
deef1d
	
deef1d
	*x = (vv[0][0] + (vv[1][0] - vv[0][0])*l)*kw;
deef1d
	*y = (vv[0][1] + (vv[1][1] - vv[0][1])*l)*kw;
deef1d
	return TRUE;
deef1d
}
deef1d
deef1d
deef1d
void heliGLGetCommonState(HeliGLCommonState *state, unsigned int flags) {
deef1d
	memset(state, 0, sizeof(*state));
deef1d
	state->flags = flags;
deef1d
	
deef1d
	if (state->flags & STATE_TRANSFORM)
deef1d
		glGetDoublev(GL_MODELVIEW_MATRIX, state->modelviewMatrix);
deef1d
	
deef1d
	if (state->flags & STATE_CLIP) {
deef1d
		const int clipCount = (int)(sizeof(state->clipPlanes)/sizeof(*state->clipPlanes));
deef1d
		for(int i = 0; i < clipCount; ++i) {
deef1d
			state->clipPlanes[i].enabled = glIsEnabled(GL_CLIP_PLANE0 + i) != 0;
deef1d
			glGetClipPlane(GL_CLIP_PLANE0 + i, state->clipPlanes[i].equation);
deef1d
		}
deef1d
	}
1d641c
	
1d641c
	if (state->flags & STATE_TARGET_FRAMEBUFFER) {
1d641c
		glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (int*)&state->framebuffer_read_id);
1d641c
		glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (int*)&state->framebuffer_draw_id);
1d641c
	}
1d641c
	if (state->flags & STATE_TARGET_VIEWPORT)
1d641c
		glGetIntegerv(GL_VIEWPORT, state->viewport);
1d641c
	if (state->flags & STATE_TARGET_PROJECTION)
1d641c
		glGetDoublev(GL_PROJECTION_MATRIX, state->projectionMatrix);
d6f40c
	if (state->flags & STATE_BACKGROUND)
d6f40c
		glGetDoublev(GL_COLOR_CLEAR_VALUE, state->clearColor);
deef1d
}
deef1d
deef1d
deef1d
void heliGLSetCommonState(const HeliGLCommonState *state) {
deef1d
	int loadClip = state->flags & STATE_CLIP;
deef1d
	int loadTransform = state->flags & STATE_CLIP;
deef1d
	if (loadClip) {
deef1d
		unsigned int mode;
deef1d
		glGetIntegerv(GL_MATRIX_MODE, (int*)&mode);
deef1d
		glMatrixMode(GL_MODELVIEW);
deef1d
		if (!loadTransform) glPushMatrix();
deef1d
		const int clipCount = (int)(sizeof(state->clipPlanes)/sizeof(*state->clipPlanes));
deef1d
		for(int i = 0; i < clipCount; ++i) {
deef1d
			if (state->clipPlanes[i].enabled) glEnable(GL_CLIP_PLANE0+i);
deef1d
			                             else glDisable(GL_CLIP_PLANE0+i);
deef1d
			glClipPlane(GL_CLIP_PLANE0+i, state->clipPlanes[i].equation);
deef1d
		}
deef1d
		if (!loadTransform) glPopMatrix(); else glLoadMatrixd(state->modelviewMatrix);
deef1d
		glMatrixMode(mode);
deef1d
	} else
deef1d
	if (loadTransform) {
deef1d
		unsigned int mode;
deef1d
		glGetIntegerv(GL_MATRIX_MODE, (int*)&mode);
deef1d
		glMatrixMode(GL_MODELVIEW);
deef1d
		glLoadMatrixd(state->modelviewMatrix);
deef1d
		glMatrixMode(mode);
deef1d
	}
1d641c
	
1d641c
	if (state->flags & STATE_TARGET_FRAMEBUFFER) {
1d641c
		if (heliGLBindFramebufferPtr) {
1d641c
			heliGLBindFramebufferPtr(GL_DRAW_FRAMEBUFFER, state->framebuffer_draw_id);
1d641c
			heliGLBindFramebufferPtr(GL_READ_FRAMEBUFFER, state->framebuffer_read_id);
1d641c
		}
1d641c
	}
1d641c
	if (state->flags & STATE_TARGET_VIEWPORT)
1d641c
		glViewport(state->viewport[0], state->viewport[1], state->viewport[2], state->viewport[3]);
1d641c
	if (state->flags & STATE_TARGET_PROJECTION) {
1d641c
		unsigned int mode;
1d641c
		glGetIntegerv(GL_MATRIX_MODE, (int*)&mode);
1d641c
		glMatrixMode(GL_PROJECTION);
1d641c
		glLoadMatrixd(state->projectionMatrix);
1d641c
		glMatrixMode(mode);
1d641c
	}
d6f40c
	if (state->flags & STATE_BACKGROUND)
d6f40c
		glClearColor(state->clearColor[0], state->clearColor[1], state->clearColor[2], state->clearColor[3]);
deef1d
}
deef1d