changeset 1875:e9b157ab56a6

first stereo support
author Vladimir Nadvornik <nadvornik@suse.cz>
date Fri, 28 Jan 2011 11:05:07 +0100
parents ca810ea8fae9
children cdf087e6e22f
files src/image-load.c src/image.c src/pixbuf-renderer.c src/pixbuf-renderer.h src/renderer-tiles.c src/renderer-tiles.h
diffstat 6 files changed, 152 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/src/image-load.c	Thu Jan 27 13:40:05 2011 +0100
+++ b/src/image-load.c	Fri Jan 28 11:05:07 2011 +0100
@@ -362,6 +362,11 @@
 		return;
 		}
 
+	if (g_ascii_strcasecmp(".jps", il->fd->extension) == 0)
+		{
+		g_object_set_data(G_OBJECT(pb), "stereo_sbs", GINT_TO_POINTER(1));
+		}
+
 	if (il->pixbuf) g_object_unref(il->pixbuf);
 
 	il->pixbuf = pb;
--- a/src/image.c	Thu Jan 27 13:40:05 2011 +0100
+++ b/src/image.c	Fri Jan 28 11:05:07 2011 +0100
@@ -1340,11 +1340,11 @@
 
 	if (vertical)
 		{
-		zoom = (gdouble)pr->window_height / height;
+		zoom = (gdouble)pr->viewport_height / height;
 		}
 	else
 		{
-		zoom = (gdouble)pr->window_width / width;
+		zoom = (gdouble)pr->viewport_width / width;
 		}
 
 	if (zoom < 1.0)
--- a/src/pixbuf-renderer.c	Thu Jan 27 13:40:05 2011 +0100
+++ b/src/pixbuf-renderer.c	Fri Jan 28 11:05:07 2011 +0100
@@ -428,7 +428,12 @@
 	pr->norm_center_x = 0.5;
 	pr->norm_center_y = 0.5;
 	
-	pr->renderer = (void *)renderer_tiles_new(pr);
+	pr->stereo_mode = PR_STEREO_HORIZ;
+	
+	pr->renderer = (void *)renderer_tiles_new(pr, pr->stereo_mode);
+	
+	pr->renderer2 = (pr->stereo_mode && (PR_STEREO_HORIZ || PR_STEREO_VERT)) ?
+	              (void *)renderer_tiles_new(pr, pr->stereo_mode | PR_STEREO_RIGHT) : NULL;
 
 	gtk_widget_set_double_buffered(box, FALSE);
 	g_signal_connect_after(G_OBJECT(box), "size_allocate",
@@ -444,6 +449,7 @@
 	pr = PIXBUF_RENDERER(object);
 
 	pr->renderer->free(pr->renderer);
+	if (pr->renderer2) pr->renderer->free(pr->renderer2);
 
 
 	if (pr->pixbuf) g_object_unref(pr->pixbuf);
@@ -745,22 +751,27 @@
 gint pixbuf_renderer_overlay_add(PixbufRenderer *pr, GdkPixbuf *pixbuf, gint x, gint y,
 				 OverlayRendererFlags flags)
 {
+	/* let's assume both renderers returns the same value */
+	if (pr->renderer2) pr->renderer2->overlay_add(pr->renderer2, pixbuf, x, y, flags);
 	return pr->renderer->overlay_add(pr->renderer, pixbuf, x, y, flags);
 }
 
 void pixbuf_renderer_overlay_set(PixbufRenderer *pr, gint id, GdkPixbuf *pixbuf, gint x, gint y)
 {
 	pr->renderer->overlay_set(pr->renderer, id, pixbuf, x, y);
+	if (pr->renderer2) pr->renderer2->overlay_set(pr->renderer2, id, pixbuf, x, y);
 }
 
 gboolean pixbuf_renderer_overlay_get(PixbufRenderer *pr, gint id, GdkPixbuf **pixbuf, gint *x, gint *y)
 {
+	if (pr->renderer2) pr->renderer2->overlay_get(pr->renderer2, id, pixbuf, x, y);
 	return pr->renderer->overlay_get(pr->renderer, id, pixbuf, x, y);
 }
 
 void pixbuf_renderer_overlay_remove(PixbufRenderer *pr, gint id)
 {
 	pr->renderer->overlay_set(pr->renderer, id, NULL, 0, 0);
+	if (pr->renderer2) pr->renderer2->overlay_set(pr->renderer2, id, NULL, 0, 0);
 }
 
 /*
@@ -918,7 +929,8 @@
 
 static void pr_border_clear(PixbufRenderer *pr)
 {
-	pr->renderer->border_draw(pr->renderer, 0, 0, pr->window_width, pr->window_height);
+	pr->renderer->border_draw(pr->renderer, 0, 0, pr->viewport_width, pr->viewport_height);
+	if (pr->renderer2) pr->renderer2->border_draw(pr->renderer2, 0, 0, pr->viewport_width, pr->viewport_height);
 }
 
 void pixbuf_renderer_set_color(PixbufRenderer *pr, GdkColor *color)
@@ -957,6 +969,10 @@
 {
 	pr->renderer->queue_clear(pr->renderer);
 	pr->renderer->queue(pr->renderer, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE);
+	if (pr->renderer2) {
+		pr->renderer2->queue_clear(pr->renderer2);
+		pr->renderer2->queue(pr->renderer2, 0, 0, pr->width, pr->height, TRUE, TILE_RENDER_ALL, new_data, FALSE);
+	}
 }
 
 /*
@@ -1098,7 +1114,8 @@
 
 	pr->renderer->invalidate_region(pr->renderer, st->x * pr->scale, st->y * pr->scale,
 				  pr->source_tile_width * pr->scale, pr->source_tile_height * pr->scale);
-
+	if (pr->renderer2) pr->renderer2->invalidate_region(pr->renderer2, st->x * pr->scale, st->y * pr->scale,
+				  pr->source_tile_width * pr->scale, pr->source_tile_height * pr->scale);
 	return st;
 }
 
@@ -1185,6 +1202,8 @@
 				{
 					pr->renderer->invalidate_region(pr->renderer, rx * pr->scale, ry * pr->scale,
 							      rw * pr->scale, rh * pr->scale);
+					if (pr->renderer2) pr->renderer2->invalidate_region(pr->renderer2, rx * pr->scale, ry * pr->scale,
+								rw * pr->scale, rh * pr->scale);
 				}
 			g_object_unref(pixbuf);
 			}
@@ -1543,13 +1562,13 @@
 	 * of the "broken image" icon.
 	*/
 
-	if (pr->width > pr->window_width)
+	if (pr->width > pr->viewport_width)
 		{
 		src_x = pr->x_scroll + pr->vis_width / 2;
 		pr->norm_center_x = (gdouble)src_x / pr->width;
 		}
 	
-	if (pr->height > pr->window_height)
+	if (pr->height > pr->viewport_height)
 		{
 		src_y = pr->y_scroll + pr->vis_height / 2;
 		pr->norm_center_y = (gdouble)src_y / pr->height;
@@ -1603,25 +1622,25 @@
 	old_vw = pr->vis_width;
 	old_vh = pr->vis_height;
 
-	if (pr->width < pr->window_width)
+	if (pr->width < pr->viewport_width)
 		{
 		pr->vis_width = pr->width;
-		pr->x_offset = (pr->window_width - pr->width) / 2;
+		pr->x_offset = (pr->viewport_width - pr->width) / 2;
 		}
 	else
 		{
-		pr->vis_width = pr->window_width;
+		pr->vis_width = pr->viewport_width;
 		pr->x_offset = 0;
 		}
 
-	if (pr->height < pr->window_height)
+	if (pr->height < pr->viewport_height)
 		{
 		pr->vis_height = pr->height;
-		pr->y_offset = (pr->window_height - pr->height) / 2;
+		pr->y_offset = (pr->viewport_height - pr->height) / 2;
 		}
 	else
 		{
-		pr->vis_height = pr->window_height;
+		pr->vis_height = pr->viewport_height;
 		pr->y_offset = 0;
 		}
 
@@ -1673,8 +1692,8 @@
 			}
 		else
 			{
-			max_w = pr->window_width;
-			max_h = pr->window_height;
+			max_w = pr->viewport_width;
+			max_h = pr->viewport_height;
 			}
 
 		if ((pr->zoom_expand && !sizeable) || w > max_w || h > max_h)
@@ -1733,6 +1752,7 @@
 	if (invalidate || invalid)
 		{
 		pr->renderer->invalidate_all(pr->renderer);
+		if (pr->renderer2) pr->renderer2->invalidate_all(pr->renderer2);
 		if (!lazy) pr_redraw(pr, TRUE);
 		}
 	if (redrawn) *redrawn = (invalidate || invalid);
@@ -1828,6 +1848,7 @@
 	if (lazy)
 		{
 		pr->renderer->queue_clear(pr->renderer);
+		if (pr->renderer2) pr->renderer2->queue_clear(pr->renderer2);
 		}
 	else
 		{
@@ -1843,10 +1864,16 @@
 {
 	gboolean zoom_changed = FALSE;
 
-	if (pr->window_width == new_width && pr->window_height == new_height) return;
+	gint new_viewport_width = (pr->stereo_mode & PR_STEREO_HORIZ) ? new_width / 2 : new_width;
+	gint new_viewport_height = (pr->stereo_mode & PR_STEREO_VERT) ? new_height / 2 : new_height;
+	
+	if (pr->window_width == new_width && pr->window_height == new_height &&
+	    pr->viewport_width == new_viewport_width && pr->viewport_height == new_viewport_height) return;
 
 	pr->window_width = new_width;
 	pr->window_height = new_height;
+	pr->viewport_width = new_viewport_width;
+	pr->viewport_height = new_viewport_height;
 
 	if (pr->zoom == 0.0)
 		{
@@ -1858,7 +1885,8 @@
 	pr_size_clamp(pr);
 	pr_scroll_clamp(pr);
 
-	pr->renderer->overlay_update_sizes(pr->renderer);
+	pr->renderer->update_sizes(pr->renderer);
+	if (pr->renderer2) pr->renderer2->update_sizes(pr->renderer2);
 
 	/* ensure scroller remains visible */
 	if (pr->scroller_overlay != -1)
@@ -1912,16 +1940,25 @@
 {
 	gint x, y;
 
-	pr->renderer->border_draw(pr->renderer, area->x, area->y, area->width, area->height);
 
 	x = MAX(0, (gint)area->x - pr->x_offset + pr->x_scroll);
 	y = MAX(0, (gint)area->y - pr->y_offset + pr->y_scroll);
 
+	pr->renderer->border_draw(pr->renderer, area->x, area->y, area->width, area->height);
 	pr->renderer->queue(pr->renderer,
 			      x, y,
 			      MIN((gint)area->width, pr->width - x),
 			      MIN((gint)area->height, pr->height - y),
 			      FALSE, TILE_RENDER_ALL, FALSE, FALSE);
+	if (pr->renderer2) 
+		{
+		pr->renderer2->border_draw(pr->renderer2, area->x, area->y, area->width, area->height);
+		pr->renderer2->queue(pr->renderer2,
+			      x, y,
+			      MIN((gint)area->width, pr->width - x),
+			      MIN((gint)area->height, pr->height - y),
+			      FALSE, TILE_RENDER_ALL, FALSE, FALSE);
+		}
 }
 
 /*
@@ -1957,6 +1994,7 @@
 	y_off = pr->y_scroll - old_y;
 	
 	pr->renderer->scroll(pr->renderer, x_off, y_off);
+	if (pr->renderer2) pr->renderer2->scroll(pr->renderer2, x_off, y_off);
 }
 
 void pixbuf_renderer_scroll_to_point(PixbufRenderer *pr, gint x, gint y,
@@ -2216,6 +2254,7 @@
  */
 static void pr_pixbuf_size_sync(PixbufRenderer *pr)
 {
+	pr->stereo_pixbuf_off = 0;
 	if (!pr->pixbuf) return;
 	switch (pr->orientation)
 		{
@@ -2225,10 +2264,21 @@
 		case EXIF_ORIENTATION_LEFT_BOTTOM:
 			pr->image_width = gdk_pixbuf_get_height(pr->pixbuf);
 			pr->image_height = gdk_pixbuf_get_width(pr->pixbuf);
+			if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(pr->pixbuf), "stereo_sbs"))) 
+				{
+				pr->image_height /= 2;
+				pr->stereo_pixbuf_off = pr->image_height;
+				}
+			
 			break;
 		default:
 			pr->image_width = gdk_pixbuf_get_width(pr->pixbuf);
 			pr->image_height = gdk_pixbuf_get_height(pr->pixbuf);
+			if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(pr->pixbuf), "stereo_sbs"))) 
+				{
+				pr->image_width /= 2;
+				pr->stereo_pixbuf_off = pr->image_width;
+				}
 		}
 }
 
@@ -2258,7 +2308,8 @@
 #endif
 			{
 			gdk_window_clear(box->window);
-			pr->renderer->overlay_draw(pr->renderer, 0, 0, pr->window_width, pr->window_height);
+			pr->renderer->overlay_draw(pr->renderer, 0, 0, pr->viewport_width, pr->viewport_height);
+			if (pr->renderer2) pr->renderer2->overlay_draw(pr->renderer2, 0, 0, pr->viewport_width, pr->viewport_height);
 			}
 
 		pr_update_signal(pr);
@@ -2422,6 +2473,7 @@
 	y2 = (gint)ceil((gdouble)(y + height) * pr->scale);
 
 	pr->renderer->queue(pr->renderer, x1, y1, x2 - x1, y2 - y1, FALSE, TILE_RENDER_AREA, TRUE, TRUE);
+	if (pr->renderer2) pr->renderer2->queue(pr->renderer2, x1, y1, x2 - x1, y2 - y1, FALSE, TILE_RENDER_AREA, TRUE, TRUE);
 }
 
 void pixbuf_renderer_zoom_adjust(PixbufRenderer *pr, gdouble increment)
--- a/src/pixbuf-renderer.h	Thu Jan 27 13:40:05 2011 +0100
+++ b/src/pixbuf-renderer.h	Fri Jan 28 11:05:07 2011 +0100
@@ -74,6 +74,17 @@
 	/* OVL_HIDE_ON_SCROLL = 1 << 1*/ /* hide temporarily when scrolling (not yet implemented) */
 } OverlayRendererFlags;
 
+typedef enum {
+	PR_STEREO_NONE     = 0,	  /* do nothing */
+	PR_STEREO_DUAL     = 1 << 0, /* independent stereo buffers, for example nvidia opengl */
+	PR_STEREO_HORIZ    = 1 << 2, /* side by side */
+	PR_STEREO_VERT     = 1 << 3, /* above below */
+	/* flags for renderer: */
+	PR_STEREO_RIGHT    = 1 << 4, /* above below */
+	PR_STEREO_ANAGLYPH = 1 << 5  /* anaglyph */
+	
+} PixbufRendererStereoMode;
+
 struct _RendererFuncs
 {
 	void (*queue)(void *renderer, gint x, gint y, gint w, gint h,
@@ -83,11 +94,11 @@
 	void (*invalidate_all)(void *renderer);
 	void (*invalidate_region)(void *renderer, gint x, gint y, gint w, gint h);
 	void (*scroll)(void *renderer, gint x_off, gint y_off);
+	void (*update_sizes)(void *renderer);
 
 	gint (*overlay_add)(void *renderer, GdkPixbuf *pixbuf, gint x, gint y, OverlayRendererFlags flags);
 	void (*overlay_set)(void *renderer, gint id, GdkPixbuf *pixbuf, gint x, gint y);
 	gboolean (*overlay_get)(void *renderer, gint id, GdkPixbuf **pixbuf, gint *x, gint *y);
-	void (*overlay_update_sizes)(void *renderer);
 	void (*overlay_draw)(void *renderer, gint x, gint y, gint w, gint h);
 
 	void (*free)(void *renderer);
@@ -99,6 +110,7 @@
 
 	gint image_width;	/* image actual dimensions (pixels) */
 	gint image_height;
+	gint stereo_pixbuf_off; /* offset of the right part of the stereo image in pixbuf */
 
 	GdkPixbuf *pixbuf;
 
@@ -193,7 +205,10 @@
 
 	gint orientation;
 
+	gint stereo_mode;
+	
 	RendererFuncs *renderer;
+	RendererFuncs *renderer2;
 };
 
 struct _PixbufRendererClass
--- a/src/renderer-tiles.c	Thu Jan 27 13:40:05 2011 +0100
+++ b/src/renderer-tiles.c	Fri Jan 28 11:05:07 2011 +0100
@@ -130,7 +130,10 @@
 	guint draw_idle_id; /* event source id */
 
 	GdkPixbuf *spare_tile;
-
+	
+	gint stereo_mode;
+	gint stereo_off_x;
+	gint stereo_off_y;
 };
 
 
@@ -176,37 +179,37 @@
 		{
 		if (pr_clip_region(x, y, w, h,
 				   0, 0,
-				   pr->window_width, pr->window_height,
+				   pr->viewport_width, pr->viewport_height,
 				   &rx, &ry, &rw, &rh))
 			{
-			gdk_window_clear_area(box->window, rx, ry, rw, rh);
+			gdk_window_clear_area(box->window, rx + rt->stereo_off_x, ry + rt->stereo_off_y, rw, rh);
 			rt_overlay_draw(rt, rx, ry, rw, rh, NULL);
 			}
 		return;
 		}
 
-	if (pr->vis_width < pr->window_width)
+	if (pr->vis_width < pr->viewport_width)
 		{
 		if (pr->x_offset > 0 &&
 		    pr_clip_region(x, y, w, h,
 				   0, 0,
-				   pr->x_offset, pr->window_height,
+				   pr->x_offset, pr->viewport_height,
 				   &rx, &ry, &rw, &rh))
 			{
-			gdk_window_clear_area(box->window, rx, ry, rw, rh);
+			gdk_window_clear_area(box->window, rx + rt->stereo_off_x, ry + rt->stereo_off_y, rw, rh);
 			rt_overlay_draw(rt, rx, ry, rw, rh, NULL);
 			}
-		if (pr->window_width - pr->vis_width - pr->x_offset > 0 &&
+		if (pr->viewport_width - pr->vis_width - pr->x_offset > 0 &&
 		    pr_clip_region(x, y, w, h,
 				   pr->x_offset + pr->vis_width, 0,
-				   pr->window_width - pr->vis_width - pr->x_offset, pr->window_height,
+				   pr->viewport_width - pr->vis_width - pr->x_offset, pr->viewport_height,
 				   &rx, &ry, &rw, &rh))
 			{
-			gdk_window_clear_area(box->window, rx, ry, rw, rh);
+			gdk_window_clear_area(box->window, rx + rt->stereo_off_x, ry + rt->stereo_off_y, rw, rh);
 			rt_overlay_draw(rt, rx, ry, rw, rh, NULL);
 			}
 		}
-	if (pr->vis_height < pr->window_height)
+	if (pr->vis_height < pr->viewport_height)
 		{
 		if (pr->y_offset > 0 &&
 		    pr_clip_region(x, y, w, h,
@@ -214,16 +217,16 @@
 				   pr->vis_width, pr->y_offset,
 				   &rx, &ry, &rw, &rh))
 			{
-			gdk_window_clear_area(box->window, rx, ry, rw, rh);
+			gdk_window_clear_area(box->window, rx + rt->stereo_off_x, ry + rt->stereo_off_y, rw, rh);
 			rt_overlay_draw(rt, rx, ry, rw, rh, NULL);
 			}
-		if (pr->window_height - pr->vis_height - pr->y_offset > 0 &&
+		if (pr->viewport_height - pr->vis_height - pr->y_offset > 0 &&
 		    pr_clip_region(x, y, w, h,
 				   pr->x_offset, pr->y_offset + pr->vis_height,
-				   pr->vis_width, pr->window_height - pr->vis_height - pr->y_offset,
+				   pr->vis_width, pr->viewport_height - pr->vis_height - pr->y_offset,
 				   &rx, &ry, &rw, &rh))
 			{
-			gdk_window_clear_area(box->window, rx, ry, rw, rh);
+			gdk_window_clear_area(box->window, rx + rt->stereo_off_x, ry + rt->stereo_off_y, rw, rh);
 			rt_overlay_draw(rt, rx, ry, rw, rh, NULL);
 			}
 		}
@@ -232,7 +235,7 @@
 static void rt_border_clear(RendererTiles *rt)
 {
 	PixbufRenderer *pr = rt->pr;
-	rt_border_draw(rt, 0, 0, pr->window_width, pr->window_height);
+	rt_border_draw(rt, 0, 0, pr->viewport_width, pr->viewport_height);
 }
 
 
@@ -502,8 +505,8 @@
 
 	if (od->flags & OVL_RELATIVE)
 		{
-		if (px < 0) px = pr->window_width - pw + px;
-		if (py < 0) py = pr->window_height - ph + py;
+		if (px < 0) px = pr->viewport_width - pw + px;
+		if (py < 0) py = pr->viewport_height - ph + py;
 		}
 
 	if (x) *x = px;
@@ -1218,6 +1221,7 @@
 	GtkWidget *box;
 	gboolean has_alpha;
 	gboolean draw = FALSE;
+	gint stereo_pixbuf_off;
 
 	if (it->render_todo == TILE_RENDER_NONE && it->pixmap && !new_data) return;
 
@@ -1242,6 +1246,7 @@
 	rt_tile_prepare(rt, it);
 	has_alpha = (pr->pixbuf && gdk_pixbuf_get_has_alpha(pr->pixbuf));
 
+	stereo_pixbuf_off = (rt->stereo_mode & PR_STEREO_RIGHT) ? pr->stereo_pixbuf_off : 0;
 	box = GTK_WIDGET(pr);
 
 	/* FIXME checker colors for alpha should be configurable,
@@ -1273,6 +1278,7 @@
 					    w, h,
 					    &pb_x, &pb_y,
 					    &pb_w, &pb_h);
+		src_x += stereo_pixbuf_off;
 
 		if (has_alpha)
 			{
@@ -1299,7 +1305,7 @@
 						box->style->fg_gc[GTK_WIDGET_STATE(box)],
 #endif
 						pr->pixbuf,
-						it->x + x, it->y + y,
+						it->x + x + stereo_pixbuf_off, it->y + y,
 						x, y,
 						w, h,
 						pr->dither_quality, it->x + x, it->y + y);
@@ -1337,6 +1343,7 @@
 					    w, h,
 					    &pb_x, &pb_y,
 					    &pb_w, &pb_h);
+
 		switch (pr->orientation)
 			{
 			gdouble tmp;
@@ -1352,7 +1359,8 @@
 				/* nothing to do */
 				break;
 			}
-
+		src_x += stereo_pixbuf_off * scale_x;
+		
 		/* HACK: The pixbuf scalers get kinda buggy(crash) with extremely
 		 * small sizes for anything but GDK_INTERP_NEAREST
 		 */
@@ -1396,7 +1404,7 @@
 				x, y,
 				x, y,
 				w, h,
-				pr->dither_quality, it->x + x, it->y + y);
+				pr->dither_quality, it->x + x + rt->stereo_off_x, it->y + y + rt->stereo_off_y);
 		}
 
 #if 0
@@ -1426,7 +1434,7 @@
 	gdk_draw_drawable(box->window, box->style->fg_gc[GTK_WIDGET_STATE(box)],
 #endif
 			  it->pixmap, x, y,
-			  pr->x_offset + (it->x - pr->x_scroll) + x, pr->y_offset + (it->y - pr->y_scroll) + y, w, h);
+			  pr->x_offset + (it->x - pr->x_scroll) + x + rt->stereo_off_x, pr->y_offset + (it->y - pr->y_scroll) + y + rt->stereo_off_y, w, h);
 
 	if (rt->overlay_list)
 		{
@@ -1869,8 +1877,8 @@
 		gdk_gc_set_exposures(gc, TRUE);
 		gdk_draw_drawable(box->window, gc,
 				  box->window,
-				  x2 + pr->x_offset, y2 + pr->y_offset,
-				  x1 + pr->x_offset, y1 + pr->y_offset, w, h);
+				  x2 + pr->x_offset + rt->stereo_off_x, y2 + pr->y_offset + rt->stereo_off_y,
+				  x1 + pr->x_offset + rt->stereo_off_x, y1 + pr->y_offset + rt->stereo_off_y, w, h);
 		g_object_unref(gc);
 
 		rt_overlay_queue_all(rt, x2, y2, x1, y1);
@@ -1941,6 +1949,28 @@
 	rt_overlay_draw((RendererTiles *)renderer, x, y, w, h, NULL);
 }
 
+static void renderer_update_sizes(void *renderer)
+{
+	RendererTiles *rt = (RendererTiles *)renderer;
+
+	rt_overlay_update_sizes(rt);
+
+	rt->stereo_off_x = 0;
+	rt->stereo_off_x = 0;
+	
+	if (rt->stereo_mode & PR_STEREO_RIGHT) 
+		{
+		if (rt->stereo_mode & PR_STEREO_HORIZ) 
+			{
+			rt->stereo_off_x = rt->pr->viewport_width;
+			}
+		else if (rt->stereo_mode & PR_STEREO_VERT) 
+			{
+			rt->stereo_off_y = rt->pr->viewport_height;
+			}
+		}
+}
+
 static void renderer_free(void *renderer)
 {
 	RendererTiles *rt = (RendererTiles *)renderer;
@@ -1955,7 +1985,7 @@
         g_free(rt);
 }
 
-RendererFuncs *renderer_tiles_new(PixbufRenderer *pr)
+RendererFuncs *renderer_tiles_new(PixbufRenderer *pr, gint stereo_mode)
 {
 	RendererTiles *rt = g_new0(RendererTiles, 1);
 	
@@ -1968,12 +1998,12 @@
 	rt->f.invalidate_all = renderer_invalidate_all;
 	rt->f.invalidate_region = renderer_invalidate_region;
 	rt->f.scroll = rt_scroll;
+	rt->f.update_sizes = renderer_update_sizes;
 
 
 	rt->f.overlay_add = renderer_tiles_overlay_add;
 	rt->f.overlay_set = renderer_tiles_overlay_set;
 	rt->f.overlay_get = renderer_tiles_overlay_get;
-	rt->f.overlay_update_sizes = rt_overlay_update_sizes;
 	rt->f.overlay_draw = renderer_overlay_draw;
 	
 	rt->tile_width = PR_TILE_SIZE;
@@ -1985,6 +2015,10 @@
 	rt->tile_cache_max = PR_CACHE_SIZE_DEFAULT;
 
 	rt->draw_idle_id = 0;
+	
+	rt->stereo_mode = stereo_mode;
+	rt->stereo_off_x = 0;
+	rt->stereo_off_y = 0;
 
 	g_signal_connect(G_OBJECT(pr), "hierarchy-changed",
 			 G_CALLBACK(rt_hierarchy_changed_cb), rt);
--- a/src/renderer-tiles.h	Thu Jan 27 13:40:05 2011 +0100
+++ b/src/renderer-tiles.h	Fri Jan 28 11:05:07 2011 +0100
@@ -19,7 +19,7 @@
 #include <pixbuf-renderer.h>
 
 
-RendererFuncs *renderer_tiles_new(PixbufRenderer *pr);
+RendererFuncs *renderer_tiles_new(PixbufRenderer *pr, gint stereo_flags);
 
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */