# HG changeset patch
# User John Tsiombikas <nuclear@member.fsf.org>
# Date 1380330813 -10800
# Node ID 0c76f70fb7e9cad31426ab6eb1c2a25426659a21
# Parent  251bc9e2e4a1760d471455ee482f6845efd31f04# Parent  1b107de821c1442102696efebd7112ca60f7f9ff
merged

diff -r 251bc9e2e4a1 -r 0c76f70fb7e9 sdr/sdr.glsl
--- a/sdr/sdr.glsl	Sat Sep 28 04:13:09 2013 +0300
+++ b/sdr/sdr.glsl	Sat Sep 28 04:13:33 2013 +0300
@@ -2,6 +2,7 @@
 uniform float aspect, scale;
 uniform float lens_center_offset;
 uniform vec4 dist_factors;
+uniform vec2 tex_scale;
 
 vec2 distort_texcoords(in vec2 tc);
 float barrel_scale(float x, in vec4 k);
@@ -10,9 +11,9 @@
 {
 	vec2 tc = distort_texcoords(gl_TexCoord[0].xy);
 
-	float vis = any(greaterThan(tc, vec2(1.0)) || lessThan(tc, vec2(0.0))) ? 0.0 : 1.0;
+	float vis = any(greaterThan(tc, vec2(1.0))) || any(lessThan(tc, vec2(0.0))) ? 0.0 : 1.0;
 
-	gl_FragColor.rgb = texture2D(tex, tc).rgb * vis;
+	gl_FragColor.rgb = texture2D(tex, tc * tex_scale).rgb * vis;
 	gl_FragColor.a = 1.0;
 }
 
diff -r 251bc9e2e4a1 -r 0c76f70fb7e9 src/main.cc
--- a/src/main.cc	Sat Sep 28 04:13:09 2013 +0300
+++ b/src/main.cc	Sat Sep 28 04:13:33 2013 +0300
@@ -7,6 +7,12 @@
 #include "camera.h"
 #include "sdr.h"
 
+#ifdef __APPLE__
+#include <OpenGL/OpenGL.h>
+#include <OpenGL/CGLCurrent.h>
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
 static bool init();
 static void cleanup();
 static void disp();
@@ -26,6 +32,8 @@
 static void passive(int x, int y);
 static void sball_rotate(int rx, int ry, int rz);
 static bool parse_args(int argc, char **argv);
+static void printfps();
+static int next_pow2(int x);
 
 static VRFpsCamera cam;
 static int width, height;
@@ -33,13 +41,15 @@
 
 static bool keystate[256];
 
-static int rtarg_width, rtarg_height;
+static int rtarg_width, rtarg_height, rtarg_tex_width, rtarg_tex_height;
+static float tex_scale_x, tex_scale_y;
 static unsigned int fbo, tex[2], zbuf;
 
 static unsigned int teapot_sdr;
 
 static bool fullscreen_pending;
 
+
 int main(int argc, char **argv)
 {
 	glutInitWindowSize(1280, 800);
@@ -102,7 +112,12 @@
 		rtarg_width = (xsz + xsz / 2) / 2;
 		rtarg_height = ysz + ysz / 2;
 
-		printf("render target: %dx%d\n", rtarg_width, rtarg_height);
+		rtarg_tex_width = next_pow2(rtarg_width);
+		rtarg_tex_height = next_pow2(rtarg_height);
+		tex_scale_x = (float)rtarg_width / (float)rtarg_tex_width;
+		tex_scale_y = (float)rtarg_height / (float)rtarg_tex_height;
+
+		printf("render target: %dx%d (%dx%d)\n", rtarg_width, rtarg_height, rtarg_tex_width, rtarg_tex_height);
 
 		// create render targets for each eye
 		GLenum wrap_mode = GL_CLAMP_TO_EDGE;
@@ -117,31 +132,43 @@
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode);
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode);
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_tex_width, rtarg_tex_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
 		}
 
 		// create the depth render buffer
-		glGenRenderbuffers(1, &zbuf);
-		glBindRenderbuffer(GL_RENDERBUFFER, zbuf);
-		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height);
+		glGenRenderbuffersEXT(1, &zbuf);
+		glBindRenderbufferEXT(GL_RENDERBUFFER, zbuf);
+		glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_tex_width, rtarg_tex_height);
 
 		// create the FBO
-		glGenFramebuffers(1, &fbo);
-		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf);
+		glGenFramebuffersEXT(1, &fbo);
+		glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
+		glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
+		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf);
 	}
 
 	teapot_sdr = create_program_load("sdr/phong.v.glsl", "sdr/phong.p.glsl");
 
+	// enable vsync
+#ifdef __APPLE__
+	int swapint = 1;
+	CGLContextObj ctx = CGLGetCurrentContext();
+	CGLSetParameter(ctx, kCGLCPSwapInterval, &swapint);
+#endif
+
+#ifdef __APPLE__
+	// this is required for glutWarpPointer to work correctly, otherwise after every
+	// warp, mac os x freezes event processing for 1/4 second.
+	CGSetLocalEventsSuppressionInterval(0.0);
+#endif
 	return true;
 }
 
 static void cleanup()
 {
 	glDeleteTextures(2, tex);
-	glDeleteRenderbuffers(1, &zbuf);
-	glDeleteFramebuffers(1, &fbo);
+	glDeleteRenderbuffersEXT(1, &zbuf);
+	glDeleteFramebuffersEXT(1, &fbo);
 	vr_shutdown();
 }
 
@@ -189,6 +216,8 @@
 
 	glutSwapBuffers();
 	assert(glGetError() == GL_NO_ERROR);
+
+	printfps();
 }
 
 // display function used in VR mode
@@ -211,8 +240,8 @@
 	glClearColor(0.1, 0.1, 0.1, 1.0);
 
 	// draw left view
-	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-	glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
+	glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
+	glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0);
 
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
@@ -228,8 +257,8 @@
 
 
 	// draw right view
-	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-	glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0);
+	glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
+	glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0);
 
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
@@ -250,13 +279,15 @@
 	glClearColor(0, 0, 0, 0);
 	glClear(GL_COLOR_BUFFER_BIT);
 
-	vr_draw_eye(tex[0], VR_EYE_LEFT);
-	vr_draw_eye(tex[1], VR_EYE_RIGHT);
+	vr_draw_eye(VR_EYE_LEFT, tex[0], tex_scale_x, tex_scale_y);
+	vr_draw_eye(VR_EYE_RIGHT, tex[1], tex_scale_x, tex_scale_y);
 
 	glutSwapBuffers();
 	assert(glGetError() == GL_NO_ERROR);
 
 	glFinish();
+
+	printfps();
 }
 
 static void draw_scene()
@@ -473,6 +504,21 @@
 	if(!use_vr) {
 		rtarg_width = width;
 		rtarg_height = height;
+
+		int new_tex_width = next_pow2(width);
+		int new_tex_height = next_pow2(height);
+
+		if(new_tex_width != rtarg_tex_width || new_tex_height != rtarg_tex_width) {
+			// TODO
+			exit(1);
+		}
+
+		rtarg_tex_width = new_tex_width;
+		rtarg_tex_height = new_tex_height;
+
+		tex_scale_x = (float)rtarg_width / (float)rtarg_tex_width;
+		tex_scale_y = (float)rtarg_height / (float)rtarg_tex_height;
+
 	}
 }
 
@@ -526,7 +572,7 @@
 	int center_y = height / 2;
 
 	int dx = x - center_x;
-	int dy = y - center_y;
+	int dy = use_vr ? 0 : y - center_y;
 
 	if(use_vr && fullscreen) {
 		dy = 0;
@@ -541,8 +587,8 @@
 
 	cam.input_rotate(DEG_TO_RAD(dtheta_deg), DEG_TO_RAD(dphi_deg), 0);
 
+	glutWarpPointer(center_x, center_y);
 	glutPostRedisplay();
-	glutWarpPointer(center_x, center_y);
 }
 
 static void sball_rotate(int rx, int ry, int rz)
@@ -568,3 +614,33 @@
 	}
 	return true;
 }
+
+static void printfps()
+{
+	static unsigned int last_upd, frames;
+	unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
+	unsigned int dmsec = msec - last_upd;
+
+	frames++;
+
+	if(dmsec > 2000) {
+		float dt = (float)dmsec / 1000.0f;
+
+		printf("fps: %.2f        \r", (float)frames / dt);
+		fflush(stdout);
+
+		frames = 0;
+		last_upd = msec;
+	}
+}
+
+static int next_pow2(int x)
+{
+	x--;
+	x = (x >> 1) | x;
+	x = (x >> 2) | x;
+	x = (x >> 4) | x;
+	x = (x >> 8) | x;
+	x = (x >> 16) | x;
+	return x + 1;
+}
diff -r 251bc9e2e4a1 -r 0c76f70fb7e9 src/vr.cc
--- a/src/vr.cc	Sat Sep 28 04:13:09 2013 +0300
+++ b/src/vr.cc	Sat Sep 28 04:13:33 2013 +0300
@@ -4,6 +4,7 @@
 #include "vr_impl.h"
 #include "vr_sdr.h"
 
+static void init_ctx();
 static bool init_ovr();
 static bool init_sdr();
 
@@ -14,6 +15,8 @@
 {
 	glewInit();
 
+	init_ctx();
+
 	if(!init_ovr()) {
 		return -1;
 	}
@@ -31,6 +34,16 @@
 	//System::Destroy();
 }
 
+static void init_ctx()
+{
+	vr_ctx.info.width = 1280;
+	vr_ctx.info.height = 800;
+	vr_ctx.info.fov = M_PI / 2.0;
+	vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
+	vr_ctx.info.ipd = 0.035;
+	vr_ctx.info.scale = 1.0;
+}
+
 static bool init_ovr()
 {
 	LogMaskConstants log_level = LogMask_All;
@@ -312,7 +325,7 @@
 	oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
 }
 
-extern "C" void vr_draw_eye(unsigned int tex, int eye)
+extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
 {
 	static const float rects[3][4] = {
 		{-1, -1, 1, 1},
@@ -342,6 +355,10 @@
 			float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
 			glUniform1f(loc, offset);
 		}
+
+		if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
+			glUniform2f(loc, tex_scale_x, tex_scale_y);
+		}
 	}
 
 	glBindTexture(GL_TEXTURE_2D, tex);
diff -r 251bc9e2e4a1 -r 0c76f70fb7e9 src/vr.h
--- a/src/vr.h	Sat Sep 28 04:13:09 2013 +0300
+++ b/src/vr.h	Sat Sep 28 04:13:33 2013 +0300
@@ -54,7 +54,7 @@
 void vr_get_rotation_euler(float *euler);
 
 /* OpenGL stuff */
-void vr_draw_eye(unsigned int tex, int eye);
+void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y);
 
 #ifdef __cplusplus
 }