← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~nha/widelands/opengl into lp:widelands

 

Nicolai Hähnle has proposed merging lp:~nha/widelands/opengl into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #796673 in widelands: "Roads "light up" in the fog of war"
  https://bugs.launchpad.net/widelands/+bug/796673
  Bug #939709 in widelands: "OpenGL Terrain Rendering with GLSL"
  https://bugs.launchpad.net/widelands/+bug/939709
  Bug #1115664 in widelands: "Extremely slow framerate/performance with OpenGL"
  https://bugs.launchpad.net/widelands/+bug/1115664

For more details, see:
https://code.launchpad.net/~nha/widelands/opengl/+merge/147207

Rewrite the OpenGL renderer to be closer to OpenGL best practices. Using vertex arrays gets performance from < 0.5 fps to the point where OpenGL is no longer the bottleneck on at least my system. Tested both OpenGL and SDL rendering with a little bit of playing and editing.

Please take a quick look, in particular a quick test for regressions on different systems would be nice.
-- 
https://code.launchpad.net/~nha/widelands/opengl/+merge/147207
Your team Widelands Developers is requested to review the proposed merge of lp:~nha/widelands/opengl into lp:widelands.
=== modified file '.bzrignore'
--- .bzrignore	2012-06-20 09:07:10 +0000
+++ .bzrignore	2013-02-07 18:50:33 +0000
@@ -23,3 +23,5 @@
 /tribes/**/*.xhtml
 /global/**/*.xhtml
 
+# Local KDevelop settings files
+**/.kdev_include_paths

=== modified file 'src/graphic/graphic.cc'
--- src/graphic/graphic.cc	2013-01-05 20:11:57 +0000
+++ src/graphic/graphic.cc	2013-02-07 18:50:33 +0000
@@ -72,7 +72,7 @@
 	ImageLoader(Graphic& gr) : gr_(gr) {}
 	virtual ~ImageLoader() {}
 
-	IPicture* load(const string& fname, bool alpha) const {
+	IPicture* load(const string& fname, bool alpha, bool intensity) const {
 		FileRead fr;
 		SDL_Surface * sdlsurf;
 
@@ -84,7 +84,7 @@
 		if (!sdlsurf)
 			throw wexception("%s", IMG_GetError());
 
-		return gr_.convert_sdl_surface_to_picture(sdlsurf, alpha);
+		return gr_.convert_sdl_surface_to_picture(sdlsurf, alpha, intensity);
 	}
 private:
 	Graphic& gr_;
@@ -238,8 +238,7 @@
 
 		m_caps.gl.multitexture =
 			 ((strstr(extensions, "GL_ARB_multitexture") != 0) and
-			  (strstr(extensions, "GL_ARB_texture_env_combine") != 0))
-			and (m_caps.gl.max_tex_combined >= 6);
+			  (strstr(extensions, "GL_ARB_texture_env_combine") != 0));
 		log("Graphics: OpenGL: Multitexture capabilities ");
 		log(m_caps.gl.multitexture ? "sufficient\n" : "insufficient, only basic terrain rendering possible\n");
 
@@ -650,13 +649,14 @@
  * @param surf a SDL_Surface from which the Surface will be created; this function
  * takes ownership of surf
  * @param alpha if true the surface is created with alpha channel
+ * @param intensity if true the surface is created as an intensity texture in OpenGL mode
  * @return the new Surface created from the SDL_Surface
  */
-IPicture* Graphic::convert_sdl_surface_to_picture(SDL_Surface * surf, bool alpha) const
+IPicture* Graphic::convert_sdl_surface_to_picture(SDL_Surface * surf, bool alpha, bool intensity) const
 {
 #ifdef USE_OPENGL
 	if (g_opengl) {
-		return new GLSurfaceTexture(surf);
+		return new GLSurfaceTexture(surf, intensity);
 	}
 #endif
 	SDL_Surface * surface;
@@ -974,7 +974,7 @@
 
 	// load edge texture
 	snprintf(buf, sizeof(buf), "worlds/%s/pics/edge.png", worldname.c_str());
-	m_edgetexture = imgcache().load(PicMod_Game, buf, false);
+	m_edgetexture = imgcache().load(PicMod_Game, buf, false, true);
 }
 
 /**

=== modified file 'src/graphic/graphic.h'
--- src/graphic/graphic.h	2013-01-05 18:52:13 +0000
+++ src/graphic/graphic.h	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2012 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -119,7 +119,8 @@
 
 	void save_png(const IPicture*, StreamWrite*) const;
 
-	virtual IPicture* convert_sdl_surface_to_picture(SDL_Surface *, bool alpha = false) const;
+	virtual IPicture* convert_sdl_surface_to_picture
+		(SDL_Surface *, bool alpha = false, bool intensity = false) const;
 
 	Surface* create_surface(int32_t w, int32_t h, bool alpha = false) const;
 

=== modified file 'src/graphic/igraphic.h'
--- src/graphic/igraphic.h	2012-12-15 18:40:59 +0000
+++ src/graphic/igraphic.h	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2012 by the Widelands Development Team
+ * Copyright (C) 2006-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -32,7 +32,10 @@
 public:
 	virtual ~IGraphic() {};
 
-	virtual IPicture* convert_sdl_surface_to_picture(SDL_Surface*, bool alpha = false) const = 0;
+	virtual IPicture* convert_sdl_surface_to_picture
+		(SDL_Surface*,
+		 bool alpha = false,
+		 bool intensity = false) const = 0;
 	virtual IBlitableSurface * create_surface(int32_t w, int32_t h, bool alpha = false) const = 0;
 
 	virtual ImageCache& imgcache() const = 0;

=== modified file 'src/graphic/image_cache.cc'
--- src/graphic/image_cache.cc	2012-12-15 18:40:59 +0000
+++ src/graphic/image_cache.cc	2013-02-07 18:50:33 +0000
@@ -40,7 +40,7 @@
 	// Implements ImageCache
 	virtual const IPicture* get(PicMod, const string& hash) const;
 	virtual const IPicture* insert(PicMod, const string& hash, const IPicture*);
-	virtual const IPicture* load(PicMod, const string& fn, bool alpha);
+	virtual const IPicture* load(PicMod, const string& fn, bool alpha, bool intensity);
 	virtual void flush(PicMod);
 
 private:
@@ -96,7 +96,7 @@
 }
 
 const IPicture* ImageCacheImpl::load
-		(PicMod module, const string& fname, bool alpha)
+		(PicMod module, const string& fname, bool alpha, bool intensity)
 {
 	//  Check if the picture is already loaded.
 	PictureMap::iterator it = m_picturemap.find(fname);
@@ -104,7 +104,7 @@
 	if (it == m_picturemap.end()) {
 		PictureRec rec;
 
-		rec.picture = img_loader_->load(fname, alpha);
+		rec.picture = img_loader_->load(fname, alpha, intensity);
 		rec.modules = 0;
 
 		it = m_picturemap.insert(make_pair(fname, rec)).first;

=== modified file 'src/graphic/image_cache.h'
--- src/graphic/image_cache.h	2012-12-13 21:10:32 +0000
+++ src/graphic/image_cache.h	2013-02-07 18:50:33 +0000
@@ -65,7 +65,7 @@
 
 	/// Loads an Image from disk and caches it. If it was already
 	/// cached, it is simply returned.
-	virtual const IPicture* load(PicMod, const std::string& fn, bool alpha = true) = 0;
+	virtual const IPicture* load(PicMod, const std::string& fn, bool alpha = true, bool intensity = false) = 0;
 
 	/// Clears the Cache for the given PicMod
 	virtual void flush(PicMod) = 0;

=== modified file 'src/graphic/image_loader.h'
--- src/graphic/image_loader.h	2012-12-13 21:10:32 +0000
+++ src/graphic/image_loader.h	2013-02-07 18:50:33 +0000
@@ -30,7 +30,7 @@
 public:
 	virtual ~IImageLoader() {}
 
-	virtual IPicture* load(const std::string& fn, bool alpha) const = 0;
+	virtual IPicture* load(const std::string& fn, bool alpha, bool intensity = false) const = 0;
 };
 
 #endif /* end of include guard: IMAGE_LOADER_H */

=== added file 'src/graphic/render/gamerenderer.cc'
--- src/graphic/render/gamerenderer.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer.cc	2013-02-07 18:50:33 +0000
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2010-2013 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include "gamerenderer.h"
+
+#include "graphic/rendertarget.h"
+
+#include "logic/editor_game_base.h"
+#include "logic/player.h"
+
+#include "wui/mapviewpixelfunctions.h"
+#include "wui/overlay_manager.h"
+
+#include "upcast.h"
+
+using namespace Widelands;
+
+GameRenderer::GameRenderer()
+{
+}
+
+GameRenderer::~GameRenderer()
+{
+}
+
+void GameRenderer::rendermap
+	(RenderTarget & dst,
+	 Widelands::Editor_Game_Base const &       egbase,
+	 Widelands::Player           const &       player,
+	 Point                                     viewofs)
+{
+	m_dst = &dst;
+	m_dst_offset = -viewofs;
+	m_egbase = &egbase;
+	m_player = &player;
+
+	draw_wrapper();
+}
+
+void GameRenderer::rendermap
+	(RenderTarget & dst,
+	 Widelands::Editor_Game_Base const & egbase,
+	 Point                               viewofs)
+{
+	m_dst = &dst;
+	m_dst_offset = -viewofs;
+	m_egbase = &egbase;
+	m_player = 0;
+
+	draw_wrapper();
+}
+
+void GameRenderer::draw_wrapper()
+{
+	Point tl_map = m_dst->get_offset() - m_dst_offset;
+
+	assert(tl_map.x >= 0); // divisions involving negative numbers are bad
+	assert(tl_map.y >= 0);
+
+	m_minfx = tl_map.x / TRIANGLE_WIDTH - 1;
+	m_minfy = tl_map.y / TRIANGLE_HEIGHT - 1;
+	m_maxfx = (tl_map.x + m_dst->get_rect().w + (TRIANGLE_WIDTH / 2)) / TRIANGLE_WIDTH;
+	m_maxfy = (tl_map.y + m_dst->get_rect().h) / TRIANGLE_HEIGHT;
+
+	// fudge for triangle boundary effects and for height differences
+	m_minfx -= 1;
+	m_minfy -= 1;
+	m_maxfx += 1;
+	m_maxfy += 10;
+
+	draw();
+}
+
+void GameRenderer::draw_objects()
+{
+	Map const & map = m_egbase->map();
+
+	for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
+		for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
+			Coords ncoords(fx, fy);
+			map.normalize_coords(ncoords);
+			FCoords f = map.get_fcoords(ncoords);
+			FCoords r = map.r_n(f);
+			FCoords bl = map.bl_n(f);
+			FCoords br = map.br_n(f);
+			Point f_pos, r_pos, bl_pos, br_pos;
+			MapviewPixelFunctions::get_basepix(Coords(fx, fy), f_pos.x, f_pos.y);
+			MapviewPixelFunctions::get_basepix(Coords(fx + 1, fy), r_pos.x, r_pos.y);
+			MapviewPixelFunctions::get_basepix(Coords(fx + (fy & 1) - 1, fy + 1), bl_pos.x, bl_pos.y);
+			MapviewPixelFunctions::get_basepix(Coords(fx + (fy & 1), fy + 1), br_pos.x, br_pos.y);
+			f_pos.y -= f.field->get_height() * HEIGHT_FACTOR;
+			r_pos.y -= r.field->get_height() * HEIGHT_FACTOR;
+			bl_pos.y -= bl.field->get_height() * HEIGHT_FACTOR;
+			br_pos.y -= br.field->get_height() * HEIGHT_FACTOR;
+			f_pos += m_dst_offset;
+			r_pos += m_dst_offset;
+			bl_pos += m_dst_offset;
+			br_pos += m_dst_offset;
+
+			uint8_t f_owner_number = f.field->get_owned_by();
+			uint8_t r_owner_number = r.field->get_owned_by();
+			uint8_t bl_owner_number = bl.field->get_owned_by();
+			uint8_t br_owner_number = br.field->get_owned_by();
+			bool f_isborder = f.field->is_border();
+			bool r_isborder = r.field->is_border();
+			bool bl_isborder = bl.field->is_border();
+			bool br_isborder = br.field->is_border();
+			Vision f_vision = 2;
+			Vision r_vision = 2;
+			Vision bl_vision = 2;
+			Vision br_vision = 2;
+
+			if (m_player && !m_player->see_all()) {
+				Player::Field const & f_pl = m_player->fields()[map.get_index(f, map.get_width())];
+				Player::Field const & r_pl = m_player->fields()[map.get_index(r, map.get_width())];
+				Player::Field const & bl_pl = m_player->fields()[map.get_index(bl, map.get_width())];
+				Player::Field const & br_pl = m_player->fields()[map.get_index(br, map.get_width())];
+
+				f_vision = f_pl.vision;
+				r_vision = r_pl.vision;
+				bl_vision = bl_pl.vision;
+				br_vision = br_pl.vision;
+				if (f_vision == 1) {
+					f_owner_number = f_pl.owner;
+					f_isborder = f_pl.border;
+				}
+				if (r_vision == 1) {
+					r_owner_number = r_pl.owner;
+					r_isborder = r_pl.border;
+				}
+				if (bl_vision == 1) {
+					bl_owner_number = bl_pl.owner;
+					bl_isborder = bl_pl.border;
+				}
+				if (br_vision == 1) {
+					br_owner_number = br_pl.owner;
+					br_isborder = br_pl.border;
+				}
+			}
+
+			if (f_isborder) {
+				Player const & owner = m_egbase->player(f_owner_number);
+				uint32_t const anim = owner.frontier_anim();
+				if (f_vision)
+					m_dst->drawanim(f_pos, anim, 0, &owner);
+				if
+					((f_vision || r_vision) &&
+					 r_isborder &&
+					 (r_owner_number == f_owner_number || !r_owner_number))
+					m_dst->drawanim(middle(f_pos, r_pos), anim, 0, &owner);
+				if
+					((f_vision || bl_vision) &&
+					 bl_isborder &&
+					 (bl_owner_number == f_owner_number || !bl_owner_number))
+					m_dst->drawanim(middle(f_pos, bl_pos), anim, 0, &owner);
+				if
+					((f_vision || br_vision) &&
+					 br_isborder &&
+					 (br_owner_number == f_owner_number || !br_owner_number))
+					m_dst->drawanim(middle(f_pos, br_pos), anim, 0, &owner);
+			}
+
+			if (1 < f_vision) { // Render stuff that belongs to the node.
+				if (BaseImmovable * const imm = f.field->get_immovable())
+					imm->draw(*m_egbase, *m_dst, f, f_pos);
+				for
+					(Bob * bob = f.field->get_first_bob();
+					 bob;
+					 bob = bob->get_next_bob())
+					bob->draw(*m_egbase, *m_dst, f_pos);
+			} else if (f_vision == 1) {
+				Player::Field const & f_pl = m_player->fields()[map.get_index(f, map.get_width())];
+				const Player * owner = f_owner_number ? m_egbase->get_player(f_owner_number) : 0;
+				if
+					(const Map_Object_Descr * const map_object_descr =
+						f_pl.map_object_descr[TCoords<>::None])
+				{
+					if
+						(const Player::Constructionsite_Information * const csinf =
+						 f_pl.constructionsite[TCoords<>::None])
+					{
+						// draw the partly finished constructionsite
+						uint32_t anim;
+						try {
+							anim = csinf->becomes->get_animation("build");
+						} catch (Map_Object_Descr::Animation_Nonexistent & e) {
+							try {
+								anim = csinf->becomes->get_animation("unoccupied");
+							} catch (Map_Object_Descr::Animation_Nonexistent) {
+								anim = csinf->becomes->get_animation("idle");
+							}
+						}
+						const AnimationGfx::Index nr_frames = g_gr->nr_frames(anim);
+						uint32_t cur_frame =
+							csinf->totaltime ? csinf->completedtime * nr_frames / csinf->totaltime : 0;
+						uint32_t tanim = cur_frame * FRAME_LENGTH;
+						uint32_t w, h;
+						g_gr->get_animation_size(anim, tanim, w, h);
+						uint32_t lines = h * csinf->completedtime * nr_frames;
+						if (csinf->totaltime)
+							lines /= csinf->totaltime;
+						assert(h * cur_frame <= lines);
+						lines -= h * cur_frame; //  This won't work if pictures have various sizes.
+
+						if (cur_frame) // not the first frame
+							// draw the prev frame from top to where next image will be drawing
+							m_dst->drawanimrect
+								(f_pos, anim, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
+						else if (csinf->was) {
+							// Is the first frame, but there was another building here before,
+							// get its last build picture and draw it instead.
+							uint32_t a;
+							try {
+								a = csinf->was->get_animation("unoccupied");
+							} catch (Map_Object_Descr::Animation_Nonexistent & e) {
+								a = csinf->was->get_animation("idle");
+							}
+							m_dst->drawanimrect
+								(f_pos, a, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
+						}
+						assert(lines <= h);
+						m_dst->drawanimrect(f_pos, anim, tanim, owner, Rect(Point(0, h - lines), w, lines));
+					} else if (upcast(const Building_Descr, building, map_object_descr)) {
+						// this is a building therefore we either draw unoccupied or idle animation
+						uint32_t pic;
+						try {
+							pic = building->get_animation("unoccupied");
+						} catch (Map_Object_Descr::Animation_Nonexistent & e) {
+							pic = building->get_animation("idle");
+						}
+						m_dst->drawanim(f_pos, pic, 0, owner);
+					} else if (const uint32_t pic = map_object_descr->main_animation()) {
+						m_dst->drawanim(f_pos, pic, 0, owner);
+					} else if (map_object_descr == &Widelands::g_flag_descr) {
+						m_dst->drawanim(f_pos, owner->flag_anim(), 0, owner);
+					}
+				}
+			}
+
+			{
+				// Render overlays on the node
+				Overlay_Manager::Overlay_Info overlay_info[MAX_OVERLAYS_PER_NODE];
+
+				const Overlay_Manager::Overlay_Info * const end =
+					overlay_info
+					+
+					map.overlay_manager().get_overlays(f, overlay_info);
+
+				for
+					(const Overlay_Manager::Overlay_Info * it = overlay_info;
+					 it < end;
+					 ++it)
+					m_dst->blit(f_pos - it->hotspot, it->pic);
+			}
+
+			{
+				// Render overlays on the R triangle
+				Overlay_Manager::Overlay_Info overlay_info[MAX_OVERLAYS_PER_TRIANGLE];
+				Overlay_Manager::Overlay_Info const * end =
+					overlay_info
+					+
+					map.overlay_manager().get_overlays
+							 	(TCoords<>(f, TCoords<>::R), overlay_info);
+
+				Point pos
+					((f_pos.x + r_pos.x + br_pos.x) / 3,
+					 (f_pos.y + r_pos.y + br_pos.y) / 3);
+
+				for
+					(Overlay_Manager::Overlay_Info const * it = overlay_info;
+					 it < end;
+					 ++it)
+					m_dst->blit(pos - it->hotspot, it->pic);
+			}
+
+			{
+				// Render overlays on the D triangle
+				Overlay_Manager::Overlay_Info overlay_info[MAX_OVERLAYS_PER_TRIANGLE];
+				Overlay_Manager::Overlay_Info const * end =
+					overlay_info
+					+
+					map.overlay_manager().get_overlays
+							 	(TCoords<>(f, TCoords<>::D), overlay_info);
+
+				Point pos
+					((f_pos.x + bl_pos.x + br_pos.x) / 3,
+					 (f_pos.y + bl_pos.y + br_pos.y) / 3);
+
+				for
+					(Overlay_Manager::Overlay_Info const * it = overlay_info;
+					 it < end;
+					 ++it)
+					m_dst->blit(pos - it->hotspot, it->pic);
+			}
+		}
+	}
+}

=== added file 'src/graphic/render/gamerenderer.h'
--- src/graphic/render/gamerenderer.h	1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer.h	2013-02-07 18:50:33 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010-2013 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef WIDELANDS_GAMERENDERER_H
+#define WIDELANDS_GAMERENDERER_H
+
+#include "point.h"
+
+namespace Widelands {
+	struct Player;
+	struct Editor_Game_Base;
+};
+
+struct RenderTarget;
+
+/**
+ * This abstract base class renders the main game view into an
+ * arbitrary @ref RenderTarget.
+ *
+ * Specializations exist for SDL software rendering and for OpenGL rendering.
+ *
+ * Users of this class should keep instances alive for as long as possible,
+ * so that target-specific optimizations (such as caching data) can
+ * be effective.
+ */
+struct GameRenderer {
+public:
+	GameRenderer();
+	virtual ~GameRenderer();
+
+	/**
+	 * Renders the map from a player's point of view into the
+	 * given drawing window.
+	 *
+	 * @param viewofs is the offset of the upper left corner of
+	 * the window into the map, in pixels.
+	 */
+	void rendermap
+		(RenderTarget & dst,
+		 Widelands::Editor_Game_Base const &       egbase,
+		 Widelands::Player           const &       player,
+		 Point                                     viewofs);
+
+	/**
+	 * Renders the map from an omniscient perspective.
+	 * This is used for spectators, players that see all, and in the editor.
+	 */
+	void rendermap
+		(RenderTarget & dst,
+		 Widelands::Editor_Game_Base const & egbase,
+		 Point                               viewofs);
+
+protected:
+	virtual void draw() = 0;
+
+	void draw_objects();
+
+	/**
+	 * The following variables, which are setup by @ref rendermap,
+	 * are only valid during rendering,
+	 * and should be treated as read-only by derived classes.
+	 */
+	/*@{*/
+	RenderTarget * m_dst;
+	Widelands::Editor_Game_Base const * m_egbase;
+	Widelands::Player const * m_player;
+
+	/// Translation from map pixel coordinates to @ref m_dst pixel coordinates
+	Point m_dst_offset;
+
+	int32_t m_minfx;
+	int32_t m_minfy;
+	int32_t m_maxfx;
+	int32_t m_maxfy;
+	/*@}*/
+
+private:
+	void draw_wrapper();
+};
+
+#endif //WIDELANDS_GAMEVIEW_H

=== added file 'src/graphic/render/gamerenderer_gl.cc'
--- src/graphic/render/gamerenderer_gl.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer_gl.cc	2013-02-07 18:50:33 +0000
@@ -0,0 +1,746 @@
+/*
+ * Copyright (C) 2011-2013 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifdef USE_OPENGL
+#include "gamerenderer_gl.h"
+
+#include "gl_surface.h"
+
+#include "logic/editor_game_base.h"
+#include "logic/player.h"
+
+#include "graphic/graphic.h"
+#include "graphic/rendertarget.h"
+#include "graphic/texture.h"
+
+#include "wui/mapviewpixelconstants.h"
+#include "wui/mapviewpixelfunctions.h"
+#include "wui/overlay_manager.h"
+
+using namespace Widelands;
+
+static const uint32_t PatchSize = 4;
+
+GameRendererGL::GameRendererGL() :
+	m_patch_vertices_size(0),
+	m_patch_indices_size(0),
+	m_edge_vertices_size(0),
+	m_road_vertices_size(0)
+{
+}
+
+GameRendererGL::~GameRendererGL()
+{
+}
+
+uint32_t GameRendererGL::patch_index(int32_t fx, int32_t fy) const
+{
+	uint32_t x = fx - m_patch_size.x;
+	uint32_t y = fy - m_patch_size.y;
+
+	assert(x < m_patch_size.w);
+	assert(y < m_patch_size.h);
+
+	uint32_t outerx = x / PatchSize;
+	uint32_t outery = y / PatchSize;
+	uint32_t innerx = x % PatchSize;
+	uint32_t innery = y % PatchSize;
+
+	return
+		(outery * (m_patch_size.w / PatchSize) + outerx) * (PatchSize * PatchSize) +
+		innery * PatchSize + innerx;
+}
+
+uint8_t GameRendererGL::field_brightness(const FCoords & coords) const
+{
+	uint32_t brightness;
+	brightness = 144 + coords.field->get_brightness();
+	brightness = (brightness * 255) / 160;
+	if (brightness > 255)
+		brightness = 255;
+
+	if (m_player && !m_player->see_all()) {
+		const Map & map = m_egbase->map();
+		const Player::Field & pf = m_player->fields()[Map::get_index(coords, map.get_width())];
+		if (pf.vision == 0) {
+			return 0;
+		} else if (pf.vision == 1) {
+			static const uint32_t DecayTime = 20000;
+			Duration time_ago = m_egbase->get_gametime() - pf.time_node_last_unseen;
+			if (time_ago < DecayTime)
+				brightness = (brightness * (2 * DecayTime - time_ago)) / (2 * DecayTime);
+			else
+				brightness = brightness / 2;
+		}
+	}
+
+	return brightness;
+}
+
+void GameRendererGL::draw()
+{
+	m_surface = dynamic_cast<GLSurface *>(m_dst->get_surface());
+	if (!m_surface)
+		return;
+	m_rect = m_dst->get_rect();
+	m_surface_offset = m_dst_offset + m_rect + m_dst->get_offset();
+
+	m_patch_size.x = m_minfx - 1;
+	m_patch_size.y = m_minfy;
+	m_patch_size.w = ((m_maxfx - m_minfx + 2 + PatchSize) / PatchSize) * PatchSize;
+	m_patch_size.h = ((m_maxfy - m_minfy + 1 + PatchSize) / PatchSize) * PatchSize;
+
+	glScissor
+		(m_rect.x, m_surface->get_h() - m_rect.y - m_rect.h,
+		 m_rect.w, m_rect.h);
+	glEnable(GL_SCISSOR_TEST);
+
+	prepare_terrain_base();
+	draw_terrain_base();
+	if (g_gr->caps().gl.multitexture && g_gr->caps().gl.max_tex_combined >= 2) {
+		prepare_terrain_dither();
+		draw_terrain_dither();
+	}
+	prepare_roads();
+	draw_roads();
+	draw_objects();
+
+	glDisable(GL_SCISSOR_TEST);
+}
+
+template<typename vertex>
+void GameRendererGL::compute_basevertex(const Coords & coords, vertex & vtx) const
+{
+	Map const & map = m_egbase->map();
+	Coords ncoords(coords);
+	map.normalize_coords(ncoords);
+	FCoords fcoords = map.get_fcoords(ncoords);
+	Point pix;
+	MapviewPixelFunctions::get_basepix(coords, pix.x, pix.y);
+	pix.y -= fcoords.field->get_height() * HEIGHT_FACTOR;
+	pix += m_surface_offset;
+	vtx.x = pix.x;
+	vtx.y = pix.y;
+	Point tex;
+	MapviewPixelFunctions::get_basepix(coords, tex.x, tex.y);
+	vtx.tcx = float(tex.x) / TEXTURE_WIDTH;
+	vtx.tcy = float(tex.y) / TEXTURE_HEIGHT;
+	uint8_t brightness = field_brightness(fcoords);
+	vtx.color[0] = vtx.color[1] = vtx.color[2] = brightness;
+	vtx.color[3] = 255;
+}
+
+void GameRendererGL::prepare_terrain_base()
+{
+	assert(sizeof(basevertex) == 32);
+
+	Map const & map = m_egbase->map();
+
+	uint32_t reqsize = m_patch_size.w * m_patch_size.h;
+	if (reqsize > 0x10000)
+		throw wexception("Too many vertices; decrease screen resolution");
+
+	if (reqsize > m_patch_vertices_size) {
+		m_patch_vertices.reset(new basevertex[reqsize]);
+		m_patch_vertices_size = reqsize;
+	}
+
+	if (m_terrain_freq.size() < 16)
+		m_terrain_freq.resize(16);
+	m_terrain_freq.assign(m_terrain_freq.size(), 0);
+
+	uint32_t index = 0;
+	for (uint32_t outery = 0; outery < m_patch_size.h / PatchSize; ++outery) {
+		for (uint32_t outerx = 0; outerx < m_patch_size.w / PatchSize; ++outerx) {
+			for (uint32_t innery = 0; innery < PatchSize; ++innery) {
+				for (uint32_t innerx = 0; innerx < PatchSize; ++innerx) {
+					Coords coords
+						(m_patch_size.x + outerx * PatchSize + innerx,
+						 m_patch_size.y + outery * PatchSize + innery);
+					assert(index == patch_index(coords.x, coords.y));
+					compute_basevertex(coords, m_patch_vertices[index]);
+					++index;
+
+					if
+						(coords.x < m_minfx || coords.y < m_minfy ||
+						 coords.x > m_maxfx || coords.y > m_maxfy)
+						continue;
+
+					Coords ncoords(coords);
+					map.normalize_coords(ncoords);
+					FCoords fcoords = map.get_fcoords(ncoords);
+					Terrain_Index ter_d = fcoords.field->get_terrains().d;
+					Terrain_Index ter_r = fcoords.field->get_terrains().r;
+					if (ter_d >= m_terrain_freq.size())
+						m_terrain_freq.resize(ter_d + 1);
+					m_terrain_freq[ter_d] += 1;
+					if (ter_r >= m_terrain_freq.size())
+						m_terrain_freq.resize(ter_r + 1);
+					m_terrain_freq[ter_r] += 1;
+				}
+			}
+		}
+	}
+
+	m_terrain_freq_cum.resize(m_terrain_freq.size());
+	uint32_t nrtriangles = 0;
+	for (uint32_t idx = 0; idx < m_terrain_freq.size(); ++idx) {
+		m_terrain_freq_cum[idx] = nrtriangles;
+		nrtriangles += m_terrain_freq[idx];
+	}
+
+	if (3 * nrtriangles > m_patch_indices_size) {
+		m_patch_indices.reset(new uint16_t[3 * nrtriangles]);
+		m_patch_indices_size = 3 * nrtriangles;
+	}
+
+	index = 0;
+	for (Terrain_Index ter = 0; ter < m_terrain_freq.size(); ++ter) {
+		assert(index == 3 * m_terrain_freq_cum[ter]);
+		for (uint32_t outery = 0; outery < m_patch_size.h / PatchSize; ++outery) {
+			for (uint32_t outerx = 0; outerx < m_patch_size.w / PatchSize; ++outerx) {
+				for (uint32_t innery = 0; innery < PatchSize; ++innery) {
+					for (uint32_t innerx = 0; innerx < PatchSize; ++innerx) {
+						Coords coords
+							(m_patch_size.x + PatchSize * outerx + innerx,
+							 m_patch_size.y + PatchSize * outery + innery);
+						if
+							(coords.x < m_minfx || coords.y < m_minfy ||
+							 coords.x > m_maxfx || coords.y > m_maxfy)
+							continue;
+
+						Coords ncoords(coords);
+						map.normalize_coords(ncoords);
+						FCoords fcoords = map.get_fcoords(ncoords);
+						if (fcoords.field->get_terrains().d == ter) {
+							Coords brn(coords.x + (coords.y & 1), coords.y + 1);
+							Coords bln(brn.x - 1, brn.y);
+							m_patch_indices[index++] = patch_index(coords.x, coords.y);
+							m_patch_indices[index++] = patch_index(bln.x, bln.y);
+							m_patch_indices[index++] = patch_index(brn.x, brn.y);
+						}
+						if (fcoords.field->get_terrains().r == ter) {
+							Coords brn(coords.x + (coords.y & 1), coords.y + 1);
+							Coords rn(coords.x + 1, coords.y);
+							m_patch_indices[index++] = patch_index(coords.x, coords.y);
+							m_patch_indices[index++] = patch_index(brn.x, brn.y);
+							m_patch_indices[index++] = patch_index(rn.x, rn.y);
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+void GameRendererGL::draw_terrain_base()
+{
+	Map const & map = m_egbase->map();
+	World const & world = map.world();
+
+	glMatrixMode(GL_TEXTURE);
+	glLoadIdentity();
+
+	glVertexPointer(2, GL_FLOAT, sizeof(basevertex), &m_patch_vertices[0].x);
+	glTexCoordPointer(2, GL_FLOAT, sizeof(basevertex), &m_patch_vertices[0].tcx);
+	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(basevertex), &m_patch_vertices[0].color);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	glEnableClientState(GL_COLOR_ARRAY);
+
+	glColor3f(1.0, 1.0, 1.0);
+	glDisable(GL_BLEND);
+
+	for (Terrain_Index ter = 0; ter < m_terrain_freq.size(); ++ter) {
+		if (!m_terrain_freq[ter])
+			continue;
+
+		const Texture & texture =
+				*g_gr->get_maptexture_data
+					(world.terrain_descr(ter).get_texture());
+		glBindTexture(GL_TEXTURE_2D, texture.getTexture());
+		glDrawRangeElements
+			(GL_TRIANGLES,
+			 0, m_patch_size.w * m_patch_size.h - 1,
+			 3 * m_terrain_freq[ter], GL_UNSIGNED_SHORT,
+			 &m_patch_indices[3 * m_terrain_freq_cum[ter]]);
+	}
+
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glDisableClientState(GL_COLOR_ARRAY);
+}
+
+/*
+ * Schematic of triangle neighborhood:
+ *
+ *               *
+ *              / \
+ *             / u \
+ *         (f)/     \
+ *    *------*------* (r)
+ *     \  l / \  r / \
+ *      \  /   \  /   \
+ *       \/  d  \/ rr  \
+ *       *------*------* (br)
+ *        \ dd /
+ *         \  /
+ *          \/
+ *          *
+ */
+void GameRendererGL::prepare_terrain_dither()
+{
+	assert(sizeof(dithervertex) == 32);
+
+	Map const & map = m_egbase->map();
+	World const & world = map.world();
+
+	if (m_terrain_edge_freq.size() < 16)
+		m_terrain_edge_freq.resize(16);
+	m_terrain_edge_freq.assign(m_terrain_edge_freq.size(), 0);
+
+	for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
+		for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
+			Coords ncoords(fx, fy);
+			map.normalize_coords(ncoords);
+			FCoords fcoords = map.get_fcoords(ncoords);
+
+			Terrain_Index ter_d = fcoords.field->get_terrains().d;
+			Terrain_Index ter_r = fcoords.field->get_terrains().r;
+			Terrain_Index ter_u = map.tr_n(fcoords).field->get_terrains().d;
+			Terrain_Index ter_rr = map.r_n(fcoords).field->get_terrains().d;
+			Terrain_Index ter_l = map.l_n(fcoords).field->get_terrains().r;
+			Terrain_Index ter_dd = map.bl_n(fcoords).field->get_terrains().r;
+			int32_t lyr_d = world.get_ter(ter_d).dither_layer();
+			int32_t lyr_r = world.get_ter(ter_r).dither_layer();
+			int32_t lyr_u = world.get_ter(ter_u).dither_layer();
+			int32_t lyr_rr = world.get_ter(ter_rr).dither_layer();
+			int32_t lyr_l = world.get_ter(ter_l).dither_layer();
+			int32_t lyr_dd = world.get_ter(ter_dd).dither_layer();
+
+			if (lyr_r > lyr_d) {
+				if (ter_r >= m_terrain_edge_freq.size())
+					m_terrain_edge_freq.resize(ter_r + 1);
+				m_terrain_edge_freq[ter_r] += 1;
+			} else if (ter_d != ter_r) {
+				if (ter_d >= m_terrain_edge_freq.size())
+					m_terrain_edge_freq.resize(ter_d + 1);
+				m_terrain_edge_freq[ter_d] += 1;
+			}
+			if ((lyr_u > lyr_r) || (lyr_u == lyr_r && ter_u != ter_r)) {
+				if (ter_u >= m_terrain_edge_freq.size())
+					m_terrain_edge_freq.resize(ter_u + 1);
+				m_terrain_edge_freq[ter_u] += 1;
+			}
+			if (lyr_rr > lyr_r) {
+				if (ter_rr >= m_terrain_edge_freq.size())
+					m_terrain_edge_freq.resize(ter_rr + 1);
+				m_terrain_edge_freq[ter_rr] += 1;
+			}
+			if ((lyr_l > lyr_d) || (lyr_l == lyr_d && ter_l != ter_d)) {
+				if (ter_l >= m_terrain_edge_freq.size())
+					m_terrain_edge_freq.resize(ter_l + 1);
+				m_terrain_edge_freq[ter_l] += 1;
+			}
+			if (lyr_dd > lyr_d) {
+				if (ter_dd >= m_terrain_edge_freq.size())
+					m_terrain_edge_freq.resize(ter_dd + 1);
+				m_terrain_edge_freq[ter_dd] += 1;
+			}
+		}
+	}
+
+	uint32_t nrtriangles = 0;
+	m_terrain_edge_freq_cum.resize(m_terrain_edge_freq.size());
+	for (Terrain_Index ter = 0; ter < m_terrain_edge_freq.size(); ++ter) {
+		m_terrain_edge_freq_cum[ter] = nrtriangles;
+		nrtriangles += m_terrain_edge_freq[ter];
+	}
+
+	if (3 * nrtriangles > m_edge_vertices_size) {
+		m_edge_vertices.reset(new dithervertex[3 * nrtriangles]);
+		m_edge_vertices_size = 3 * nrtriangles;
+	}
+
+	std::vector<uint32_t> indexs;
+	indexs.resize(m_terrain_edge_freq_cum.size());
+	for (Terrain_Index ter = 0; ter < m_terrain_edge_freq.size(); ++ter)
+		indexs[ter] = 3 * m_terrain_edge_freq_cum[ter];
+
+	for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
+		for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
+			Coords ncoords(fx, fy);
+			map.normalize_coords(ncoords);
+			FCoords fcoords = map.get_fcoords(ncoords);
+
+			Terrain_Index ter_d = fcoords.field->get_terrains().d;
+			Terrain_Index ter_r = fcoords.field->get_terrains().r;
+			Terrain_Index ter_u = map.tr_n(fcoords).field->get_terrains().d;
+			Terrain_Index ter_rr = map.r_n(fcoords).field->get_terrains().d;
+			Terrain_Index ter_l = map.l_n(fcoords).field->get_terrains().r;
+			Terrain_Index ter_dd = map.bl_n(fcoords).field->get_terrains().r;
+			int32_t lyr_d = world.get_ter(ter_d).dither_layer();
+			int32_t lyr_r = world.get_ter(ter_r).dither_layer();
+			int32_t lyr_u = world.get_ter(ter_u).dither_layer();
+			int32_t lyr_rr = world.get_ter(ter_rr).dither_layer();
+			int32_t lyr_l = world.get_ter(ter_l).dither_layer();
+			int32_t lyr_dd = world.get_ter(ter_dd).dither_layer();
+
+			Coords f(fx, fy);
+			Coords rn(fx + 1, fy);
+			Coords brn(fx + (fy & 1), fy + 1);
+			Coords bln(brn.x - 1, brn.y);
+
+			// Hack texture coordinates to avoid wrap-around
+			static const float TyZero = 1.0 / TEXTURE_HEIGHT;
+			static const float TyOne = 1.0 - TyZero;
+
+			uint32_t index;
+			if (lyr_r > lyr_d) {
+				index = indexs[ter_r];
+				compute_basevertex(f, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				compute_basevertex(bln, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.5;
+				m_edge_vertices[index].edgey = TyOne;
+				++index;
+				compute_basevertex(brn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 1.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				indexs[ter_r] = index;
+			} else if (ter_d != ter_r) {
+				index = indexs[ter_d];
+				compute_basevertex(f, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				compute_basevertex(brn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 1.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				compute_basevertex(rn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.5;
+				m_edge_vertices[index].edgey = TyOne;
+				++index;
+				indexs[ter_d] = index;
+			}
+			if ((lyr_u > lyr_r) || (lyr_u == lyr_r && ter_u != ter_r)) {
+				index = indexs[ter_u];
+				compute_basevertex(f, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				compute_basevertex(brn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.5;
+				m_edge_vertices[index].edgey = TyOne;
+				++index;
+				compute_basevertex(rn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 1.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				indexs[ter_u] = index;
+			}
+			if (lyr_rr > lyr_r) {
+				index = indexs[ter_rr];
+				compute_basevertex(f, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.5;
+				m_edge_vertices[index].edgey = TyOne;
+				++index;
+				compute_basevertex(brn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 1.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				compute_basevertex(rn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				indexs[ter_rr] = index;
+			}
+			if ((lyr_l > lyr_d) || (lyr_l == lyr_d && ter_l != ter_d)) {
+				index = indexs[ter_l];
+				compute_basevertex(f, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 1.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				compute_basevertex(bln, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				compute_basevertex(brn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.5;
+				m_edge_vertices[index].edgey = TyOne;
+				++index;
+				indexs[ter_l] = index;
+			}
+			if (lyr_dd > lyr_d) {
+				index = indexs[ter_dd];
+				compute_basevertex(f, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.5;
+				m_edge_vertices[index].edgey = TyOne;
+				++index;
+				compute_basevertex(bln, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 1.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				compute_basevertex(brn, m_edge_vertices[index]);
+				m_edge_vertices[index].edgex = 0.0;
+				m_edge_vertices[index].edgey = TyZero;
+				++index;
+				indexs[ter_dd] = index;
+			}
+		}
+	}
+
+	for (Terrain_Index ter = 0; ter < m_terrain_edge_freq.size(); ++ter) {
+		assert(indexs[ter] == 3 * (m_terrain_edge_freq_cum[ter] + m_terrain_edge_freq[ter]));
+	}
+}
+
+void GameRendererGL::draw_terrain_dither()
+{
+	Map const & map = m_egbase->map();
+	World const & world = map.world();
+
+	if (m_edge_vertices_size == 0)
+		return;
+
+	glVertexPointer(2, GL_FLOAT, sizeof(dithervertex), &m_edge_vertices[0].x);
+	glTexCoordPointer(2, GL_FLOAT, sizeof(dithervertex), &m_edge_vertices[0].tcx);
+	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(dithervertex), &m_edge_vertices[0].color);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	glEnableClientState(GL_COLOR_ARRAY);
+
+	glActiveTextureARB(GL_TEXTURE1_ARB);
+	glClientActiveTextureARB(GL_TEXTURE1_ARB);
+	glTexCoordPointer(2, GL_FLOAT, sizeof(dithervertex), &m_edge_vertices[0].edgex);
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	GLuint edge = dynamic_cast<GLSurfaceTexture const &>
+		(*g_gr->get_edge_texture()).get_gl_texture();
+	glBindTexture(GL_TEXTURE_2D, edge);
+	glEnable(GL_TEXTURE_2D);
+	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
+	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+	glActiveTextureARB(GL_TEXTURE0_ARB);
+	glClientActiveTextureARB(GL_TEXTURE0_ARB);
+
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+
+	for (Terrain_Index ter = 0; ter < m_terrain_freq.size(); ++ter) {
+		if (!m_terrain_edge_freq[ter])
+			continue;
+
+		const Texture & texture =
+				*g_gr->get_maptexture_data
+					(world.terrain_descr(ter).get_texture());
+		glBindTexture(GL_TEXTURE_2D, texture.getTexture());
+		glDrawArrays
+			(GL_TRIANGLES,
+			 3 * m_terrain_edge_freq_cum[ter], 3 * m_terrain_edge_freq[ter]);
+	}
+
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glDisableClientState(GL_COLOR_ARRAY);
+	glActiveTextureARB(GL_TEXTURE1_ARB);
+	glClientActiveTextureARB(GL_TEXTURE1_ARB);
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glDisable(GL_TEXTURE_2D);
+	glActiveTextureARB(GL_TEXTURE0_ARB);
+	glClientActiveTextureARB(GL_TEXTURE0_ARB);
+}
+
+uint8_t GameRendererGL::field_roads(const FCoords & coords) const
+{
+	if (m_player) {
+		const Map & map = m_egbase->map();
+		const Player::Field & pf = m_player->fields()[Map::get_index(coords, map.get_width())];
+		return pf.roads | map.get_overlay_manager().get_road_overlay(coords);
+	} else {
+		return coords.field->get_roads();
+	}
+}
+
+void GameRendererGL::prepare_roads()
+{
+	const Map & map = m_egbase->map();
+
+	m_road_freq[0] = 0;
+	m_road_freq[1] = 0;
+
+	for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
+		for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
+			Coords ncoords(fx, fy);
+			map.normalize_coords(ncoords);
+			FCoords fcoords = map.get_fcoords(ncoords);
+			uint8_t roads = field_roads(fcoords);
+
+			for (int dir = 0; dir < 3; ++dir) {
+				uint8_t road = (roads >> (2 * dir)) & Road_Mask;
+				if (road >= Road_Normal && road <= Road_Busy) {
+					++m_road_freq[road - Road_Normal];
+				}
+			}
+		}
+	}
+
+	uint32_t nrquads = m_road_freq[0] + m_road_freq[1];
+	if (4 * nrquads > m_road_vertices_size) {
+		m_road_vertices.reset(new basevertex[4 * nrquads]);
+		m_road_vertices_size = 4 * nrquads;
+	}
+
+	uint32_t indexs[2];
+	indexs[0] = 0;
+	indexs[1] = 4 * m_road_freq[0];
+
+	for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
+		for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
+			Coords ncoords(fx, fy);
+			map.normalize_coords(ncoords);
+			FCoords fcoords = map.get_fcoords(ncoords);
+			uint8_t roads = field_roads(fcoords);
+
+			uint8_t road = (roads >> Road_East) & Road_Mask;
+			if (road >= Road_Normal && road <= Road_Busy) {
+				uint32_t index = indexs[road - Road_Normal];
+				basevertex start, end;
+				compute_basevertex(Coords(fx, fy), start);
+				compute_basevertex(Coords(fx + 1, fy), end);
+				m_road_vertices[index] = start;
+				m_road_vertices[index].y -= 2;
+				m_road_vertices[index].tcy -= 2.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = start;
+				m_road_vertices[index].y += 2;
+				m_road_vertices[index].tcy += 2.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = end;
+				m_road_vertices[index].y += 2;
+				m_road_vertices[index].tcy += 2.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = end;
+				m_road_vertices[index].y -= 2;
+				m_road_vertices[index].tcy -= 2.0 / TEXTURE_HEIGHT;
+				++index;
+				indexs[road - Road_Normal] = index;
+			}
+
+			road = (roads >> Road_SouthEast) & Road_Mask;
+			if (road >= Road_Normal && road <= Road_Busy) {
+				uint32_t index = indexs[road - Road_Normal];
+				basevertex start, end;
+				compute_basevertex(Coords(fx, fy), start);
+				compute_basevertex(Coords(fx + (fy & 1), fy + 1), end);
+				m_road_vertices[index] = start;
+				m_road_vertices[index].x += 3;
+				m_road_vertices[index].tcx += 3.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = start;
+				m_road_vertices[index].x -= 3;
+				m_road_vertices[index].tcx -= 3.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = end;
+				m_road_vertices[index].x -= 3;
+				m_road_vertices[index].tcx -= 3.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = end;
+				m_road_vertices[index].x += 3;
+				m_road_vertices[index].tcx += 3.0 / TEXTURE_HEIGHT;
+				++index;
+				indexs[road - Road_Normal] = index;
+			}
+
+			road = (roads >> Road_SouthWest) & Road_Mask;
+			if (road >= Road_Normal && road <= Road_Busy) {
+				uint32_t index = indexs[road - Road_Normal];
+				basevertex start, end;
+				compute_basevertex(Coords(fx, fy), start);
+				compute_basevertex(Coords(fx + (fy & 1) - 1, fy + 1), end);
+				m_road_vertices[index] = start;
+				m_road_vertices[index].x += 3;
+				m_road_vertices[index].tcx += 3.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = start;
+				m_road_vertices[index].x -= 3;
+				m_road_vertices[index].tcx -= 3.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = end;
+				m_road_vertices[index].x -= 3;
+				m_road_vertices[index].tcx -= 3.0 / TEXTURE_HEIGHT;
+				++index;
+				m_road_vertices[index] = end;
+				m_road_vertices[index].x += 3;
+				m_road_vertices[index].tcx += 3.0 / TEXTURE_HEIGHT;
+				++index;
+				indexs[road - Road_Normal] = index;
+			}
+		}
+	}
+
+	assert(indexs[0] == 4 * m_road_freq[0]);
+	assert(indexs[1] == 4 * nrquads);
+}
+
+void GameRendererGL::draw_roads()
+{
+	if (!m_road_freq[0] && !m_road_freq[1])
+		return;
+
+	GLuint rt_normal =
+		dynamic_cast<GLSurfaceTexture const &>
+		(*g_gr->get_road_texture(Widelands::Road_Normal)).get_gl_texture();
+	GLuint rt_busy =
+		dynamic_cast<GLSurfaceTexture const &>
+		(*g_gr->get_road_texture(Widelands::Road_Busy)).get_gl_texture();
+
+	glVertexPointer(2, GL_FLOAT, sizeof(basevertex), &m_road_vertices[0].x);
+	glTexCoordPointer(2, GL_FLOAT, sizeof(basevertex), &m_road_vertices[0].tcx);
+	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(basevertex), &m_road_vertices[0].color);
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	glEnableClientState(GL_COLOR_ARRAY);
+
+	glDisable(GL_BLEND);
+
+	if (m_road_freq[0]) {
+		glBindTexture(GL_TEXTURE_2D, rt_normal);
+		glDrawArrays(GL_QUADS, 0, 4 * m_road_freq[0]);
+	}
+
+	if (m_road_freq[1]) {
+		glBindTexture(GL_TEXTURE_2D, rt_busy);
+		glDrawArrays(GL_QUADS, 4 * m_road_freq[0], 4 * m_road_freq[1]);
+	}
+
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+	glDisableClientState(GL_COLOR_ARRAY);
+}
+
+#endif // USE_OPENGL

=== added file 'src/graphic/render/gamerenderer_gl.h'
--- src/graphic/render/gamerenderer_gl.h	1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer_gl.h	2013-02-07 18:50:33 +0000
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2011-2013 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifdef USE_OPENGL
+#ifndef WIDELANDS_GAMERENDERER_GL_H
+#define WIDELANDS_GAMERENDERER_GL_H
+
+#include "gamerenderer.h"
+
+#include "rect.h"
+
+#include <vector>
+#include <boost/scoped_array.hpp>
+
+namespace Widelands {
+struct Coords;
+struct FCoords;
+}
+
+class GLSurface;
+
+/**
+ * OpenGL implementation of @ref GameRenderer.
+ */
+struct GameRendererGL : GameRenderer {
+	GameRendererGL();
+	virtual ~GameRendererGL();
+
+private:
+	struct basevertex {
+		float x;
+		float y;
+		float tcx;
+		float tcy;
+		uint8_t color[4];
+		uint32_t pad[3];
+	};
+
+	struct dithervertex {
+		float x;
+		float y;
+		float tcx;
+		float tcy;
+		float edgex;
+		float edgey;
+		uint8_t color[4];
+		uint32_t pad[1];
+	};
+
+	void draw();
+	void prepare_terrain_base();
+	void draw_terrain_base();
+	void prepare_terrain_dither();
+	void draw_terrain_dither();
+	void prepare_roads();
+	void draw_roads();
+
+	uint32_t patch_index(int32_t fx, int32_t fy) const;
+	uint8_t field_brightness(const Widelands::FCoords & coords) const;
+	uint8_t field_roads(const Widelands::FCoords & coords) const;
+	template<typename vertex>
+	void compute_basevertex(const Widelands::Coords & coords, vertex & vtx) const;
+
+	/**
+	 * The following variables are only valid during rendering.
+	 */
+	/*@{*/
+	GLSurface * m_surface;
+
+	/// Bounding rectangle inside the destination surface
+	Rect m_rect;
+
+	/// Translation from map pixel coordinates to surface pixel coordinates
+	/// (relative to the top-left corner of the surface, @b not relative
+	/// to the bounding rectangle)
+	Point m_surface_offset;
+
+	Rect m_patch_size;
+	boost::scoped_array<basevertex> m_patch_vertices;
+	uint32_t m_patch_vertices_size;
+	boost::scoped_array<uint16_t> m_patch_indices;
+	uint32_t m_patch_indices_size;
+	std::vector<uint32_t> m_terrain_freq;
+	std::vector<uint32_t> m_terrain_freq_cum;
+	boost::scoped_array<dithervertex> m_edge_vertices;
+	uint32_t m_edge_vertices_size;
+	std::vector<uint32_t> m_terrain_edge_freq;
+	std::vector<uint32_t> m_terrain_edge_freq_cum;
+
+	uint32_t m_road_freq[2];
+	boost::scoped_array<basevertex> m_road_vertices;
+	uint32_t m_road_vertices_size;
+	/*@}*/
+};
+
+#endif // WIDELANDS_GAMERENDERER_GL_H
+#endif // USE_OPENGL

=== added file 'src/graphic/render/gamerenderer_sdl.cc'
--- src/graphic/render/gamerenderer_sdl.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer_sdl.cc	2013-02-07 18:50:33 +0000
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2010-2013 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include "gamerenderer_sdl.h"
+
+#include "logic/field.h"
+#include "logic/map.h"
+#include "logic/player.h"
+
+#include "graphic/rendertarget.h"
+
+#include "wui/overlay_manager.h"
+
+#include "terrain_sdl.h"
+
+
+using namespace Widelands;
+
+///This is used by rendermap to calculate the brightness of the terrain.
+inline static Sint8 node_brightness
+	(Widelands::Time   const gametime,
+	 Widelands::Time   const last_seen,
+	 Widelands::Vision const vision,
+	 int8_t                  result)
+{
+	if      (vision == 0)
+		result = -128;
+	else if (vision == 1) {
+		assert(last_seen <= gametime);
+		Widelands::Duration const time_ago = gametime - last_seen;
+		result =
+			static_cast<Sint16>
+			(((static_cast<Sint16>(result) + 128) >> 1)
+			 *
+			 (1.0 + (time_ago < 45000 ? expf(-8.46126929e-5 * time_ago) : 0)))
+			-
+			128;
+	}
+
+	return result;
+}
+
+
+void GameRendererSDL::draw()
+{
+	draw_terrain();
+	draw_objects();
+}
+
+void GameRendererSDL::draw_terrain()
+{
+	if (m_player && !m_player->see_all())
+		m_dst->get_surface()->fill_rect(m_dst->get_rect(), RGBAColor(0, 0, 0, 255));
+
+	Map const & map = m_egbase->map();
+	World const & world = map.world();
+	uint32_t const mapwidth = map.get_width();
+
+#define get_terrain_texture(ter) \
+	(g_gr->get_maptexture_data(world.terrain_descr((ter)).get_texture()))
+
+	int32_t dx              = m_maxfx - m_minfx + 1;
+	int32_t dy              = m_maxfy - m_minfy + 1;
+	int32_t linear_fy       = m_minfy;
+	int32_t b_posy          = linear_fy * TRIANGLE_HEIGHT + m_dst_offset.y;
+
+	Widelands::Time const gametime = m_egbase->get_gametime();
+
+	while (dy--) {
+		const int32_t posy = b_posy;
+		b_posy += TRIANGLE_HEIGHT;
+		const int32_t linear_fx = m_minfx;
+		FCoords r(Coords(linear_fx, linear_fy));
+		FCoords br(Coords(linear_fx + (linear_fy & 1) - 1, linear_fy + 1));
+		int32_t r_posx =
+			r.x * TRIANGLE_WIDTH
+			+
+			(linear_fy & 1) * (TRIANGLE_WIDTH / 2)
+			+
+			m_dst_offset.x;
+		int32_t br_posx = r_posx - TRIANGLE_WIDTH / 2;
+
+		// Calculate safe (bounded) field coordinates and get field pointers
+		map.normalize_coords(r);
+		map.normalize_coords(br);
+		Map_Index  r_index = Map::get_index (r, mapwidth);
+		r.field = &map[r_index];
+		Map_Index br_index = Map::get_index(br, mapwidth);
+		br.field = &map[br_index];
+		FCoords tr;
+		map.get_tln(r, &tr);
+		Map_Index tr_index = tr.field - &map[0];
+
+		const Texture * f_r_texture;
+
+		if (m_player && !m_player->see_all()) {
+			const Player::Field & l_pf = m_player->fields()[Map::get_index(map.l_n(r), mapwidth)];
+			f_r_texture = get_terrain_texture(l_pf.terrains.r);
+		} else {
+			f_r_texture = get_terrain_texture(map.l_n(r).field->get_terrains().r);
+		}
+
+		uint32_t count = dx;
+
+		while (count--) {
+			const FCoords bl = br;
+			const FCoords f = r;
+			const int32_t f_posx = r_posx;
+			const int32_t bl_posx = br_posx;
+			Map_Index f_index = r_index;
+			Map_Index bl_index = br_index;
+			move_r(mapwidth, tr, tr_index);
+			move_r(mapwidth,  r,  r_index);
+			move_r(mapwidth, br, br_index);
+			r_posx  += TRIANGLE_WIDTH;
+			br_posx += TRIANGLE_WIDTH;
+
+			const Texture * l_r_texture = f_r_texture;
+			const Texture * f_d_texture;
+			const Texture * tr_d_texture;
+			uint8_t roads;
+			Sint8 f_brightness;
+			Sint8 r_brightness;
+			Sint8 bl_brightness;
+			Sint8 br_brightness;
+
+			if (m_player && !m_player->see_all()) {
+				const Player::Field & f_pf = m_player->fields()[f_index];
+				const Player::Field & r_pf = m_player->fields()[r_index];
+				const Player::Field & bl_pf = m_player->fields()[bl_index];
+				const Player::Field & br_pf = m_player->fields()[br_index];
+				const Player::Field & tr_pf = m_player->fields()[tr_index];
+
+				f_r_texture = get_terrain_texture(f_pf.terrains.r);
+				f_d_texture = get_terrain_texture(f_pf.terrains.d);
+				tr_d_texture = get_terrain_texture(tr_pf.terrains.d);
+
+				roads = f_pf.roads | map.overlay_manager().get_road_overlay(f);
+
+				f_brightness = node_brightness
+				 	(gametime, f_pf.time_node_last_unseen,
+				 	 f_pf.vision, f.field->get_brightness());
+				r_brightness = node_brightness
+				 	(gametime, r_pf.time_node_last_unseen,
+				 	 r_pf.vision, r.field->get_brightness());
+				bl_brightness = node_brightness
+				 	(gametime, bl_pf.time_node_last_unseen,
+				 	 bl_pf.vision, bl.field->get_brightness());
+				br_brightness = node_brightness
+				 	(gametime, br_pf.time_node_last_unseen,
+				 	 br_pf.vision, br.field->get_brightness());
+			} else {
+				f_r_texture = get_terrain_texture(f.field->get_terrains().r);
+				f_d_texture = get_terrain_texture(f.field->get_terrains().d);
+				tr_d_texture = get_terrain_texture(tr.field->get_terrains().d);
+
+				roads = f.field->get_roads();
+
+				f_brightness = f.field->get_brightness();
+				r_brightness = r.field->get_brightness();
+				bl_brightness = bl.field->get_brightness();
+				br_brightness = br.field->get_brightness();
+			}
+
+			Vertex f_vert
+				(f_posx, posy - f.field->get_height() * HEIGHT_FACTOR,
+				 f_brightness, 0, 0);
+			Vertex r_vert
+				(r_posx, posy - r.field->get_height() * HEIGHT_FACTOR,
+				 r_brightness, TRIANGLE_WIDTH, 0);
+			Vertex bl_vert
+				(bl_posx, b_posy - bl.field->get_height() * HEIGHT_FACTOR,
+				 bl_brightness, 0, 64);
+			Vertex br_vert
+				(br_posx, b_posy - br.field->get_height() * HEIGHT_FACTOR,
+				 br_brightness, TRIANGLE_WIDTH, 64);
+
+			if (linear_fy & 1) {
+				f_vert.tx += TRIANGLE_WIDTH / 2;
+				r_vert.tx += TRIANGLE_WIDTH / 2;
+			} else {
+				f_vert.tx += TRIANGLE_WIDTH;
+				r_vert.tx += TRIANGLE_WIDTH;
+				bl_vert.tx += TRIANGLE_WIDTH / 2;
+				br_vert.tx += TRIANGLE_WIDTH / 2;
+			}
+
+			draw_field //  Render ground
+				(*m_dst,
+				 f_vert, r_vert, bl_vert, br_vert,
+				 roads,
+				 *tr_d_texture, *l_r_texture, *f_d_texture, *f_r_texture);
+		}
+
+		++linear_fy;
+	}
+
+#undef get_terrain_texture
+}
+
+
+/**
+ * Draw ground textures and roads for the given parallelogram (two triangles)
+ * into the bitmap.
+ *
+ * Vertices:
+ *   - f_vert vertex of the field
+ *   - r_vert vertex right of the field
+ *   - bl_vert vertex bottom left of the field
+ *   - br_vert vertex bottom right of the field
+ *
+ * Textures:
+ *   - f_r_texture Terrain of the triangle right of the field
+ *   - f_d_texture Terrain of the triangle under of the field
+ *   - tr_d_texture Terrain of the triangle top of the right triangle ??
+ *   - l_r_texture Terrain of the triangle left of the down triangle ??
+ *
+ *             (tr_d)
+ *
+ *       (f) *------* (r)
+ *          / \  r /
+ *  (l_r)  /   \  /
+ *        /  d  \/
+ *  (bl) *------* (br)
+ */
+void GameRendererSDL::draw_field
+	(RenderTarget & dst,
+	 Vertex  const &  f_vert,
+	 Vertex  const &  r_vert,
+	 Vertex  const & bl_vert,
+	 Vertex  const & br_vert,
+	 uint8_t         roads,
+	 Texture const & tr_d_texture,
+	 Texture const &  l_r_texture,
+	 Texture const &  f_d_texture,
+	 Texture const &  f_r_texture)
+{
+	upcast(SDLSurface, sdlsurf, dst.get_surface());
+	if (sdlsurf)
+	{
+		sdlsurf->set_subwin(dst.get_rect());
+		switch (sdlsurf->format().BytesPerPixel) {
+		case 2:
+			draw_field_int<Uint16>
+				(*sdlsurf,
+				 f_vert, r_vert, bl_vert, br_vert,
+				 roads,
+				 tr_d_texture, l_r_texture, f_d_texture, f_r_texture);
+			break;
+		case 4:
+			draw_field_int<Uint32>
+				(*sdlsurf,
+				 f_vert, r_vert, bl_vert, br_vert,
+				 roads,
+				 tr_d_texture, l_r_texture, f_d_texture, f_r_texture);
+			break;
+		default:
+			assert(false);
+			break;
+		}
+		sdlsurf->unset_subwin();
+	}
+}

=== added file 'src/graphic/render/gamerenderer_sdl.h'
--- src/graphic/render/gamerenderer_sdl.h	1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer_sdl.h	2013-02-07 18:50:33 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010-2013 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef WIDELANDS_GAMERENDERER_SDL_H
+#define WIDELANDS_GAMERENDERER_SDL_H
+
+#include "gamerenderer.h"
+
+struct Texture;
+struct Vertex;
+
+/**
+ * Software-rendering implementation of @ref GameRenderer.
+ */
+struct GameRendererSDL : GameRenderer {
+	void draw();
+
+private:
+	void draw_terrain();
+
+	/**
+	 * Helper function to draw two terrain triangles. This is called from the
+	 * rendermap() functions.
+	 */
+	void draw_field
+		(RenderTarget & dst,
+		 Vertex  const &  f_vert,
+		 Vertex  const &  r_vert,
+		 Vertex  const & bl_vert,
+		 Vertex  const & br_vert,
+		 uint8_t         roads,
+		 Texture const & tr_d_texture,
+		 Texture const &  l_r_texture,
+		 Texture const &  f_d_texture,
+		 Texture const &  f_r_texture);
+};
+
+#endif // WIDELANDS_GAMERENDERER_SDL_H

=== removed file 'src/graphic/render/gameview_opengl.cc'
--- src/graphic/render/gameview_opengl.cc	2012-09-21 21:36:07 +0000
+++ src/graphic/render/gameview_opengl.cc	1970-01-01 00:00:00 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2011-2012 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifdef USE_OPENGL
-
-#include "gameview_opengl.h"
-
-#include "constants.h"
-#include "economy/road.h"
-#include "graphic/graphic.h"
-#include "graphic/texture.h"
-
-#include "terrain_opengl.h"
-
-using namespace  Widelands;
-
-/**
- * Draw ground textures and roads for the given parallelogram (two triangles)
- * into the bitmap.
- *
- * Vertices:
- *   - f_vert vertex of the field
- *   - r_vert vertex right of the field
- *   - bl_vert vertex bottom left of the field
- *   - br_vert vertex bottom right of the field
- *
- * Textures:
- *   - f_r_texture Terrain of the triangle right of the field
- *   - f_d_texture Terrain of the triangle under of the field
- *   - tr_d_texture Terrain of the triangle top of the right triangle ??
- *   - l_r_texture Terrain of the triangle left of the down triangle ??
- *
- *             (tr_d)
- *
- *       (f) *------* (r)
- *          / \  r /
- *  (l_r)  /   \  /
- *        /  d  \/
- *  (bl) *------* (br)
- */
-void GameViewOpenGL::draw_field
-	(Rect          & subwin,
-	 Vertex  const &  f_vert,
-	 Vertex  const &  r_vert,
-	 Vertex  const & bl_vert,
-	 Vertex  const & br_vert,
-	 uint8_t         roads,
-	 Texture const & tr_d_texture,
-	 Texture const &  l_r_texture,
-	 Texture const &  f_d_texture,
-	 Texture const &  f_r_texture)
-{
-	// Draw triangle right (bottom) of the field
-	draw_field_opengl
-		(subwin, f_vert, br_vert, r_vert, f_r_texture, f_d_texture, tr_d_texture);
-	// Draw triangle bottom of the field
-	draw_field_opengl
-		(subwin, f_vert, bl_vert, br_vert, f_d_texture, l_r_texture, f_d_texture);
-
-	// Draw the roads
-	draw_roads_opengl(subwin, roads, f_vert, r_vert, bl_vert, br_vert);
-}
-
-void GameViewOpenGL::rendermap_init()
-{
-	glMatrixMode(GL_TEXTURE);
-	glLoadIdentity();
-	glScalef
-		(1.0f / static_cast<GLfloat>(TEXTURE_WIDTH),
-		 1.0f / static_cast<GLfloat>(TEXTURE_HEIGHT), 1);
-	glDisable(GL_BLEND);
-
-	// Use scissor test to clip the window. This takes coordinates in screen
-	// coordinates (y goes from bottom to top)
-	glScissor
-		(m_rect.x, g_gr->get_yres() - m_rect.y - m_rect.h,
-		 m_rect.w, m_rect.h);
-	glEnable(GL_SCISSOR_TEST);
-}
-
-void GameViewOpenGL::rendermap_deint()
-{
-	glDisable(GL_SCISSOR_TEST);
-	glMatrixMode(GL_TEXTURE);
-	glLoadIdentity();
-}
-
-#endif

=== removed file 'src/graphic/render/gameview_opengl.h'
--- src/graphic/render/gameview_opengl.h	2012-09-21 21:36:07 +0000
+++ src/graphic/render/gameview_opengl.h	1970-01-01 00:00:00 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2011 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifdef USE_OPENGL
-#ifndef GAMEVIEW_OPENGL_H_
-#define GAMEVIEW_OPENGL_H_
-
-#include "gameview.h"
-
-class GameViewOpenGL : public GameView
-{
-public:
-	GameViewOpenGL(RenderTarget & rt):
-		GameView(rt) {}
-	~GameViewOpenGL() {}
-
-protected:
-	/**
-	 * Helper function to draw two terrain triangles. This is called from the
-	 * rendermap() functions.
-	 */
-	void draw_field
-		(Rect          & subwin,
-		 Vertex  const &  f_vert,
-		 Vertex  const &  r_vert,
-		 Vertex  const & bl_vert,
-		 Vertex  const & br_vert,
-		 uint8_t         roads,
-		 Texture const & tr_d_texture,
-		 Texture const &  l_r_texture,
-		 Texture const &  f_d_texture,
-		 Texture const &  f_r_texture);
-
-	void rendermap_init();
-	void rendermap_deint();
-};
-
-
-#endif /* GAMEVIEW_OPENGL_H_ */
-#endif /* USE_OPENGL */

=== removed file 'src/graphic/render/gameview_sdl.cc'
--- src/graphic/render/gameview_sdl.cc	2012-12-07 20:25:12 +0000
+++ src/graphic/render/gameview_sdl.cc	1970-01-01 00:00:00 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2011-2012 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include "gameview_sdl.h"
-
-#include "upcast.h"
-
-#include "economy/road.h"
-#include "economy/flag.h"
-
-#include "wui/minimap.h"
-#include "wui/mapviewpixelconstants.h"
-
-#include "logic/field.h"
-#include "logic/map.h"
-#include "logic/player.h"
-
-#include "graphic/graphic.h"
-#include "graphic/rendertarget.h"
-#include "graphic/surface.h"
-#include "graphic/texture.h"
-
-#include "wui/overlay_manager.h"
-
-#include "terrain_sdl.h"
-
-
-/**
- * Draw ground textures and roads for the given parallelogram (two triangles)
- * into the bitmap.
- *
- * Vertices:
- *   - f_vert vertex of the field
- *   - r_vert vertex right of the field
- *   - bl_vert vertex bottom left of the field
- *   - br_vert vertex bottom right of the field
- *
- * Textures:
- *   - f_r_texture Terrain of the triangle right of the field
- *   - f_d_texture Terrain of the triangle under of the field
- *   - tr_d_texture Terrain of the triangle top of the right triangle ??
- *   - l_r_texture Terrain of the triangle left of the down triangle ??
- *
- *             (tr_d)
- *
- *       (f) *------* (r)
- *          / \  r /
- *  (l_r)  /   \  /
- *        /  d  \/
- *  (bl) *------* (br)
- */
-void GameViewSDL::draw_field
-	(Rect          & subwin,
-	 Vertex  const &  f_vert,
-	 Vertex  const &  r_vert,
-	 Vertex  const & bl_vert,
-	 Vertex  const & br_vert,
-	 uint8_t         roads,
-	 Texture const & tr_d_texture,
-	 Texture const &  l_r_texture,
-	 Texture const &  f_d_texture,
-	 Texture const &  f_r_texture)
-{
-	upcast(SDLSurface, sdlsurf, m_surface);
-	if (sdlsurf)
-	{
-		sdlsurf->set_subwin(subwin);
-		switch (sdlsurf->format().BytesPerPixel) {
-		case 2:
-			draw_field_int<Uint16>
-				(*sdlsurf,
-				 f_vert, r_vert, bl_vert, br_vert,
-				 roads,
-				 tr_d_texture, l_r_texture, f_d_texture, f_r_texture);
-			break;
-		case 4:
-			draw_field_int<Uint32>
-				(*sdlsurf,
-				 f_vert, r_vert, bl_vert, br_vert,
-				 roads,
-				 tr_d_texture, l_r_texture, f_d_texture, f_r_texture);
-			break;
-		default:
-			assert(false);
-			break;
-		}
-		sdlsurf->unset_subwin();
-	}
-}

=== removed file 'src/graphic/render/gameview_sdl.h'
--- src/graphic/render/gameview_sdl.h	2012-02-27 20:24:28 +0000
+++ src/graphic/render/gameview_sdl.h	1970-01-01 00:00:00 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2011-2012 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef GAMEVIEW_SDL_H_
-#define GAMEVIEW_SDL_H_
-
-#include "gameview.h"
-
-class GameViewSDL : public GameView
-{
-public:
-	GameViewSDL(RenderTarget & rt):
-		GameView(rt) {}
-	~GameViewSDL() {}
-
-protected:
-	/**
-	 * Helper function to draw two terrain triangles. This is called from the
-	 * rendermap() functions.
-	 */
-	void draw_field
-		(Rect          & subwin,
-		 Vertex  const &  f_vert,
-		 Vertex  const &  r_vert,
-		 Vertex  const & bl_vert,
-		 Vertex  const & br_vert,
-		 uint8_t         roads,
-		 Texture const & tr_d_texture,
-		 Texture const &  l_r_texture,
-		 Texture const &  f_d_texture,
-		 Texture const &  f_r_texture);
-};
-
-#endif /* GAMEVIEW_SDL_H_ */

=== modified file 'src/graphic/render/gl_surface_texture.cc'
--- src/graphic/render/gl_surface_texture.cc	2013-01-04 09:59:13 +0000
+++ src/graphic/render/gl_surface_texture.cc	2013-02-07 18:50:33 +0000
@@ -85,7 +85,7 @@
  *
  * \note Takes ownership of the given surface.
  */
-GLSurfaceTexture::GLSurfaceTexture(SDL_Surface * surface)
+GLSurfaceTexture::GLSurfaceTexture(SDL_Surface * surface, bool intensity)
 {
 	init(surface->w, surface->h);
 
@@ -166,7 +166,7 @@
 	SDL_LockSurface(surface);
 
 	glTexImage2D
-		(GL_TEXTURE_2D, 0, GL_RGBA, m_tex_w, m_tex_h, 0,
+		(GL_TEXTURE_2D, 0, intensity ? GL_INTENSITY : GL_RGBA, m_tex_w, m_tex_h, 0,
 		 pixels_format, GL_UNSIGNED_BYTE, surface->pixels);
 
 	SDL_UnlockSurface(surface);

=== modified file 'src/graphic/render/gl_surface_texture.h'
--- src/graphic/render/gl_surface_texture.h	2012-12-15 18:40:59 +0000
+++ src/graphic/render/gl_surface_texture.h	2013-02-07 18:50:33 +0000
@@ -30,7 +30,7 @@
 	static void Initialize();
 	static void Cleanup();
 
-	GLSurfaceTexture(SDL_Surface * surface);
+	GLSurfaceTexture(SDL_Surface * surface, bool intensity = false);
 	GLSurfaceTexture(int w, int h, bool alpha);
 	virtual ~GLSurfaceTexture();
 

=== renamed file 'src/graphic/render/gameview.cc' => 'src/graphic/render/minimaprenderer.cc'
--- src/graphic/render/gameview.cc	2012-12-14 20:09:35 +0000
+++ src/graphic/render/minimaprenderer.cc	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2012 by the Widelands Development Team
+ * Copyright (C) 2010-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -17,7 +17,7 @@
  *
  */
 
-#include "gameview.h"
+#include "minimaprenderer.h"
 #include "upcast.h"
 
 #include "economy/road.h"
@@ -39,931 +39,7 @@
 
 #include "terrain_sdl.h"
 
-using Widelands::BaseImmovable;
-using Widelands::Coords;
-using Widelands::FCoords;
-using Widelands::Map;
-using Widelands::Map_Object_Descr;
-using Widelands::Player;
-using Widelands::TCoords;
-using namespace  Widelands;
-
-///This is used by rendermap to calculate the brightness of the terrain.
-inline static Sint8 node_brightness
-	(Widelands::Time   const gametime,
-	 Widelands::Time   const last_seen,
-	 Widelands::Vision const vision,
-	 int8_t                  result)
-{
-	if      (vision == 0)
-		result = -128;
-	else if (vision == 1) {
-		assert(last_seen <= gametime);
-		Widelands::Duration const time_ago = gametime - last_seen;
-		result =
-			static_cast<Sint16>
-			(((static_cast<Sint16>(result) + 128) >> 1)
-			 *
-			 (1.0 + (time_ago < 45000 ? expf(-8.46126929e-5 * time_ago) : 0)))
-			-
-			128;
-	}
-
-	return result;
-}
-
-
-#define RENDERMAP_INITIALIZATIONS                                             \
-   viewofs -= m_offset;                                                       \
-                                                                              \
-   Map                   const & map             = egbase.map();              \
-   Widelands::World      const & world           = map.world();               \
-   Overlay_Manager       const & overlay_manager = map.get_overlay_manager(); \
-   uint32_t const                mapwidth        = map.get_width();           \
-   int32_t minfx, minfy;                                                      \
-   int32_t maxfx, maxfy;                                                      \
-                                                                              \
-   /* hack to prevent negative numbers */                                     \
-   minfx = (viewofs.x + (TRIANGLE_WIDTH >> 1)) / TRIANGLE_WIDTH - 1;          \
-                                                                              \
-   minfy = viewofs.y / TRIANGLE_HEIGHT;                                       \
-   maxfx = (viewofs.x + (TRIANGLE_WIDTH >> 1) + m_rect.w) / TRIANGLE_WIDTH;   \
-   maxfy = (viewofs.y + m_rect.h) / TRIANGLE_HEIGHT;                          \
-   maxfx +=  1; /* because of big buildings */                                \
-   maxfy += 10; /* because of heights */                                      \
-                                                                              \
-   int32_t dx              = maxfx - minfx + 1;                               \
-   int32_t dy              = maxfy - minfy + 1;                               \
-   int32_t linear_fy       = minfy;                                           \
-   bool row_is_forward     = linear_fy & 1;                                   \
-   int32_t b_posy          = linear_fy * TRIANGLE_HEIGHT - viewofs.y;         \
-
-
-/**
- * Loop through fields row by row. For each field, draw ground textures, then
- * roads, then immovables, then bobs, then overlay stuff (build icons etc...)
- */
-void GameView::rendermap
-	(Widelands::Editor_Game_Base const &       egbase,
-	 Widelands::Player           const &       player,
-	 Point                                     viewofs)
-{
-	m_surface->fill_rect(m_rect, RGBAColor(0, 0, 0, 255));
-
-	if (player.see_all())
-		return rendermap(egbase, viewofs);
-
-	RENDERMAP_INITIALIZATIONS;
-
-	const Player::Field * const first_player_field = player.fields();
-	Widelands::Time const gametime = egbase.get_gametime();
-
-	rendermap_init();
-
-	while (dy--) {
-		const int32_t posy = b_posy;
-		b_posy += TRIANGLE_HEIGHT;
-		const int32_t linear_fx = minfx;
-		FCoords r(Coords(linear_fx, linear_fy));
-		FCoords br(Coords(linear_fx - not row_is_forward, linear_fy + 1));
-		int32_t r_posx =
-			r.x * TRIANGLE_WIDTH
-			+
-			row_is_forward * (TRIANGLE_WIDTH / 2)
-			-
-			viewofs.x;
-		int32_t br_posx = r_posx - TRIANGLE_WIDTH / 2;
-
-		// Calculate safe (bounded) field coordinates and get field pointers
-		map.normalize_coords(r);
-		map.normalize_coords(br);
-		Widelands::Map_Index  r_index = Map::get_index (r, mapwidth);
-		r.field = &map[r_index];
-		Widelands::Map_Index br_index = Map::get_index(br, mapwidth);
-		br.field = &map[br_index];
-		const Player::Field *  r_player_field = first_player_field +  r_index;
-		const Player::Field * br_player_field = first_player_field + br_index;
-		FCoords tr, f;
-		map.get_tln(r, &tr);
-		map.get_ln(r, &f);
-		Widelands::Map_Index tr_index = tr.field - &map[0];
-		const Texture * f_r_texture =
-			g_gr->get_maptexture_data
-				(world
-				 .terrain_descr(first_player_field[f.field - &map[0]].terrains.r)
-				 .get_texture());
-
-		uint32_t count = dx;
-
-		while (count--) {
-			const FCoords bl = br;
-			const Player::Field &  f_player_field =  *r_player_field;
-			const Player::Field & bl_player_field = *br_player_field;
-			f = r;
-			const int32_t f_posx = r_posx, bl_posx = br_posx;
-			const Texture & l_r_texture = *f_r_texture;
-			move_r(mapwidth, tr, tr_index);
-			move_r(mapwidth,  r,  r_index);
-			move_r(mapwidth, br, br_index);
-			r_player_field  = first_player_field +  r_index;
-			br_player_field = first_player_field + br_index;
-			r_posx  += TRIANGLE_WIDTH;
-			br_posx += TRIANGLE_WIDTH;
-			const Texture & tr_d_texture =
-				*g_gr->get_maptexture_data
-					(world.terrain_descr(first_player_field[tr_index].terrains.d).get_texture());
-			const Texture & f_d_texture =
-				*g_gr->get_maptexture_data(world.terrain_descr(f_player_field.terrains.d).get_texture());
-			f_r_texture =
-				g_gr->get_maptexture_data(world.terrain_descr(f_player_field.terrains.r).get_texture());
-
-			uint8_t const roads =
-				f_player_field.roads | overlay_manager.get_road_overlay(f);
-
-			Vertex f_vert
-				(f_posx, posy - f.field->get_height() * HEIGHT_FACTOR,
-				 node_brightness
-				 	(gametime, f_player_field.time_node_last_unseen,
-				 	 f_player_field.vision, f.field->get_brightness()),
-				 0, 0);
-			Vertex r_vert
-				(r_posx, posy - r.field->get_height() * HEIGHT_FACTOR,
-				 node_brightness
-				 	(gametime, r_player_field->time_node_last_unseen,
-				 	 r_player_field->vision, r.field->get_brightness()),
-				 TRIANGLE_WIDTH, 0);
-			Vertex bl_vert
-				(bl_posx, b_posy - bl.field->get_height() * HEIGHT_FACTOR,
-				 node_brightness
-				 	(gametime, bl_player_field.time_node_last_unseen,
-				 	 bl_player_field.vision, bl.field->get_brightness()),
-				 0, 64);
-			Vertex br_vert
-				(br_posx, b_posy - br.field->get_height() * HEIGHT_FACTOR,
-				 node_brightness
-				 	(gametime, br_player_field->time_node_last_unseen,
-				 	 br_player_field->vision, br.field->get_brightness()),
-				 TRIANGLE_WIDTH, 64);
-
-			if (row_is_forward) {
-				f_vert.tx += TRIANGLE_WIDTH / 2;
-				r_vert.tx += TRIANGLE_WIDTH / 2;
-			} else {
-				f_vert.tx += TRIANGLE_WIDTH;
-				r_vert.tx += TRIANGLE_WIDTH;
-				bl_vert.tx += TRIANGLE_WIDTH / 2;
-				br_vert.tx += TRIANGLE_WIDTH / 2;
-			}
-
-			draw_field //  Render ground
-				(m_rect,
-				 f_vert, r_vert, bl_vert, br_vert,
-				 roads,
-				 tr_d_texture, l_r_texture, f_d_texture, *f_r_texture);
-		}
-
-		++linear_fy;
-		row_is_forward = not row_is_forward;
-	}
-
-	{
-		const int32_t dx2        = maxfx - minfx + 1;
-		int32_t dy2              = maxfy - minfy + 1;
-		int32_t linear_fy2       = minfy;
-		bool row_is_forward2     = linear_fy2 & 1;
-		int32_t b_posy2          = linear_fy2 * TRIANGLE_HEIGHT - viewofs.y - m_offset.y;
-
-		while (dy2--) {
-			const int32_t posy = b_posy2;
-			b_posy2 += TRIANGLE_HEIGHT;
-
-			{ //  Draw things on the node.
-				const int32_t linear_fx = minfx;
-				FCoords r (Coords(linear_fx, linear_fy2));
-				FCoords br(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
-
-				//  Calculate safe (bounded) field coordinates and get field pointers.
-				map.normalize_coords(r);
-				map.normalize_coords(br);
-				Widelands::Map_Index  r_index = Map::get_index (r, mapwidth);
-				r.field = &map[r_index];
-				Widelands::Map_Index br_index = Map::get_index(br, mapwidth);
-				br.field = &map[br_index];
-				FCoords tr, f;
-				map.get_tln(r, &tr);
-				map.get_ln(r, &f);
-				bool r_is_border;
-				uint8_t f_owner_number = f.field->get_owned_by();   //  do not use if f_vision < 1 -> PPOV
-				uint8_t r_owner_number;
-				r_is_border = r.field->is_border();                 //  do not use if f_vision < 1 -> PPOV
-				r_owner_number = r.field->get_owned_by();           //  do not use if f_vision < 1 -> PPOV
-				uint8_t br_owner_number = br.field->get_owned_by(); //  do not use if f_vision < 1 -> PPOV
-				Player::Field const * r_player_field = first_player_field + r_index;
-				const Player::Field * br_player_field = first_player_field + br_index;
-				Widelands::Vision  r_vision =  r_player_field->vision;
-				Widelands::Vision br_vision = br_player_field->vision;
-				Point r_pos
-					(linear_fx * TRIANGLE_WIDTH
-					 +
-					 row_is_forward2 * (TRIANGLE_WIDTH / 2)
-					 -
-					 viewofs.x - m_offset.x,
-					 posy - r.field->get_height() * HEIGHT_FACTOR);
-				Point br_pos
-					(r_pos.x - TRIANGLE_WIDTH / 2,
-					 b_posy2 - br.field->get_height() * HEIGHT_FACTOR);
-
-				int32_t count = dx2;
-
-				while (count--) {
-					f = r;
-					const Player::Field & f_player_field = *r_player_field;
-					move_r(mapwidth, tr);
-					move_r(mapwidth,  r,  r_index);
-					move_r(mapwidth, br, br_index);
-					r_player_field  = first_player_field +  r_index;
-					br_player_field = first_player_field + br_index;
-
-					//  do not use if f_vision < 1 -> PPOV
-					const uint8_t tr_owner_number = tr.field->get_owned_by();
-
-					const bool f_is_border = r_is_border;
-					const uint8_t l_owner_number = f_owner_number;
-					const uint8_t bl_owner_number = br_owner_number;
-					f_owner_number = r_owner_number;
-					r_is_border = r.field->is_border();         //  do not use if f_vision < 1 -> PPOV
-					r_owner_number = r.field->get_owned_by();   //  do not use if f_vision < 1 -> PPOV
-					br_owner_number = br.field->get_owned_by(); //  do not use if f_vision < 1 -> PPOV
-					Widelands::Vision const  f_vision =  r_vision;
-					Widelands::Vision const bl_vision = br_vision;
-					r_vision  = player.vision (r_index);
-					br_vision = player.vision(br_index);
-					const Point f_pos = r_pos, bl_pos = br_pos;
-					r_pos = Point(r_pos.x + TRIANGLE_WIDTH, posy - r.field->get_height() * HEIGHT_FACTOR);
-					br_pos = Point(br_pos.x + TRIANGLE_WIDTH, b_posy2 - br.field->get_height() * HEIGHT_FACTOR);
-
-					if (1 < f_vision) { // Render stuff that belongs to the node.
-						//  Render border markes on and halfway between border nodes.
-						if (f_is_border) {
-							const Player & owner = egbase.player(f_owner_number);
-							uint32_t const anim = owner.frontier_anim();
-							drawanim(f_pos, anim, 0, &owner);
-							if
-								((f_vision | r_vision)
-								 and
-								 r_owner_number == f_owner_number
-								 and
-								 ((tr_owner_number == f_owner_number)
-								 xor
-								 (br_owner_number == f_owner_number)))
-								drawanim(middle(f_pos, r_pos), anim, 0, &owner);
-							if
-								((f_vision | bl_vision)
-								 and
-								 bl_owner_number == f_owner_number
-								 and
-								 ((l_owner_number == f_owner_number)
-								 xor
-								 (br_owner_number == f_owner_number)))
-								drawanim(middle(f_pos, bl_pos), anim, 0, &owner);
-							if
-								((f_vision | br_vision)
-								 and
-								 br_owner_number == f_owner_number
-								 and
-								 ((r_owner_number == f_owner_number)
-								 xor
-								 (bl_owner_number == f_owner_number)))
-								drawanim(middle(f_pos, br_pos), anim, 0, &owner);
-						}
-
-
-						// Render bobs
-						// TODO - rendering order?
-						//  This must be defined somehow. Some bobs have a higher
-						//  priority than others. Maybe this priority is a moving
-						//  versus non-moving bobs thing? draw_ground implies that
-						//  this doesn't render map objects. Are there any overdraw
-						//  issues with the current rendering order?
-
-						// Draw Map_Objects hooked to this field
-						if (BaseImmovable * const imm = f.field->get_immovable())
-							imm->draw(egbase, *this, f, f_pos);
-						for
-							(Widelands::Bob * bob = f.field->get_first_bob();
-							 bob;
-							 bob = bob->get_next_bob())
-							bob->draw(egbase, *this, f_pos);
-
-						//  Render overlays on nodes.
-						Overlay_Manager::Overlay_Info
-							overlay_info[MAX_OVERLAYS_PER_NODE];
-
-						const Overlay_Manager::Overlay_Info * const end =
-							overlay_info
-							+
-							overlay_manager.get_overlays(f, overlay_info);
-
-						for
-							(const Overlay_Manager::Overlay_Info * it = overlay_info;
-							 it < end;
-							 ++it)
-							blit(f_pos - it->hotspot, it->pic);
-					} else if (f_vision == 1) {
-						const Player * owner = f_player_field.owner ? egbase.get_player(f_player_field.owner) : 0;
-						if (owner) {
-							// Draw borders as they stood the last time we saw them
-							uint32_t const anim = owner->frontier_anim();
-							if (f_player_field.border)
-								drawanim(f_pos, anim, 0, owner);
-							if (f_player_field.border_r)
-								drawanim(middle(f_pos,  r_pos), anim, 0, owner);
-							if (f_player_field.border_br)
-								drawanim(middle(f_pos, bl_pos), anim, 0, owner);
-							if (f_player_field.border_bl)
-								drawanim(middle(f_pos, br_pos), anim, 0, owner);
-						}
-						if
-							(const Map_Object_Descr * const map_object_descr =
-							 f_player_field.map_object_descr[TCoords<>::None])
-						{
-							if
-								(const Player::Constructionsite_Information * const csinf =
-								 f_player_field.constructionsite[TCoords<>::None])
-							{
-								// draw the partly finished constructionsite
-								uint32_t anim;
-								try {
-									anim = csinf->becomes->get_animation("build");
-								} catch (Map_Object_Descr::Animation_Nonexistent & e) {
-									try {
-										anim = csinf->becomes->get_animation("unoccupied");
-									} catch (Map_Object_Descr::Animation_Nonexistent) {
-										anim = csinf->becomes->get_animation("idle");
-									}
-								}
-								const AnimationGfx::Index nr_frames = g_gr->nr_frames(anim);
-								uint32_t cur_frame =
-									csinf->totaltime ? csinf->completedtime * nr_frames / csinf->totaltime : 0;
-								uint32_t tanim = cur_frame * FRAME_LENGTH;
-								uint32_t w, h;
-								g_gr->get_animation_size(anim, tanim, w, h);
-								uint32_t lines = h * csinf->completedtime * nr_frames;
-								if (csinf->totaltime)
-									lines /= csinf->totaltime;
-								assert(h * cur_frame <= lines);
-								lines -= h * cur_frame; //  This won't work if pictures have various sizes.
-
-								if (cur_frame) // not the first frame
-									// draw the prev frame from top to where next image will be drawing
-									drawanimrect
-										(f_pos, anim, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
-								else if (csinf->was) {
-									// Is the first frame, but there was another building here before,
-									// get its last build picture and draw it instead.
-									uint32_t a;
-									try {
-										a = csinf->was->get_animation("unoccupied");
-									} catch (Map_Object_Descr::Animation_Nonexistent & e) {
-										a = csinf->was->get_animation("idle");
-									}
-									drawanimrect
-										(f_pos, a, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
-								}
-								assert(lines <= h);
-								drawanimrect(f_pos, anim, tanim, owner, Rect(Point(0, h - lines), w, lines));
-							} else if (upcast(const Building_Descr, building, map_object_descr)) {
-								// this is a building therefore we either draw unoccupied or idle animation
-								uint32_t pic;
-								try {
-									pic = building->get_animation("unoccupied");
-								} catch (Map_Object_Descr::Animation_Nonexistent & e) {
-									pic = building->get_animation("idle");
-								}
-								drawanim(f_pos, pic, 0, owner);
-							} else if (const uint32_t pic = map_object_descr->main_animation()) {
-								drawanim(f_pos, pic, 0, owner);
-							} else if (map_object_descr == &Widelands::g_flag_descr) {
-								drawanim(f_pos, owner->flag_anim(), 0, owner);
-							}
-						}
-					}
-				}
-			}
-
-			if (false) { //  Draw things on the R-triangle (nothing to draw yet).
-				const int32_t linear_fx = minfx;
-				FCoords r(Coords(linear_fx, linear_fy2));
-				FCoords b(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
-				int32_t posx =
-					(linear_fx - 1) * TRIANGLE_WIDTH
-					+
-					(row_is_forward2 + 1) * (TRIANGLE_WIDTH / 2)
-					-
-					viewofs.x;
-
-				//  Calculate safe (bounded) field coordinates.
-				map.normalize_coords(r);
-				map.normalize_coords(b);
-
-				//  Get field pointers.
-				r.field = &map[Map::get_index(r, mapwidth)];
-				b.field = &map[Map::get_index(b, mapwidth)];
-
-				int32_t count = dx2;
-
-				//  One less iteration than for nodes and D-triangles.
-				while (--count) {
-					const FCoords f = r;
-					map.get_rn(r, &r);
-					map.get_rn(b, &b);
-					posx += TRIANGLE_WIDTH;
-
-					//  FIXME Implement visibility rules for objects on triangles
-					//  FIXME when they are used in the game. The only things that
-					//  FIXME are drawn on triangles now (except the ground) are
-					//  FIXME overlays for the editor terrain tool, and the editor
-					//  FIXME does not need visibility rules.
-					{ //  FIXME Visibility check here.
-						Overlay_Manager::Overlay_Info overlay_info
-							[MAX_OVERLAYS_PER_TRIANGLE];
-						const Overlay_Manager::Overlay_Info & overlay_info_end = *
-							(overlay_info
-							 +
-							 overlay_manager.get_overlays
-							 	(TCoords<>(f, TCoords<>::R), overlay_info));
-
-						for
-							(const Overlay_Manager::Overlay_Info * it = overlay_info;
-							 it < &overlay_info_end;
-							 ++it)
-							blit
-								(Point
-								 	(posx,
-								 	 posy
-								 	 +
-								 	 (TRIANGLE_HEIGHT
-								 	  -
-								 	  (f.field->get_height()
-								 	   +
-								 	   r.field->get_height()
-								 	   +
-								 	   b.field->get_height())
-								 	  *
-								 	  HEIGHT_FACTOR)
-								 	 /
-								 	 3)
-								 -
-								 it->hotspot,
-								 it->pic);
-					}
-				}
-			}
-
-			if (false) { //  Draw things on the D-triangle (nothing to draw yet).
-				const int32_t linear_fx = minfx;
-				FCoords f(Coords(linear_fx - 1, linear_fy2));
-				FCoords br
-					(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
-				int32_t posx =
-					(linear_fx - 1) * TRIANGLE_WIDTH
-					+
-					row_is_forward2 * (TRIANGLE_WIDTH / 2)
-					-
-					viewofs.x;
-
-				//  Calculate safe (bounded) field coordinates.
-				map.normalize_coords(f);
-				map.normalize_coords(br);
-
-				//  Get field pointers.
-				f.field  = &map[Map::get_index(f,  mapwidth)];
-				br.field = &map[Map::get_index(br, mapwidth)];
-
-				int32_t count = dx2;
-
-				while (count--) {
-					const FCoords bl = br;
-					map.get_rn(f, &f);
-					map.get_rn(br, &br);
-					posx += TRIANGLE_WIDTH;
-
-					{ //  FIXME Visibility check here.
-						Overlay_Manager::Overlay_Info overlay_info
-							[MAX_OVERLAYS_PER_TRIANGLE];
-						Overlay_Manager::Overlay_Info const * const overlay_info_end
-							=
-							overlay_info
-							+
-							overlay_manager.get_overlays
-								(TCoords<>(f, TCoords<>::D), overlay_info);
-
-						for
-							(const Overlay_Manager::Overlay_Info * it = overlay_info;
-							 it < overlay_info_end;
-							 ++it)
-							blit
-								(Point
-								 	(posx,
-								 	 posy
-								 	 +
-								 	 ((TRIANGLE_HEIGHT * 2)
-								 	  -
-								 	  (f.field->get_height()
-								 	   +
-								 	   bl.field->get_height()
-								 	   +
-								 	   br.field->get_height())
-								 	  *
-								 	  HEIGHT_FACTOR)
-								 	 /
-								 	 3)
-								 -
-								 it->hotspot,
-								 it->pic);
-					}
-				}
-			}
-
-			++linear_fy2;
-			row_is_forward2 = not row_is_forward2;
-		}
-	}
-
-	rendermap_deint();
-
-	g_gr->reset_texture_animation_reminder();
-}
-
-void GameView::rendermap
-	(Widelands::Editor_Game_Base const &       egbase,
-	 Point                                     viewofs)
-{
-	RENDERMAP_INITIALIZATIONS;
-
-	rendermap_init();
-
-	while (dy--) {
-		const int32_t posy = b_posy;
-		b_posy += TRIANGLE_HEIGHT;
-		const int32_t linear_fx = minfx;
-		FCoords r(Coords(linear_fx, linear_fy));
-		FCoords br(Coords(linear_fx - not row_is_forward, linear_fy + 1));
-		int32_t r_posx =
-			r.x * TRIANGLE_WIDTH
-			+
-			row_is_forward * (TRIANGLE_WIDTH / 2)
-			-
-			viewofs.x;
-		int32_t br_posx = r_posx - TRIANGLE_WIDTH / 2;
-
-		// Calculate safe (bounded) field coordinates and get field pointers
-		map.normalize_coords(r);
-		map.normalize_coords(br);
-		Widelands::Map_Index  r_index = Map::get_index (r, mapwidth);
-		r.field = &map[r_index];
-		Widelands::Map_Index br_index = Map::get_index(br, mapwidth);
-		br.field = &map[br_index];
-		FCoords tr, f;
-		map.get_tln(r, &tr);
-		map.get_ln(r, &f);
-		const Texture * f_r_texture =
-			g_gr->get_maptexture_data
-				(world.terrain_descr(f.field->terrain_r()).get_texture());
-
-		uint32_t count = dx;
-
-		while (count--) {
-			const FCoords bl = br;
-			f = r;
-			const int32_t f_posx = r_posx, bl_posx = br_posx;
-			const Texture & l_r_texture = *f_r_texture;
-			move_r(mapwidth, tr);
-			move_r(mapwidth,  r,  r_index);
-			move_r(mapwidth, br, br_index);
-			r_posx  += TRIANGLE_WIDTH;
-			br_posx += TRIANGLE_WIDTH;
-			const Texture & tr_d_texture =
-				*g_gr->get_maptexture_data
-					(world.terrain_descr(tr.field->terrain_d()).get_texture());
-			const Texture & f_d_texture =
-				*g_gr->get_maptexture_data
-					(world.terrain_descr(f.field->terrain_d()).get_texture());
-			f_r_texture =
-				g_gr->get_maptexture_data
-					(world.terrain_descr(f.field->terrain_r()).get_texture());
-
-			const uint8_t roads =
-				f.field->get_roads() | overlay_manager.get_road_overlay(f);
-
-			Vertex f_vert
-				(f_posx, posy - f.field->get_height() * HEIGHT_FACTOR,
-				 f.field->get_brightness(),
-				 0, 0);
-			Vertex r_vert
-				(r_posx, posy - r.field->get_height() * HEIGHT_FACTOR,
-				 r.field->get_brightness(),
-				 TRIANGLE_WIDTH, 0);
-			Vertex bl_vert
-				(bl_posx, b_posy - bl.field->get_height() * HEIGHT_FACTOR,
-				 bl.field->get_brightness(),
-				 0, 64);
-			Vertex br_vert
-				(br_posx, b_posy - br.field->get_height() * HEIGHT_FACTOR,
-				 br.field->get_brightness(),
-				 TRIANGLE_WIDTH, 64);
-
-			if (row_is_forward) {
-				f_vert.tx += TRIANGLE_WIDTH / 2;
-				r_vert.tx += TRIANGLE_WIDTH / 2;
-			} else {
-				bl_vert.tx -= TRIANGLE_WIDTH / 2;
-				br_vert.tx -= TRIANGLE_WIDTH / 2;
-			}
-
-			draw_field //  Render ground
-				(m_rect,
-				 f_vert, r_vert, bl_vert, br_vert,
-				 roads,
-				 tr_d_texture, l_r_texture, f_d_texture, *f_r_texture);
-		}
-
-		++linear_fy;
-		row_is_forward = not row_is_forward;
-	}
-
-	{
-		const int32_t dx2 = maxfx - minfx + 1;
-		int32_t dy2 = maxfy - minfy + 1;
-		int32_t linear_fy2 = minfy;
-		bool row_is_forward2 = linear_fy2 & 1;
-		int32_t b_posy2 = linear_fy2 * TRIANGLE_HEIGHT - viewofs.y;
-
-		while (dy2--) {
-			const int32_t posy = b_posy2;
-			b_posy2 += TRIANGLE_HEIGHT;
-
-			{ //  Draw things on the node.
-				const int32_t linear_fx = minfx;
-				FCoords r(Coords(linear_fx, linear_fy2));
-				FCoords br
-					(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
-
-				//  Calculate safe (bounded) field coordinates and get field
-				//  pointers.
-				map.normalize_coords(r);
-				map.normalize_coords(br);
-				Widelands::Map_Index  r_index = Map::get_index (r, mapwidth);
-				r.field = &map[r_index];
-				Widelands::Map_Index br_index = Map::get_index(br, mapwidth);
-				br.field = &map[br_index];
-				FCoords tr, f;
-				map.get_tln(r, &tr);
-				map.get_ln(r, &f);
-				bool r_is_border;
-				uint8_t f_owner_number = f.field->get_owned_by();
-				uint8_t r_owner_number;
-				r_is_border = r.field->is_border();
-				r_owner_number = r.field->get_owned_by();
-				uint8_t br_owner_number = br.field->get_owned_by();
-				Point r_pos
-					(linear_fx * TRIANGLE_WIDTH
-					 +
-					 row_is_forward2 * (TRIANGLE_WIDTH / 2)
-					 -
-					 viewofs.x,
-					 posy - r.field->get_height() * HEIGHT_FACTOR);
-				Point br_pos
-					(r_pos.x - TRIANGLE_WIDTH / 2,
-					 b_posy2 - br.field->get_height() * HEIGHT_FACTOR);
-
-				int32_t count = dx2;
-
-				while (count--) {
-					f = r;
-					move_r(mapwidth, tr);
-					move_r(mapwidth,  r,  r_index);
-					move_r(mapwidth, br, br_index);
-					const uint8_t tr_owner_number = tr.field->get_owned_by();
-					const bool f_is_border = r_is_border;
-					const uint8_t l_owner_number = f_owner_number;
-					const uint8_t bl_owner_number = br_owner_number;
-					f_owner_number = r_owner_number;
-					r_is_border = r.field->is_border();
-					r_owner_number = r.field->get_owned_by();
-					br_owner_number = br.field->get_owned_by();
-					const Point f_pos = r_pos, bl_pos = br_pos;
-					r_pos = Point
-						(r_pos.x + TRIANGLE_WIDTH,
-						 posy - r.field->get_height() * HEIGHT_FACTOR);
-					br_pos = Point
-						(br_pos.x + TRIANGLE_WIDTH,
-						 b_posy2 - br.field->get_height() * HEIGHT_FACTOR);
-
-					//  Render border markes on and halfway between border nodes.
-					if (f_is_border) {
-						const Player & owner = egbase.player(f_owner_number);
-						uint32_t const anim = owner.frontier_anim();
-						drawanim(f_pos, anim, 0, &owner);
-						if
-							(r_owner_number == f_owner_number
-							 and
-							 ((tr_owner_number == f_owner_number)
-							  xor
-							  (br_owner_number == f_owner_number)))
-							drawanim(middle(f_pos, r_pos), anim, 0, &owner);
-						if
-							(bl_owner_number == f_owner_number
-							 and
-							 ((l_owner_number == f_owner_number)
-							  xor
-							  (br_owner_number == f_owner_number)))
-							drawanim(middle(f_pos, bl_pos), anim, 0, &owner);
-						if
-							(br_owner_number == f_owner_number
-							 and
-							 ((r_owner_number == f_owner_number)
-							  xor
-							  (bl_owner_number == f_owner_number)))
-							drawanim(middle(f_pos, br_pos), anim, 0, &owner);
-					}
-
-					{ // Render stuff that belongs to the node.
-
-						// Render bobs
-						// TODO - rendering order?
-						//  This must be defined somehow. Some bobs have a higher
-						//  priority than others. Maybe this priority is a moving
-						//  versus non-moving bobs thing? draw_ground implies that
-						//  this doesn't render map objects. Are there any overdraw
-						//  issues with the current rendering order?
-
-						// Draw Map_Objects hooked to this field
-						if (BaseImmovable * const imm = f.field->get_immovable())
-							imm->draw(egbase, *this, f, f_pos);
-						for
-							(Widelands::Bob * bob = f.field->get_first_bob();
-							 bob;
-							 bob = bob->get_next_bob())
-							bob->draw(egbase, *this, f_pos);
-
-						//  Render overlays on nodes.
-						Overlay_Manager::Overlay_Info
-							overlay_info[MAX_OVERLAYS_PER_NODE];
-
-						const Overlay_Manager::Overlay_Info * const end =
-							overlay_info
-							+
-							overlay_manager.get_overlays(f, overlay_info);
-
-						for
-							(const Overlay_Manager::Overlay_Info * it = overlay_info;
-							 it < end;
-							 ++it)
-							blit(f_pos - it->hotspot, it->pic);
-					}
-				}
-			}
-
-			{ //  Draw things on the R-triangle.
-				const int32_t linear_fx = minfx;
-				FCoords r(Coords(linear_fx, linear_fy2));
-				FCoords b
-					(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
-				int32_t posx =
-					(linear_fx - 1) * TRIANGLE_WIDTH
-					+
-					(row_is_forward2 + 1) * (TRIANGLE_WIDTH / 2)
-					-
-					viewofs.x;
-
-				//  Calculate safe (bounded) field coordinates.
-				map.normalize_coords(r);
-				map.normalize_coords(b);
-
-				//  Get field pointers.
-				r.field = &map[Map::get_index(r, mapwidth)];
-				b.field = &map[Map::get_index(b, mapwidth)];
-
-				int32_t count = dx2;
-
-				//  One less iteration than for nodes and D-triangles.
-				while (--count) {
-					const FCoords f = r;
-					map.get_rn(r, &r);
-					map.get_rn(b, &b);
-					posx += TRIANGLE_WIDTH;
-
-					{
-						Overlay_Manager::Overlay_Info overlay_info
-							[MAX_OVERLAYS_PER_TRIANGLE];
-						Overlay_Manager::Overlay_Info const & overlay_info_end =
-							*
-							(overlay_info
-							 +
-							 overlay_manager.get_overlays
-							 	(TCoords<>(f, TCoords<>::R), overlay_info));
-
-						for
-							(Overlay_Manager::Overlay_Info const * it = overlay_info;
-							 it < &overlay_info_end;
-							 ++it)
-							blit
-								(Point
-								 	(posx,
-								 	 posy
-								 	 +
-								 	 (TRIANGLE_HEIGHT
-								 	  -
-								 	  (f.field->get_height()
-								 	   +
-								 	   r.field->get_height()
-								 	   +
-								 	   b.field->get_height())
-								 	  *
-								 	  HEIGHT_FACTOR)
-								 	 /
-								 	 3)
-								 -
-								 it->hotspot,
-								 it->pic);
-					}
-				}
-			}
-
-			{ //  Draw things on the D-triangle.
-				const int32_t linear_fx = minfx;
-				FCoords f(Coords(linear_fx - 1, linear_fy2));
-				FCoords br(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
-				int32_t posx =
-					(linear_fx - 1) * TRIANGLE_WIDTH
-					+
-					row_is_forward2 * (TRIANGLE_WIDTH / 2)
-					-
-					viewofs.x;
-
-				//  Calculate safe (bounded) field coordinates.
-				map.normalize_coords(f);
-				map.normalize_coords(br);
-
-				//  Get field pointers.
-				f.field  = &map[Map::get_index(f,  mapwidth)];
-				br.field = &map[Map::get_index(br, mapwidth)];
-
-				int32_t count = dx2;
-
-				while (count--) {
-					const FCoords bl = br;
-					map.get_rn(f, &f);
-					map.get_rn(br, &br);
-					posx += TRIANGLE_WIDTH;
-
-					{
-						Overlay_Manager::Overlay_Info overlay_info
-							[MAX_OVERLAYS_PER_TRIANGLE];
-						const Overlay_Manager::Overlay_Info & overlay_info_end = *
-							(overlay_info
-							 +
-							 overlay_manager.get_overlays
-							 	(TCoords<>(f, TCoords<>::D), overlay_info));
-
-						for
-							(const Overlay_Manager::Overlay_Info * it = overlay_info;
-							 it < &overlay_info_end;
-							 ++it)
-							blit
-								(Point
-								 	(posx,
-								 	 posy
-								 	 +
-								 	 ((TRIANGLE_HEIGHT * 2)
-								 	  -
-								 	  (f.field->get_height()
-								 	   +
-								 	   bl.field->get_height()
-								 	   +
-								 	   br.field->get_height())
-								 	  *
-								 	  HEIGHT_FACTOR)
-								 	 /
-								 	 3)
-								 -
-								 it->hotspot,
-								 it->pic);
-					}
-				}
-			}
-
-			++linear_fy2;
-			row_is_forward2 = not row_is_forward2;
-		}
-	}
-
-	rendermap_deint();
-
-	g_gr->reset_texture_animation_reminder();
-}
-
+using namespace Widelands;
 
 /**
  * Renders a minimap into the current window. The field at viewpoint will be
@@ -973,7 +49,7 @@
  * Calculate the field at the top-left corner of the clipping rect
  * The entire clipping rect will be used for drawing.
  */
-void GameView::renderminimap
+void MiniMapRenderer::renderminimap
 	(Widelands::Editor_Game_Base const &       egbase,
 	 Player                      const * const player,
 	 Point                               const viewpoint,
@@ -986,47 +62,6 @@
 }
 
 
-
-/**
- * Draw ground textures and roads for the given parallelogram (two triangles)
- * into the bitmap.
- *
- * Vertices:
- *   - f_vert vertex of the field
- *   - r_vert vertex right of the field
- *   - bl_vert vertex bottom left of the field
- *   - br_vert vertex bottom right of the field
- *
- * Textures:
- *   - f_r_texture Terrain of the triangle right of the field
- *   - f_d_texture Terrain of the triangle under of the field
- *   - tr_d_texture Terrain of the triangle top of the right triangle ??
- *   - l_r_texture Terrain of the triangle left of the down triangle ??
- *
- *             (tr_d)
- *
- *       (f) *------* (r)
- *          / \  r /
- *  (l_r)  /   \  /
- *        /  d  \/
- *  (bl) *------* (br)
- */
-
-void GameView::draw_field
-	(Rect          & /* subwin */,
-	 Vertex  const &  /* f_vert */,
-	 Vertex  const &  /* r_vert */,
-	 Vertex  const & /* bl_vert */,
-	 Vertex  const & /* br_vert */,
-	 uint8_t         /* roads */,
-	 Texture const & /* tr_d_texture */,
-	 Texture const &  /* l_r_texture */,
-	 Texture const &  /* f_d_texture */,
-	 Texture const &  /* f_r_texture */)
-{
-
-}
-
 /*
  * Blend to colors; only needed for calc_minimap_color below
  */
@@ -1290,7 +325,7 @@
 viewpt is the field at the top left of the rectangle.
 ===============
 */
-void GameView::draw_minimap
+void MiniMapRenderer::draw_minimap
 	(Widelands::Editor_Game_Base const &       egbase,
 	 Widelands::Player           const * const player,
 	 Rect                                const rc,

=== renamed file 'src/graphic/render/gameview.h' => 'src/graphic/render/minimaprenderer.h'
--- src/graphic/render/gameview.h	2012-11-24 16:22:10 +0000
+++ src/graphic/render/minimaprenderer.h	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2012 by the Widelands Development Team
+ * Copyright (C) 2010-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -17,58 +17,25 @@
  *
  */
 
-#ifndef WIDELANDS_GAMEVIEW_H
-#define WIDELANDS_GAMEVIEW_H
+#ifndef WIDELANDS_MINIMAPRENDERER_H
+#define WIDELANDS_MINIMAPRENDERER_H
+
+#include "graphic/rendertarget.h"
 
 namespace Widelands {
 	struct Player;
 	struct Editor_Game_Base;
 };
 
-struct Vertex;
-struct Texture;
-
-#include "graphic/rendertarget.h"
-
 /**
- * This class does the game rendering. The class is initialized from a
- * RenderTarget and can draw views of the game and the minimap. The game
- * can be rendered to the full screen or to a subwindow. This depends on
- * the RenderTarget from which it was initialized.
- *
- * @todo GameView mixes opengl and software rendering. This should be split
- * properly to have different classes for OpenGL and Software rendering.
- * Perhaps creating a GameRenderManager where different rendering classes can
- * be registered so it is easiely possible to create different game rendering?
+ * This class renders the minimap.
  */
-class GameView : public RenderTarget
+class MiniMapRenderer : public RenderTarget
 {
 public:
-	GameView(RenderTarget & rt) :
+	MiniMapRenderer(RenderTarget & rt) :
 		RenderTarget(rt) {}
-	virtual ~GameView() {}
-
-	/**
-	 * Renders the map from a player's point of view into the current drawing
-	 * window.
-	 *
-	 * Will call the function below when player.see_all().
-	 *
-	 * viewofs is the offset of the upper left corner of the window into the map,
-	 * in pixels.
-	 */
-	void rendermap
-		(Widelands::Editor_Game_Base const &       egbase,
-		 Widelands::Player           const &       player,
-		 Point                                     viewofs);
-
-	/**
-	 * Same as above but not from a player's point of view. Used in game when
-	 * rendering for a player that sees all and the editor.
-	 */
-	void rendermap
-		(Widelands::Editor_Game_Base const & egbase,
-		 Point                               viewofs);
+	virtual ~MiniMapRenderer() {}
 
 	/**
 	 * Render the minimap. If player is not 0, it renders from that player's
@@ -81,22 +48,6 @@
 		 uint32_t                            flags);
 
 protected:
-	/**
-	 * Helper function to draw two terrain triangles. This is called from the
-	 * rendermap() functions.
-	 */
-	virtual void draw_field
-		(Rect          & subwin,
-		 Vertex  const &  f_vert,
-		 Vertex  const &  r_vert,
-		 Vertex  const & bl_vert,
-		 Vertex  const & br_vert,
-		 uint8_t         roads,
-		 Texture const & tr_d_texture,
-		 Texture const &  l_r_texture,
-		 Texture const &  f_d_texture,
-		 Texture const &  f_r_texture);
-
 	/// A helper function to draw the minimap. This is called from
 	/// renderminimap().
 	void draw_minimap
@@ -106,16 +57,6 @@
 		 Point                               viewpt,
 		 Point                               framept,
 		 uint32_t                            flags);
-
-	/**
-	 * This is called before the view of the game is rendered.
-	 */
-	virtual void rendermap_init() {}
-
-	/**
-	* This is called after the view of the game is rendered.
-	*/
-	virtual void rendermap_deint() {}
 };
 
-#endif //WIDELANDS_GAMEVIEW_H
+#endif //WIDELANDS_MINIMAPRENDERER_H

=== removed file 'src/graphic/render/terrain_opengl.h'
--- src/graphic/render/terrain_opengl.h	2012-12-07 07:32:24 +0000
+++ src/graphic/render/terrain_opengl.h	1970-01-01 00:00:00 +0000
@@ -1,327 +0,0 @@
-/*
- * Copyright (C) 2010-2012 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- */
-
-#ifdef USE_OPENGL
-#ifndef TERRAIN_OPENGL_H
-#define TERRAIN_OPENGL_H
-
-#include "gl_surface_texture.h"
-#include "vertex.h"
-
-
-void draw_field_opengl
-	(Rect const & subwin,
-	 Vertex const & p1,
-	 Vertex const & p2,
-	 Vertex const & p3,
-	 Texture const & texture,
-	 Texture const & left_texture,
-	 Texture const & top_texture)
-{
-	if (p1.b <= -128 and p2.b <= -128 and p3.b <= -128)
-		return;
-
-	Vertex t1(p1), t2(p2), t3(p3);
-
-	t1.x = p1.x + subwin.x;
-	t1.y = p1.y + subwin.y;
-	t2.x = p2.x + subwin.x;
-	t2.y = p2.y + subwin.y;
-	t3.x = p3.x + subwin.x;
-	t3.y = p3.y + subwin.y;
-
-	if (t1.x < subwin.x and t2.x < subwin.x and t3.x < subwin.x)
-		return;
-	if (t1.y < subwin.y and t2.y < subwin.y and t3.y < subwin.y)
-		return;
-
-	int const subxr = subwin.x + subwin.w;
-	if (t1.x > subxr and t2.x > subxr and t3.x > subxr)
-		return;
-
-	int const subyd = subwin.y + subwin.h;
-	if (t1.y > subyd and t2.y > subyd and t3.y > subyd)
-		return;
-
-	glEnable(GL_BLEND);
-
-	if (g_gr->caps().gl.multitexture) {
-
-		// load current texture
-		glActiveTextureARB(GL_TEXTURE0_ARB);
-		glEnable(GL_TEXTURE_2D);
-		glBindTexture(GL_TEXTURE_2D, texture.getTexture());
-		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-
-		// initialize all texture layers to prevent bug if some layers are skipped
-		for (int i = 1; i < 5; i++) {
-			glActiveTextureARB(GL_TEXTURE0_ARB + i);
-			glEnable(GL_TEXTURE_2D);
-			glBindTexture(GL_TEXTURE_2D, top_texture.getTexture());
-			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
-		}
-
-		if ((&top_texture != &texture) and not (p1.b == -128 and p3.b == -128)) {
-			// load top texture
-			glActiveTextureARB(GL_TEXTURE1_ARB);
-			glEnable(GL_TEXTURE_2D);
-			glBindTexture(GL_TEXTURE_2D, top_texture.getTexture());
-			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
-
-			GLuint edge = dynamic_cast<GLSurfaceTexture const &>
-				(*g_gr->get_edge_texture()).get_gl_texture();
-
-			// combine current and top texture
-			glActiveTextureARB(GL_TEXTURE2_ARB);
-			glEnable(GL_TEXTURE_2D);
-			glBindTexture(GL_TEXTURE_2D, edge);
-			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
-		}
-
-		if ((&left_texture != &texture) and not (p1.b == -128 and p2.b == -128)) {
-			// load left texture
-			glActiveTextureARB(GL_TEXTURE3_ARB);
-			glEnable(GL_TEXTURE_2D);
-			glBindTexture(GL_TEXTURE_2D, left_texture.getTexture());
-			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
-
-			GLuint edge = dynamic_cast<GLSurfaceTexture const &>
-				(*g_gr->get_edge_texture()).get_gl_texture();
-
-			// combine current and left texture
-			glActiveTextureARB(GL_TEXTURE4_ARB);
-			glEnable(GL_TEXTURE_2D);
-			glBindTexture(GL_TEXTURE_2D, edge);
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE3_ARB);
-			glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
-			glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
-		}
-
-		// Fade effect for fog of war
-		glActiveTextureARB(GL_TEXTURE5_ARB);
-		glEnable(GL_TEXTURE_2D);
-		// texture does not matter but one has to be bound
-		glBindTexture(GL_TEXTURE_2D, texture.getTexture());
-		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
-		glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
-		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
-		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
-		glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
-		glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
-
-		glBegin(GL_TRIANGLES); {
-			{
-				GLfloat const brightness = (150.0 + p1.b) / 150.0;
-				glColor3f(brightness, brightness, brightness);
-			}
-			glMultiTexCoord2iARB(GL_TEXTURE0_ARB, t1.tx, t1.ty);
-			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t1.tx / TEXTURE_WIDTH, t1.ty / TEXTURE_WIDTH);
-			glMultiTexCoord2fARB(GL_TEXTURE2_ARB, 0, 0);
-			glMultiTexCoord2fARB(GL_TEXTURE3_ARB, t1.tx / TEXTURE_WIDTH, t1.ty / TEXTURE_WIDTH);
-			glMultiTexCoord2fARB(GL_TEXTURE4_ARB, 1, 0);
-			glMultiTexCoord2fARB(GL_TEXTURE5_ARB, t1.tx / TEXTURE_WIDTH, t1.ty / TEXTURE_WIDTH);
-			glVertex2f(t1.x, t1.y);
-
-			{
-				GLfloat const brightness = (150.0 + p2.b) / 150.0;
-				glColor3f(brightness, brightness, brightness);
-			}
-			glMultiTexCoord2iARB(GL_TEXTURE0_ARB, t2.tx, t2.ty);
-			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t2.tx / TEXTURE_WIDTH, t2.ty / TEXTURE_WIDTH);
-			glMultiTexCoord2fARB(GL_TEXTURE2_ARB, 0.5, 1);
-			glMultiTexCoord2fARB(GL_TEXTURE3_ARB, t2.tx / TEXTURE_WIDTH, t2.ty / TEXTURE_WIDTH);
-			glMultiTexCoord2fARB(GL_TEXTURE4_ARB, 0, 0);
-			glMultiTexCoord2fARB(GL_TEXTURE5_ARB, t2.tx / TEXTURE_WIDTH, t2.ty / TEXTURE_WIDTH);
-			glVertex2f(t2.x, t2.y);
-
-			{
-				GLfloat const brightness = (150.0 + p3.b) / 150.0;
-				glColor3f(brightness, brightness, brightness);
-			}
-			glMultiTexCoord2iARB(GL_TEXTURE0_ARB, t3.tx, t3.ty);
-			glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t3.tx / TEXTURE_WIDTH, t3.ty / TEXTURE_WIDTH);
-			glMultiTexCoord2fARB(GL_TEXTURE2_ARB, 1, 0);
-			glMultiTexCoord2fARB(GL_TEXTURE3_ARB, t3.tx / TEXTURE_WIDTH, t3.ty / TEXTURE_WIDTH);
-			glMultiTexCoord2fARB(GL_TEXTURE4_ARB, 0.5, 1);
-			glMultiTexCoord2fARB(GL_TEXTURE5_ARB, t3.tx / TEXTURE_WIDTH, t3.ty / TEXTURE_WIDTH);
-			glVertex2f(t3.x, t3.y);
-		} glEnd();
-
-		// Cleanup OpenGL
-		glActiveTextureARB(GL_TEXTURE5_ARB);
-		glDisable(GL_TEXTURE_2D);
-		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-		glActiveTextureARB(GL_TEXTURE4_ARB);
-		glDisable(GL_TEXTURE_2D);
-		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-		glActiveTextureARB(GL_TEXTURE3_ARB);
-		glDisable(GL_TEXTURE_2D);
-		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-		glActiveTextureARB(GL_TEXTURE2_ARB);
-		glDisable(GL_TEXTURE_2D);
-		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-		glActiveTextureARB(GL_TEXTURE1_ARB);
-		glDisable(GL_TEXTURE_2D);
-		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-		glActiveTextureARB(GL_TEXTURE0_ARB);
-		glEnable(GL_TEXTURE_2D);
-		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
-	} else {
-		// don't use multitexture
-		glBindTexture(GL_TEXTURE_2D, texture.getTexture());
-		glBegin(GL_TRIANGLES); {
-			{
-				GLfloat const brightness = (150.0 + p1.b) / 150.0;
-				glColor3f(brightness, brightness, brightness);
-			}
-			glTexCoord2i(t1.tx, t1.ty);
-			glVertex2f(t1.x, t1.y);
-
-			{
-				GLfloat const brightness = (150.0 + p2.b) / 150.0;
-				glColor3f(brightness, brightness, brightness);
-			}
-			glTexCoord2i(t2.tx, t2.ty);
-			glVertex2f(t2.x, t2.y);
-
-			{
-				GLfloat const brightness = (150.0 + p3.b) / 150.0;
-				glColor3f(brightness, brightness, brightness);
-			}
-			glTexCoord2i(t3.tx, t3.ty);
-			glVertex2f(t3.x, t3.y);
-		} glEnd();
-	}
-}
-
-#define horiz_road_opengl(tex, start, end)                                    \
-   glBindTexture( GL_TEXTURE_2D, tex);                                        \
-   glBegin(GL_QUADS); {                                                       \
-      glTexCoord2i(0, 0);                                                     \
-      glVertex2f(subwin.x + start.x, subwin.y + start.y - 2);                 \
-      glTexCoord2i(TEXTURE_WIDTH, 0);                                         \
-      glVertex2f(subwin.x + end.x,   subwin.y + end.y - 2);                   \
-      glTexCoord2i(TEXTURE_WIDTH, 4);                                         \
-      glVertex2f(subwin.x + end.x,   subwin.y + end.y + 2);                   \
-      glTexCoord2i(0, 4);                                                     \
-      glVertex2f(subwin.x + start.x, subwin.y + start.y + 2);                 \
-   } glEnd();                                                                 \
-
-#define vert_road_opengl(tex, start, end)                                     \
-   glBindTexture( GL_TEXTURE_2D, tex);                                        \
-   glBegin(GL_QUADS); {                                                       \
-      glTexCoord2i(0, 0);                                                     \
-      glVertex2f(subwin.x + start.x - 3, subwin.y + start.y);                 \
-      glTexCoord2i(6, 0);                                                     \
-      glVertex2f(subwin.x + start.x + 3, subwin.y + start.y);                 \
-      glTexCoord2i(TEXTURE_WIDTH, TEXTURE_HEIGHT);                            \
-      glVertex2f(subwin.x + end.x + 3,   subwin.y + end.y);                   \
-      glTexCoord2i(TEXTURE_WIDTH - 6, TEXTURE_HEIGHT);                        \
-      glVertex2f(subwin.x + end.x - 3,   subwin.y + end.y);                   \
-   } glEnd();                                                                 \
-
-void draw_roads_opengl
-	(Rect & subwin,
-	 uint8_t roads,
-	 Vertex const & f_vert,
-	 Vertex const & r_vert,
-	 Vertex const & bl_vert,
-	 Vertex const & br_vert)
-{
-	uint8_t road;
-
-	GLuint rt_normal =
-		dynamic_cast<GLSurfaceTexture const &>
-		(*g_gr->get_road_texture(Widelands::Road_Normal)).get_gl_texture();
-	GLuint rt_busy   =
-		dynamic_cast<GLSurfaceTexture const &>
-		(*g_gr->get_road_texture(Widelands::Road_Busy)).get_gl_texture();
-
-	glDisable(GL_BLEND);
-	glColor4f(1.0f, 1.0f, 1.0f, 0.6f);
-
-	road = (roads >> Widelands::Road_East) & Widelands::Road_Mask;
-	if ((-128 < f_vert.b or -128 < r_vert.b) and road) {
-		switch (road) {
-		case Widelands::Road_Normal:
-			horiz_road_opengl(rt_normal, f_vert, r_vert)
-			break;
-		case Widelands::Road_Busy:
-			horiz_road_opengl(rt_busy, f_vert, r_vert)
-			break;
-		default:
-			assert(false);
-		}
-	}
-
-	road = (roads >> Widelands::Road_SouthEast) & Widelands::Road_Mask;
-	if ((-128 < f_vert.b or -128 < br_vert.b) and road) {
-		switch (road) {
-		case Widelands::Road_Normal:
-			vert_road_opengl(rt_normal, f_vert, br_vert);
-			break;
-		case Widelands::Road_Busy:
-			vert_road_opengl(rt_busy, f_vert, br_vert);
-			break;
-		default:
-			assert(false);
-		}
-	}
-
-	road = (roads >> Widelands::Road_SouthWest) & Widelands::Road_Mask;
-	if ((-128 < f_vert.b or -128 < bl_vert.b) and road) {
-		switch (road) {
-		case Widelands::Road_Normal:
-			vert_road_opengl(rt_normal, f_vert, bl_vert);
-			break;
-		case Widelands::Road_Busy:
-			vert_road_opengl(rt_busy, f_vert, bl_vert);
-			break;
-		default:
-			assert(false);
-		}
-	}
-}
-
-#endif
-#endif

=== modified file 'src/graphic/rendertarget.h'
--- src/graphic/rendertarget.h	2012-12-15 18:40:59 +0000
+++ src/graphic/rendertarget.h	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -88,6 +88,8 @@
 	void reset();
 
 	Surface* get_surface() {return m_surface;}
+	const Rect & get_rect() const {return m_rect;}
+	const Point & get_offset() const {return m_offset;}
 
 protected:
 	bool clip(Rect & r) const throw ();

=== modified file 'src/logic/instances.h'
--- src/logic/instances.h	2013-02-03 10:44:13 +0000
+++ src/logic/instances.h	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License

=== modified file 'src/logic/tribe.h'
--- src/logic/tribe.h	2013-02-03 10:44:13 +0000
+++ src/logic/tribe.h	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002, 2006-2011 by the Widelands Development Team
+ * Copyright (C) 2002, 2006-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -128,15 +128,25 @@
 	Immovable_Descr const * get_immovable_descr(int32_t const index) const {
 		return m_immovables.get(index);
 	}
+<<<<<<< TREE
 	Immovable_Descr const * get_immovable_descr(const std::string & imm_name) const {
 		return m_immovables.get(get_immovable_index(imm_name.c_str()));
+=======
+	Immovable_Descr const * get_immovable_descr(const std::string & immname) const {
+		return m_immovables.get(get_immovable_index(immname.c_str()));
+>>>>>>> MERGE-SOURCE
 	}
 	int32_t get_bob(char const * const l) const {return m_bobs.get_index(l);}
 	Bob::Descr const * get_bob_descr(uint16_t const index) const {
 		return m_bobs.get(index);
 	}
+<<<<<<< TREE
 	Bob::Descr const * get_bob_descr(const std::string & bob_name) const {
 		return m_bobs.exists(bob_name.c_str());
+=======
+	Bob::Descr const * get_bob_descr(const std::string & bobname) const {
+		return m_bobs.exists(bobname.c_str());
+>>>>>>> MERGE-SOURCE
 	}
 	int32_t get_nr_bobs() {return m_bobs.get_nitems();}
 

=== modified file 'src/logic/world.cc'
--- src/logic/world.cc	2012-11-30 22:10:10 +0000
+++ src/logic/world.cc	2013-02-07 18:50:33 +0000
@@ -821,6 +821,7 @@
 m_name              (s->get_name()),
 m_descname          (s->get_string("name", s->get_name())),
 m_frametime         (FRAME_LENGTH),
+m_dither_layer   (0),
 m_valid_resources   (0),
 m_nr_valid_resources(0),
 m_default_resources (-1),
@@ -896,6 +897,8 @@
 			throw game_data_error("%s: invalid type '%s'", m_name.c_str(), is);
 	}
 
+	m_dither_layer = s->get_int("dither_layer", 0);
+
 	// Determine template of the texture animation pictures
 	char fnametmpl[256];
 

=== modified file 'src/logic/world.h'
--- src/logic/world.h	2012-11-30 22:10:10 +0000
+++ src/logic/world.h	2013-02-07 18:50:33 +0000
@@ -113,6 +113,7 @@
 	int32_t get_default_resources_amount() const throw () {
 		return m_default_amount;
 	}
+	int32_t dither_layer() const {return m_dither_layer;}
 
 private:
 	const std::string m_name;
@@ -121,12 +122,13 @@
 	uint32_t    m_frametime;
 	uint8_t   m_is;
 
+	int32_t m_dither_layer;
+
 	uint8_t         * m_valid_resources;
 	uint8_t           m_nr_valid_resources;
 	int8_t            m_default_resources;
 	int32_t           m_default_amount;
 	uint32_t          m_texture; //  renderer's texture
-
 };
 
 struct MapGenInfo;

=== modified file 'src/point.h'
--- src/point.h	2012-09-21 21:36:07 +0000
+++ src/point.h	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2007 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -44,6 +44,9 @@
 	Point   operator+  (const Point & other) const {
 		return Point(x + other.x, y + other.y);
 	}
+	Point   operator-  () const {
+		return Point(-x, -y);
+	}
 	Point   operator-  (const Point & other) const {
 		return Point(x - other.x, y - other.y);
 	}

=== modified file 'src/rect.h'
--- src/rect.h	2013-02-04 21:52:38 +0000
+++ src/rect.h	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -24,8 +24,13 @@
 
 struct Rect : public Point {
 	Rect() throw () : w(0), h(0) {}
+<<<<<<< TREE
 	Rect(int32_t gx, int32_t gy, uint32_t W, uint32_t H) throw ()
 		: Point(gx, gy), w(W), h(H)
+=======
+	Rect(int32_t nx, int32_t ny, uint32_t W, uint32_t H) throw ()
+		: Point(nx, ny), w(W), h(H)
+>>>>>>> MERGE-SOURCE
 	{}
 	Rect(const Point& p, uint32_t W, uint32_t H) throw ()
 		: Point(p), w(W), h(H)

=== modified file 'src/wui/mapview.cc'
--- src/wui/mapview.cc	2012-12-16 14:29:46 +0000
+++ src/wui/mapview.cc	2013-02-07 18:50:33 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -19,7 +19,6 @@
 
 #include "mapview.h"
 
-
 #include "interactive_base.h"
 #include "interactive_player.h"
 #include "mapviewpixelfunctions.h"
@@ -30,9 +29,8 @@
 
 #include "graphic/graphic.h"
 #include "graphic/rendertarget.h"
-#include "graphic/render/gameview.h"
-#include "graphic/render/gameview_opengl.h"
-#include "graphic/render/gameview_sdl.h"
+#include "graphic/render/gamerenderer_gl.h"
+#include "graphic/render/gamerenderer_sdl.h"
 
 #include "upcast.h"
 
@@ -48,6 +46,11 @@
 m_complete_redraw_needed(true)
 {}
 
+Map_View::~Map_View()
+{
+	// explicit destructor so that smart pointer destructors
+	// with forward-declared types are properly instantiated
+}
 
 /// Moves the mouse cursor so that it is directly above the given node
 void Map_View::warp_mouse_to_node(Widelands::Coords const c) {
@@ -95,21 +98,21 @@
 
 	egbase.map().overlay_manager().load_graphics();
 
-	GameView * gameview;
+	if (!m_renderer) {
 #ifdef USE_OPENGL
-	if (g_opengl) {
-		gameview = new GameViewOpenGL(dst);
-	} else
+		if (g_opengl) {
+			m_renderer.reset(new GameRendererGL());
+		} else
 #endif
-	{
-		gameview = new GameViewSDL(dst);
+		{
+			m_renderer.reset(new GameRendererSDL());
+		}
 	}
 	if (upcast(Interactive_Player const, interactive_player, &intbase())) {
-		gameview->rendermap(egbase, interactive_player->player(), m_viewpoint);
+		m_renderer->rendermap(dst, egbase, interactive_player->player(), m_viewpoint);
 	} else {
-		gameview->rendermap(egbase, m_viewpoint);
+		m_renderer->rendermap(dst, egbase, m_viewpoint);
 	}
-	delete gameview;
 
 	m_complete_redraw_needed = false;
 	draw_tooltip(dst, tooltip());

=== modified file 'src/wui/mapview.h'
--- src/wui/mapview.h	2012-02-15 21:25:34 +0000
+++ src/wui/mapview.h	2013-02-07 18:50:33 +0000
@@ -27,6 +27,7 @@
 
 #include "ui_basic/panel.h"
 
+struct GameRenderer;
 struct Interactive_Base;
 
 /**
@@ -45,6 +46,7 @@
 		(UI::Panel * const parent,
 		 const int32_t x, const int32_t y, const uint32_t w, const uint32_t h,
 		 Interactive_Base &);
+	virtual ~Map_View();
 
 	void set_changeview(const ChangeViewFn & fn);
 
@@ -83,6 +85,7 @@
 private:
 	void stop_dragging();
 
+	boost::scoped_ptr<GameRenderer> m_renderer;
 	Interactive_Base & m_intbase;
 	ChangeViewFn m_changeview;
 	Point              m_viewpoint;

=== modified file 'src/wui/minimap.cc'
--- src/wui/minimap.cc	2012-12-13 10:41:22 +0000
+++ src/wui/minimap.cc	2013-02-07 18:50:33 +0000
@@ -26,7 +26,7 @@
 
 #include "graphic/graphic.h"
 #include "graphic/rendertarget.h"
-#include "graphic/render/gameview.h"
+#include "graphic/render/minimaprenderer.h"
 
 
 MiniMap::View::View
@@ -60,9 +60,9 @@
 
 void MiniMap::View::draw(RenderTarget & dst)
 {
-	GameView gameview(dst);
+	MiniMapRenderer mmr(dst);
 
-	gameview.renderminimap
+	mmr.renderminimap
 		(m_ibase.egbase(),
 		 m_ibase.get_player(),
 		 (*m_flags) & (MiniMap::Zoom2) ?

=== modified file 'worlds/blackland/terrainconf'
--- worlds/blackland/terrainconf	2012-02-15 21:25:34 +0000
+++ worlds/blackland/terrainconf	2013-02-07 18:50:33 +0000
@@ -7,75 +7,91 @@
 name="Ashes"
 def_resources=water 5
 is=green
+dither_layer=20
 
 [mountain1]
 name="Mountain1"
-resources=coal, iron, gold, granit 
+resources=coal, iron, gold, granit
 is=mountain
+dither_layer=50
 
 [lava-stone1]
 name="Lava stone1"
 is=acid
+dither_layer=70
 
 [lava-stone2]
 name="Lava stone2"
 is=acid
+dither_layer=70
 
 [strand]
 name="Beach"
 is=dry
+dither_layer=10
 
 [water]
 name="Water"
 def_resources=fish 4
 is=water
 fps=14
+dither_layer=0
 
 [hardground1]
 name="Hardground1"
 def_resources=water 10
 is=green
+dither_layer=30
 
 [hardground2]
 name="Hardground2"
 def_resources=water 10
 is=green
+dither_layer=30
 
 [hardground3]
 name="Hardground3"
 def_resources=water 10
 is=green
+dither_layer=30
 
 [mountain2]
 name="Mountain2"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=50
 
 [mountain3]
 name="Mountain3"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=50
 
 [mountain4]
 name="Mountain4"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=50
 
 [ashes2]
 name="Ashes2"
 def_resources=water 4
 is=green
+dither_layer=20
 
 [hardground4]
 name="Hardground4"
 def_resources=water 10
 is=green
+dither_layer=30
 
 [lava]
 name="Lava"
 is=acid
+dither_layer=60
 
 [hardlava]
 name="Hard lava"
 is=green
+dither_layer=40
 

=== modified file 'worlds/desert/terrainconf'
--- worlds/desert/terrainconf	2012-02-15 21:25:34 +0000
+++ worlds/desert/terrainconf	2013-02-07 18:50:33 +0000
@@ -7,66 +7,80 @@
 [desert1]
 name="Desert1"
 is=dry
+dither_layer=20
 
 [desert2]
 name="Desert2"
 is=dry
+dither_layer=20
 
 [desert3]
 name="Desert3"
 is=dry
+dither_layer=20
 
 [desert4]
 name="Desert4"
 def_resources=water 2
 is=green
+dither_layer=20
 
 [drysoil]
 name="Dry soil"
 def_resources=water 4
 is=green
+dither_layer=30
 
 [beach]
 name="Beach"
 is=dry
+dither_layer=10
 
 [steppe]
 name="Steppe"
 def_resources=water 5
 is=green
+dither_layer=30
 
 [meadow]
 name="Meadow"
 def_resources=water 10
 is=green
+dither_layer=40
 
 [mountainmeadow]
 name="Mountain meadow"
 is=green
+dither_layer=50
 
 [highmountainmeadow]
 name="High mountain meadow"
 is=green
+dither_layer=60
 
 [mountain1]
 name="Mountain1"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=70
 
 [mountain2]
 name="Mountain2"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=70
 
 [mountain3]
 name="Mountain3"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=70
 
 [mountain4]
 name="Mountain4"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=70
 
 
 ##### Here are few imported textures of greenland
@@ -76,7 +90,9 @@
 def_resources=fish 4
 is=water
 fps=5
+dither_layer=0
 
 [lava]
 name="Lava"
 is=acid
+dither_layer=80

=== modified file 'worlds/greenland/terrainconf'
--- worlds/greenland/terrainconf	2012-02-15 21:25:34 +0000
+++ worlds/greenland/terrainconf	2013-02-07 18:50:33 +0000
@@ -7,76 +7,92 @@
 name="Steppe"
 def_resources=water 5
 is=green
+dither_layer=20
 
 [berg1]
 name="Mountain1"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=60
 
 [schnee]
 name="Snow"
 is=dead
+dither_layer=70
 
 [sumpf]
 name="Swamp"
 def_resources=water 20
 is=unpassable
 fps=14
+dither_layer=30
 
 [strand]
 name="Beach"
 is=dry
+dither_layer=10
 
 [wasser]
 name="Water"
 def_resources=fish 4
 is=water
 fps=14
+dither_layer=0
 
 [wiese1]
 name="Meadow1"
 def_resources=water 10
 is=green
+dither_layer=40
 
 [wiese2]
 name="Meadow2"
 def_resources=water 10
 is=green
+dither_layer=40
 
 [wiese3]
 name="Meadow3"
 def_resources=water 10
 is=green
+dither_layer=40
 
 [berg2]
 name="Mountain2"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=60
 
 [berg3]
 name="Mountain3"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=60
 
 [berg4]
 name="Mountain4"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=60
 
 [steppe_kahl]
 name="Barren steppe"
 def_resources=water 4
 is=green
+dither_layer=20
 
 [wiese4]
 name="Meadow4"
 def_resources=water 10
 is=green
+dither_layer=40
 
 [lava]
 name="Lava"
 is=acid
+dither_layer=80
 
 [bergwiese]
 name="Mountain meadow"
 is=green
+dither_layer=50

=== modified file 'worlds/winterland/terrainconf'
--- worlds/winterland/terrainconf	2012-02-15 21:25:34 +0000
+++ worlds/winterland/terrainconf	2013-02-07 18:50:33 +0000
@@ -7,77 +7,93 @@
 name="Tundra"
 def_resources=water 5
 is=green
+dither_layer=50
 
 [mountain1]
 name="Mountain1"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=70
 
 [ice_flows]
 name="Ice flows"
 is=water
 fps=5
+dither_layer=10
 
 [ice_flows2]
 name="Ice flows2"
 is=water
 fps=5
+dither_layer=20
 
 [ice]
 name="Ice"
 is=dry
 #### of course ice is not dry, but this disallows the users, to build on snow. only flags are allowed. ;-)
+dither_layer=30
 
 [water]
 name="Water"
 def_resources=fish 4
 is=water
 fps=8
+dither_layer=0
 
 [tundra_taiga]
 name="Tundra taiga"
 def_resources=water 10
 is=green
+dither_layer=50
 
 [tundra2]
 name="Tundra2"
 def_resources=water 10
 is=green
+dither_layer=50
 
 [tundra3]
 name="Tundra3"
 def_resources=water 10
 is=green
+dither_layer=50
 
 [mountain2]
 name="Mountain2"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=70
 
 [mountain3]
 name="Mountain3"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=70
 
 [mountain4]
 name="Mountain4"
 resources=coal, iron, gold, granit
 is=mountain
+dither_layer=70
 
 [strand]
 name="Beach"
 is=dry
+dither_layer=40
 
 [taiga]
 name="Taiga"
 def_resources=water 10
 is=green
+dither_layer=50
 
 [lava]
 name="Lava"
 is=acid
+dither_layer=80
 
 [snow]
 name="Snow"
 def_resources=water 30
 is=green
+dither_layer=60


Follow ups