← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/cleanup_game_renderer into lp:widelands

 

SirVer has proposed merging lp:~widelands-dev/widelands/cleanup_game_renderer into lp:widelands with lp:~widelands-dev/widelands/use_sdl_image_in_one_place as a prerequisite.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/cleanup_game_renderer/+merge/243124

This is bart of some chained branches. The base branches need to be merged before this.

Suggested commit message:
- Consolidated GameRenderer and its only base class into one.
- Pulled map renderer and minimap renderer into their own library. It becomes clear that we have basic graphics library and a widelands aware one.
- Removed unused files.

--- 
We should think about changing the directory layout of src. We have at least a wl/ui (wui) base/ui (ui_basic), wl/scripting (most of it), base/scripting (LuaTable at least) , wl/graphic (game renderer, minimap renderer) and base/graphic (surfaces, texture_atlas and so on).

I do not like the name base/ for the "basic" libraries. The separation is "could be useful for other projects" and "is widelands aware". Suggestions for cool names?

-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/cleanup_game_renderer into lp:widelands.
=== modified file 'src/editor/CMakeLists.txt'
--- src/editor/CMakeLists.txt	2014-10-13 15:04:50 +0000
+++ src/editor/CMakeLists.txt	2014-11-28 08:45:54 +0000
@@ -104,4 +104,6 @@
     ui_fsmenu
     widelands_ball_of_mud
     wui
+    wui_mapview_pixelfunctions
+    wui_overlay_manager
 )

=== modified file 'src/game_io/CMakeLists.txt'
--- src/game_io/CMakeLists.txt	2014-11-24 06:31:16 +0000
+++ src/game_io/CMakeLists.txt	2014-11-28 08:45:54 +0000
@@ -27,6 +27,7 @@
     base_time_string
     economy
     graphic
+    graphic_minimap_renderer
     io_fileread
     io_filesystem
     logic
@@ -36,4 +37,6 @@
     profile
     scripting
     wui
+    wui_mapview_pixelfunctions
+    wui_overlay_manager
 )

=== modified file 'src/graphic/CMakeLists.txt'
--- src/graphic/CMakeLists.txt	2014-11-28 08:45:54 +0000
+++ src/graphic/CMakeLists.txt	2014-11-28 08:45:54 +0000
@@ -1,5 +1,8 @@
 add_subdirectory(text)
 
+# TODO(sirver): Separate this directory into a base directory and one
+# that is Widelands aware (can include logic stuff).
+
 wl_library(graphic_color
   SRCS
     color.h
@@ -77,14 +80,52 @@
     graphic_surface
 )
 
+wl_library(graphic_game_renderer
+  SRCS
+    game_renderer.cc
+    game_renderer.h
+    gl/dither_program.cc
+    gl/dither_program.h
+    gl/fields_to_draw.h
+    gl/road_program.cc
+    gl/road_program.h
+    gl/terrain_program.cc
+    gl/terrain_program.h
+  DEPENDS
+    base_exceptions
+    base_geometry
+    base_log
+    base_macros
+    graphic
+    graphic_image_io
+    graphic_surface
+    io_filesystem
+    logic
+    wui_mapview_pixelfunctions
+    wui_overlay_manager
+)
+
+wl_library(graphic_minimap_renderer
+  SRCS
+    minimap_renderer.cc
+    minimap_renderer.h
+  DEPENDS
+    base_geometry
+    base_macros
+    economy
+    graphic
+    graphic_image
+    graphic_surface
+    logic
+    wui_mapview_pixelfunctions
+)
+
 wl_library(graphic
   SRCS
     align.cc
     align.h
     animation.cc
     animation.h
-    colormap.cc
-    colormap.h
     default_resolution.h
     diranimations.h
     font.cc
@@ -93,34 +134,21 @@
     font_handler.h
     font_handler1.cc
     font_handler1.h
-    game_renderer.cc
-    game_renderer.h
     gl/blit_program.cc
     gl/blit_program.h
-    gl/dither_program.cc
-    gl/dither_program.h
     gl/draw_line_program.cc
     gl/draw_line_program.h
     gl/draw_rect_program.cc
     gl/draw_rect_program.h
-    gl/fields_to_draw.h
     gl/fill_rect_program.cc
     gl/fill_rect_program.h
-    gl/game_renderer.cc
-    gl/game_renderer.h
-    gl/road_program.cc
-    gl/road_program.h
     gl/system_headers.h
-    gl/terrain_program.cc
-    gl/terrain_program.h
     graphic.cc
     graphic.h
     image_transformations.cc
     image_transformations.h
     in_memory_image.cc
     in_memory_image.h
-    minimap_renderer.cc
-    minimap_renderer.h
     rendertarget.cc
     rendertarget.h
     richtext.cc
@@ -141,7 +169,6 @@
     base_log
     base_macros
     build_info
-    economy
     graphic_color
     graphic_image
     graphic_image_io
@@ -156,6 +183,6 @@
     profile
     scripting
     sound
-    wui
+    wui_overlay_manager
     wui_text_layout
 )

=== removed file 'src/graphic/colormap.cc'
--- src/graphic/colormap.cc	2014-07-17 13:26:23 +0000
+++ src/graphic/colormap.cc	1970-01-01 00:00:00 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2002-2004, 2006, 2009 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 "graphic/colormap.h"
-
-#include <algorithm>
-#include <cassert>
-#include <cstdlib>
-#include <cstring>
-
-/**
- * Create a new Colormap, taking the palette as a parameter.
- * It automatically creates the colormap for shading.
- */
-Colormap::Colormap (const SDL_Color & pal, const SDL_PixelFormat & format) {
-	memcpy(palette, &pal, sizeof(palette));
-
-	assert(format.BytesPerPixel == 4);
-	colormap = malloc(format.BytesPerPixel * 65536);
-
-	for (int i = 0; i < 256; ++i)
-		for (int j = 0; j < 256; ++j) {
-			int32_t shade = (j < 128) ? j : (j - 256);
-			shade = 256 + 2 * shade;
-
-			const uint32_t r = std::min<uint32_t>((palette[i].r * shade) >> 8, 255);
-			const uint32_t g = std::min<uint32_t>((palette[i].g * shade) >> 8, 255);
-			const uint32_t b = std::min<uint32_t>((palette[i].b * shade) >> 8, 255);
-
-			const uint32_t value =
-				SDL_MapRGB(&const_cast<SDL_PixelFormat &>(format), r, g, b);
-			static_cast<uint32_t *>(colormap)[(j << 8) | i] = value;
-		}
-}
-
-/**
- * Clean up.
- */
-Colormap::~Colormap ()
-{
-	free(colormap);
-}

=== removed file 'src/graphic/colormap.h'
--- src/graphic/colormap.h	2014-07-12 12:25:21 +0000
+++ src/graphic/colormap.h	1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2002-2004, 2006, 2008 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 WL_GRAPHIC_COLORMAP_H
-#define WL_GRAPHIC_COLORMAP_H
-
-#include <SDL_video.h>
-
-#include "graphic/color.h"
-
-/**
- * Colormap contains a palette and lookup table for use with ground textures.
-*/
-class Colormap {
-public:
-	Colormap (const SDL_Color &, const SDL_PixelFormat & fmt);
-	~Colormap ();
-
-	// Returns the palette of this colormap (256 entries of RGB Colors);
-	SDL_Color * get_palette() {return palette;}
-
-	// Returns the internally calculated colormap used in the renderer.
-	void * get_colormap () const {return colormap;}
-
-private:
-	SDL_Color palette[256];
-
-	/// maps 8 bit color and brightness value to the shaded color.
-	/// \note Brightness is currently 8 bits. Restricting brightness to 64 or
-	/// less shades would greatly reduce the size of this table, and thus
-	/// improve memory cache impact inside the renderer.
-	void * colormap;
-};
-
-#endif  // end of include guard: WL_GRAPHIC_COLORMAP_H

=== modified file 'src/graphic/game_renderer.cc'
--- src/graphic/game_renderer.cc	2014-09-27 18:53:55 +0000
+++ src/graphic/game_renderer.cc	2014-11-28 08:45:54 +0000
@@ -19,82 +19,227 @@
 
 #include "graphic/game_renderer.h"
 
-#include "base/macros.h"
+#include <memory>
+
+#include "graphic/gl/dither_program.h"
+#include "graphic/gl/fields_to_draw.h"
+#include "graphic/gl/road_program.h"
+#include "graphic/gl/terrain_program.h"
 #include "graphic/graphic.h"
 #include "graphic/rendertarget.h"
+#include "graphic/surface.h"
 #include "logic/editor_game_base.h"
 #include "logic/player.h"
+#include "logic/world/world.h"
+#include "wui/mapviewpixelconstants.h"
 #include "wui/mapviewpixelfunctions.h"
 #include "wui/overlay_manager.h"
 
+// Explanation of how drawing works:
+// Schematic of triangle neighborhood:
+//
+//               *
+//              / \
+//             / u \
+//         (f)/     \
+//    *------*------* (r)
+//     \  l / \  r / \
+//      \  /   \  /   \
+//       \/  d  \/ rr  \
+//       *------*------* (br)
+//        \ dd /
+//         \  /
+//          \/
+//          *
+//
+// Each field (f) owns two triangles: (r)ight & (d)own. When we look at the
+// field, we have to make sure to schedule drawing the triangles. This is done
+// by of these triangles is done by TerrainProgram.
+//
+// To draw dithered edges, we have to look at the neighboring triangles for the
+// two triangles too: If a neighboring triangle has another texture and our
+// dither layer is smaller, we have to draw a dithering triangle too - this lets the neighboring
+// texture
+// bleed into our triangle.
+//
+// The dither triangle is the triangle that should be partially (either r or
+// d). Example: if r and d have different textures and r.dither_layer >
+// d.dither_layer, then we will repaint d with the dither texture as mask.
+
+std::unique_ptr<TerrainProgram> GameRenderer::terrain_program_;
+std::unique_ptr<DitherProgram> GameRenderer::dither_program_;
+std::unique_ptr<RoadProgram> GameRenderer::road_program_;
+
+namespace {
+
 using namespace Widelands;
 
-GameRenderer::GameRenderer()
-{
-}
-
-GameRenderer::~GameRenderer()
-{
-}
-
-void GameRenderer::rendermap
-	(RenderTarget & dst,
-	 const Widelands::EditorGameBase &       egbase,
-	 const Widelands::Player           &       player,
-	 const Point                       &       viewofs)
-{
-	m_dst = &dst;
-	m_dst_offset = -viewofs;
-	m_egbase = &egbase;
-	m_player = &player;
-
-	draw_wrapper();
-}
-
-void GameRenderer::rendermap
-	(RenderTarget & dst,
-	 const Widelands::EditorGameBase & egbase,
-	 const Point                       & viewofs)
-{
-	m_dst = &dst;
-	m_dst_offset = -viewofs;
-	m_egbase = &egbase;
-	m_player = nullptr;
-
-	draw_wrapper();
-}
-
-void GameRenderer::draw_wrapper()
-{
-	Point tl_map = m_dst->get_offset() - m_dst_offset;
+// Returns the brightness value in [0, 1.] for 'fcoords' at 'gametime' for
+// 'player' (which can be nullptr).
+float field_brightness(const FCoords& fcoords,
+                       const uint32_t gametime,
+                       const Map& map,
+                       const Player* const player) {
+	uint32_t brightness = 144 + fcoords.field->get_brightness();
+	brightness = std::min<uint32_t>(255, (brightness * 255) / 160);
+
+	if (player && !player->see_all()) {
+		const Player::Field& pf = player->fields()[Map::get_index(fcoords, map.get_width())];
+		if (pf.vision == 0) {
+			return 0.;
+		} else if (pf.vision == 1) {
+			static const uint32_t kDecayTimeInMs = 20000;
+			const Duration time_ago = gametime - pf.time_node_last_unseen;
+			if (time_ago < kDecayTimeInMs) {
+				brightness = (brightness * (2 * kDecayTimeInMs - time_ago)) / (2 * kDecayTimeInMs);
+			} else {
+				brightness = brightness / 2;
+			}
+		}
+	}
+	return brightness / 255.;
+}
+
+// Returns the road that should be rendered here. The format is like in field,
+// but this is not the physically present road, but the one that should be
+// drawn (i.e. taking into account if there is fog of war involved or road
+// building overlays enabled).
+uint8_t field_roads(const FCoords& coords, const Map& map, const Player* const player) {
+	uint8_t roads;
+	if (player && !player->see_all()) {
+		const Player::Field& pf = player->fields()[Map::get_index(coords, map.get_width())];
+		roads = pf.roads | map.overlay_manager().get_road_overlay(coords);
+	} else {
+		roads = coords.field->get_roads();
+	}
+	roads |= map.overlay_manager().get_road_overlay(coords);
+	return roads;
+}
+
+}  // namespace
+
+GameRenderer::GameRenderer()  {
+}
+
+GameRenderer::~GameRenderer() {
+}
+
+void GameRenderer::rendermap(RenderTarget& dst,
+                             const Widelands::EditorGameBase& egbase,
+                             const Point& view_offset,
+
+                             const Widelands::Player& player) {
+	draw(dst, egbase, view_offset, &player);
+}
+
+void GameRenderer::rendermap(RenderTarget& dst,
+                             const Widelands::EditorGameBase& egbase,
+                             const Point& view_offset) {
+	draw(dst, egbase, view_offset, nullptr);
+}
+
+void GameRenderer::draw(RenderTarget& dst,
+                        const EditorGameBase& egbase,
+                        const Point& view_offset,
+                        const Player* player) {
+	if (terrain_program_ == nullptr) {
+		terrain_program_.reset(new TerrainProgram());
+		dither_program_.reset(new DitherProgram());
+		road_program_.reset(new RoadProgram());
+	}
+
+	Point tl_map = dst.get_offset() + view_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;
+	int minfx = tl_map.x / TRIANGLE_WIDTH - 1;
+	int minfy = tl_map.y / TRIANGLE_HEIGHT - 1;
+	int maxfx = (tl_map.x + dst.get_rect().w + (TRIANGLE_WIDTH / 2)) / TRIANGLE_WIDTH;
+	int maxfy = (tl_map.y + 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();
+	minfx -= 1;
+	minfy -= 1;
+	maxfx += 1;
+	maxfy += 10;
+
+
+	Surface* surface = dst.get_surface();
+	if (!surface)
+		return;
+
+	const Rect& bounding_rect = dst.get_rect();
+	const Point surface_offset = bounding_rect.top_left() + dst.get_offset() - view_offset;
+
+	glScissor(bounding_rect.x,
+	          surface->height() - bounding_rect.y - bounding_rect.h,
+	          bounding_rect.w,
+	          bounding_rect.h);
+	glEnable(GL_SCISSOR_TEST);
+
+	Map& map = egbase.map();
+	const uint32_t gametime = egbase.get_gametime();
+
+	FieldsToDraw fields_to_draw(minfx, maxfx, minfy, maxfy);
+	for (int32_t fy = minfy; fy <= maxfy; ++fy) {
+		for (int32_t fx = minfx; fx <= maxfx; ++fx) {
+			FieldsToDraw::Field& f =
+			   *fields_to_draw.mutable_field(fields_to_draw.calculate_index(fx, fy));
+
+			f.fx = fx;
+			f.fy = fy;
+
+			Coords coords(fx, fy);
+			int x, y;
+			MapviewPixelFunctions::get_basepix(coords, x, y);
+
+			map.normalize_coords(coords);
+			const FCoords& fcoords = map.get_fcoords(coords);
+
+			f.texture_x = float(x) / kTextureSideLength;
+			f.texture_y = float(y) / kTextureSideLength;
+
+			f.gl_x = f.pixel_x = x + surface_offset.x;
+			f.gl_y = f.pixel_y = y + surface_offset.y - fcoords.field->get_height() * HEIGHT_FACTOR;
+			surface->pixel_to_gl(&f.gl_x, &f.gl_y);
+
+			f.ter_d = fcoords.field->terrain_d();
+			f.ter_r = fcoords.field->terrain_r();
+
+			f.brightness = field_brightness(fcoords, gametime, map, player);
+
+			f.roads = field_roads(fcoords, map, player);
+		}
+	}
+
+	const World& world = egbase.world();
+	terrain_program_->draw(gametime, world.terrains(), fields_to_draw);
+	dither_program_->draw(gametime, world.terrains(), fields_to_draw);
+	road_program_->draw(*surface, fields_to_draw);
+
+	draw_objects(dst, egbase, view_offset, player, minfx, maxfx, minfy, maxfy);
+
+	glDisable(GL_SCISSOR_TEST);
 }
 
-void GameRenderer::draw_objects()
-{
+void GameRenderer::draw_objects(RenderTarget& dst,
+                                const EditorGameBase& egbase,
+                                const Point& view_offset,
+                                const Player* player,
+                                int minfx,
+                                int maxfx,
+                                int minfy,
+                                int maxfy) {
+	// TODO(sirver): this should use FieldsToDraw. Would simplify this function a lot.
 	static const uint32_t F = 0;
 	static const uint32_t R = 1;
 	static const uint32_t BL = 2;
 	static const uint32_t BR = 3;
-	const Map & map = m_egbase->map();
+	const Map & map = egbase.map();
 
-	for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
-		for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
+	for (int32_t fy = minfy; fy <= maxfy; ++fy) {
+		for (int32_t fx = minfx; fx <= maxfx; ++fx) {
 			Coords ncoords(fx, fy);
 			map.normalize_coords(ncoords);
 			FCoords coords[4];
@@ -109,7 +254,7 @@
 			MapviewPixelFunctions::get_basepix(Coords(fx + (fy & 1), fy + 1), pos[BR].x, pos[BR].y);
 			for (uint32_t d = 0; d < 4; ++d) {
 				pos[d].y -= coords[d].field->get_height() * HEIGHT_FACTOR;
-				pos[d] += m_dst_offset;
+				pos[d] -= view_offset;
 			}
 
 			PlayerNumber owner_number[4];
@@ -120,9 +265,9 @@
 			for (uint32_t d = 0; d < 4; ++d)
 				isborder[d] = coords[d].field->is_border();
 
-			if (m_player && !m_player->see_all()) {
+			if (player && !player->see_all()) {
 				for (uint32_t d = 0; d < 4; ++d) {
-					const Player::Field & pf = m_player->fields()[map.get_index(coords[d], map.get_width())];
+					const Player::Field & pf = player->fields()[map.get_index(coords[d], map.get_width())];
 					vision[d] = pf.vision;
 					if (pf.vision == 1) {
 						owner_number[d] = pf.owner;
@@ -132,32 +277,32 @@
 			}
 
 			if (isborder[F]) {
-				const Player & owner = m_egbase->player(owner_number[F]);
+				const Player & owner = egbase.player(owner_number[F]);
 				uint32_t const anim_idx = owner.tribe().frontier_animation();
 				if (vision[F])
-					m_dst->drawanim(pos[F], anim_idx, 0, &owner);
+					dst.drawanim(pos[F], anim_idx, 0, &owner);
 				for (uint32_t d = 1; d < 4; ++d) {
 					if
 						((vision[F] || vision[d]) &&
 						 isborder[d] &&
 						 (owner_number[d] == owner_number[F] || !owner_number[d]))
 					{
-						m_dst->drawanim(middle(pos[F], pos[d]), anim_idx, 0, &owner);
+						dst.drawanim(middle(pos[F], pos[d]), anim_idx, 0, &owner);
 					}
 				}
 			}
 
 			if (1 < vision[F]) { // Render stuff that belongs to the node.
 				if (BaseImmovable * const imm = coords[F].field->get_immovable())
-					imm->draw(*m_egbase, *m_dst, coords[F], pos[F]);
+					imm->draw(egbase, dst, coords[F], pos[F]);
 				for
 					(Bob * bob = coords[F].field->get_first_bob();
 					 bob;
 					 bob = bob->get_next_bob())
-					bob->draw(*m_egbase, *m_dst, pos[F]);
+					bob->draw(egbase, dst, pos[F]);
 			} else if (vision[F] == 1) {
-				const Player::Field & f_pl = m_player->fields()[map.get_index(coords[F], map.get_width())];
-				const Player * owner = owner_number[F] ? m_egbase->get_player(owner_number[F]) : nullptr;
+				const Player::Field & f_pl = player->fields()[map.get_index(coords[F], map.get_width())];
+				const Player * owner = owner_number[F] ? egbase.get_player(owner_number[F]) : nullptr;
 				if
 					(const MapObjectDescr * const map_object_descr =
 						f_pl.map_object_descr[TCoords<>::None])
@@ -193,7 +338,7 @@
 
 						if (cur_frame) // not the first frame
 							// draw the prev frame from top to where next image will be drawing
-							m_dst->drawanimrect
+							dst.drawanimrect
 								(pos[F], anim_idx, 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,
@@ -204,11 +349,11 @@
 							} catch (MapObjectDescr::AnimationNonexistent &) {
 								a = csinf.was->get_animation("idle");
 							}
-							m_dst->drawanimrect
+							dst.drawanimrect
 								(pos[F], a, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
 						}
 						assert(lines <= h);
-						m_dst->drawanimrect(pos[F], anim_idx, tanim, owner, Rect(Point(0, h - lines), w, lines));
+						dst.drawanimrect(pos[F], anim_idx, tanim, owner, Rect(Point(0, h - lines), w, lines));
 					} else if (upcast(const BuildingDescr, building, map_object_descr)) {
 						// this is a building therefore we either draw unoccupied or idle animation
 						uint32_t pic;
@@ -217,11 +362,11 @@
 						} catch (MapObjectDescr::AnimationNonexistent &) {
 							pic = building->get_animation("idle");
 						}
-						m_dst->drawanim(pos[F], pic, 0, owner);
+						dst.drawanim(pos[F], pic, 0, owner);
 					} else if (const uint32_t pic = map_object_descr->main_animation()) {
-						m_dst->drawanim(pos[F], pic, 0, owner);
+						dst.drawanim(pos[F], pic, 0, owner);
 					} else if (map_object_descr->type() == MapObjectType::FLAG) {
-						m_dst->drawanim(pos[F], owner->tribe().flag_animation(), 0, owner);
+						dst.drawanim(pos[F], owner->tribe().flag_animation(), 0, owner);
 					}
 				}
 			}
@@ -239,7 +384,7 @@
 					(const OverlayManager::OverlayInfo * it = overlay_info;
 					 it < end;
 					 ++it)
-					m_dst->blit(pos[F] - it->hotspot, it->pic);
+					dst.blit(pos[F] - it->hotspot, it->pic);
 			}
 
 			{
@@ -259,7 +404,7 @@
 					(OverlayManager::OverlayInfo const * it = overlay_info;
 					 it < end;
 					 ++it)
-					m_dst->blit(tripos - it->hotspot, it->pic);
+					dst.blit(tripos - it->hotspot, it->pic);
 			}
 
 			{
@@ -279,7 +424,7 @@
 					(OverlayManager::OverlayInfo const * it = overlay_info;
 					 it < end;
 					 ++it)
-					m_dst->blit(tripos - it->hotspot, it->pic);
+					dst.blit(tripos - it->hotspot, it->pic);
 			}
 		}
 	}

=== modified file 'src/graphic/game_renderer.h'
--- src/graphic/game_renderer.h	2014-09-27 18:53:55 +0000
+++ src/graphic/game_renderer.h	2014-11-28 08:45:54 +0000
@@ -20,17 +20,22 @@
 #ifndef WL_GRAPHIC_GAME_RENDERER_H
 #define WL_GRAPHIC_GAME_RENDERER_H
 
-#include <boost/utility.hpp>
+#include <memory>
 
 #include "base/macros.h"
 #include "base/point.h"
+#include "graphic/gl/utils.h"
 
 namespace Widelands {
 	class Player;
 	class EditorGameBase;
 }
 
+class DitherProgram;
 class RenderTarget;
+class RoadProgram;
+class TerrainProgram;
+
 
 /**
  * This abstract base class renders the main game view into an
@@ -45,56 +50,41 @@
 class 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,
-		 const Widelands::EditorGameBase &       egbase,
-		 const Widelands::Player           &       player,
-		 const 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,
-		 const Widelands::EditorGameBase & egbase,
-		 const 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::EditorGameBase 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;
-	/*@}*/
+	~GameRenderer();
+
+	// Renders the map from a player's point of view into the given
+	// drawing window. 'view_offset' is the offset of the upper left
+	// corner of the window into the map, in pixels.
+	void rendermap(RenderTarget& dst,
+	               const Widelands::EditorGameBase& egbase,
+	               const Point& view_offset,
+	               const Widelands::Player& player);
+
+	// Renders the map from an omniscient perspective. This is used
+	// for spectators, players that see all, and in the editor.
+	void rendermap(RenderTarget& dst, const Widelands::EditorGameBase& egbase, const Point& view_offset);
 
 private:
-	void draw_wrapper();
+	static std::unique_ptr<TerrainProgram> terrain_program_;
+	static std::unique_ptr<DitherProgram> dither_program_;
+	static std::unique_ptr<RoadProgram> road_program_;
+
+	// Draw the map for the given parameters (see rendermap). 'player'
+	// can be nullptr in which case the whole map is drawn.
+	void draw(RenderTarget& dst,
+	          const Widelands::EditorGameBase& egbase,
+	          const Point& view_offset,
+	          const Widelands::Player* player);
+
+	// Draws the objects (animations & overlays).
+	void draw_objects(RenderTarget& dst,
+	                  const Widelands::EditorGameBase& egbase,
+	                  const Point& view_offset,
+	                  const Widelands::Player* player,
+	                  int minfx,
+	                  int maxfx,
+	                  int minfy,
+	                  int maxfy);
 
 	DISALLOW_COPY_AND_ASSIGN(GameRenderer);
 };

=== removed file 'src/graphic/gl/game_renderer.cc'
--- src/graphic/gl/game_renderer.cc	2014-11-28 08:45:54 +0000
+++ src/graphic/gl/game_renderer.cc	1970-01-01 00:00:00 +0000
@@ -1,191 +0,0 @@
-/*
- * 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.
- *
- */
-
-#include "graphic/gl/game_renderer.h"
-
-#include <memory>
-
-#include "graphic/gl/dither_program.h"
-#include "graphic/gl/fields_to_draw.h"
-#include "graphic/gl/road_program.h"
-#include "graphic/gl/terrain_program.h"
-#include "graphic/graphic.h"
-#include "graphic/rendertarget.h"
-#include "graphic/surface.h"
-#include "logic/editor_game_base.h"
-#include "logic/player.h"
-#include "logic/world/world.h"
-#include "wui/mapviewpixelconstants.h"
-#include "wui/mapviewpixelfunctions.h"
-#include "wui/overlay_manager.h"
-
-namespace {
-
-using namespace Widelands;
-
-// Returns the brightness value in [0, 1.] for 'fcoords' at 'gametime' for
-// 'player' (which can be nullptr).
-float field_brightness(const FCoords& fcoords,
-                       const uint32_t gametime,
-                       const Map& map,
-                       const Player* const player) {
-	uint32_t brightness = 144 + fcoords.field->get_brightness();
-	brightness = std::min<uint32_t>(255, (brightness * 255) / 160);
-
-	if (player && !player->see_all()) {
-		const Player::Field& pf = player->fields()[Map::get_index(fcoords, map.get_width())];
-		if (pf.vision == 0) {
-			return 0.;
-		} else if (pf.vision == 1) {
-			static const uint32_t kDecayTimeInMs = 20000;
-			const Duration time_ago = gametime - pf.time_node_last_unseen;
-			if (time_ago < kDecayTimeInMs) {
-				brightness = (brightness * (2 * kDecayTimeInMs - time_ago)) / (2 * kDecayTimeInMs);
-			} else {
-				brightness = brightness / 2;
-			}
-		}
-	}
-	return brightness / 255.;
-}
-
-// Returns the road that should be rendered here. The format is like in field,
-// but this is not the physically present road, but the one that should be
-// drawn (i.e. taking into account if there is fog of war involved or road
-// building overlays enabled).
-uint8_t field_roads(const FCoords& coords, const Map& map, const Player* const player) {
-	uint8_t roads;
-	if (player && !player->see_all()) {
-		const Player::Field& pf = player->fields()[Map::get_index(coords, map.get_width())];
-		roads = pf.roads | map.overlay_manager().get_road_overlay(coords);
-	} else {
-		roads = coords.field->get_roads();
-	}
-	roads |= map.overlay_manager().get_road_overlay(coords);
-	return roads;
-}
-
-}  // namespace
-
-// Explanation of how drawing works:
-// Schematic of triangle neighborhood:
-//
-//               *
-//              / \
-//             / u \
-//         (f)/     \
-//    *------*------* (r)
-//     \  l / \  r / \
-//      \  /   \  /   \
-//       \/  d  \/ rr  \
-//       *------*------* (br)
-//        \ dd /
-//         \  /
-//          \/
-//          *
-//
-// Each field (f) owns two triangles: (r)ight & (d)own. When we look at the
-// field, we have to make sure to schedule drawing the triangles. This is done
-// by of these triangles is done by TerrainProgram.
-//
-// To draw dithered edges, we have to look at the neighboring triangles for the
-// two triangles too: If a neighboring triangle has another texture and our
-// dither layer is smaller, we have to draw a dithering triangle too - this lets the neighboring
-// texture
-// bleed into our triangle.
-//
-// The dither triangle is the triangle that should be partially (either r or
-// d). Example: if r and d have different textures and r.dither_layer >
-// d.dither_layer, then we will repaint d with the dither texture as mask.
-
-
-std::unique_ptr<TerrainProgram> GlGameRenderer::terrain_program_;
-std::unique_ptr<DitherProgram> GlGameRenderer::dither_program_;
-std::unique_ptr<RoadProgram> GlGameRenderer::road_program_;
-
-GlGameRenderer::GlGameRenderer()  {
-}
-
-GlGameRenderer::~GlGameRenderer() {
-}
-
-void GlGameRenderer::draw() {
-	if (terrain_program_ == nullptr) {
-		terrain_program_.reset(new TerrainProgram());
-		dither_program_.reset(new DitherProgram());
-		road_program_.reset(new RoadProgram());
-	}
-
-	Surface* surface = m_dst->get_surface();
-	if (!surface)
-		return;
-
-	const Rect& bounding_rect = m_dst->get_rect();
-	const Point surface_offset = m_dst_offset + bounding_rect.top_left() + m_dst->get_offset();
-
-	glScissor(bounding_rect.x,
-	          surface->height() - bounding_rect.y - bounding_rect.h,
-	          bounding_rect.w,
-	          bounding_rect.h);
-	glEnable(GL_SCISSOR_TEST);
-
-	Map& map = m_egbase->map();
-	const uint32_t gametime = m_egbase->get_gametime();
-
-	FieldsToDraw fields_to_draw(m_minfx, m_maxfx, m_minfy, m_maxfy);
-	for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
-		for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
-			FieldsToDraw::Field& f =
-			   *fields_to_draw.mutable_field(fields_to_draw.calculate_index(fx, fy));
-
-			f.fx = fx;
-			f.fy = fy;
-
-			Coords coords(fx, fy);
-			int x, y;
-			MapviewPixelFunctions::get_basepix(coords, x, y);
-
-			map.normalize_coords(coords);
-			const FCoords& fcoords = map.get_fcoords(coords);
-
-			f.texture_x = float(x) / kTextureSideLength;
-			f.texture_y = float(y) / kTextureSideLength;
-
-			f.gl_x = f.pixel_x = x + surface_offset.x;
-			f.gl_y = f.pixel_y = y + surface_offset.y - fcoords.field->get_height() * HEIGHT_FACTOR;
-			surface->pixel_to_gl(&f.gl_x, &f.gl_y);
-
-			f.ter_d = fcoords.field->terrain_d();
-			f.ter_r = fcoords.field->terrain_r();
-
-			f.brightness = field_brightness(fcoords, gametime, map, m_player);
-
-			f.roads = field_roads(fcoords, map, m_player);
-		}
-	}
-
-	const World& world = m_egbase->world();
-	terrain_program_->draw(gametime, world.terrains(), fields_to_draw);
-	dither_program_->draw(gametime, world.terrains(), fields_to_draw);
-	road_program_->draw(*surface, fields_to_draw);
-
-	draw_objects();
-
-	glDisable(GL_SCISSOR_TEST);
-}

=== removed file 'src/graphic/gl/game_renderer.h'
--- src/graphic/gl/game_renderer.h	2014-11-01 20:40:39 +0000
+++ src/graphic/gl/game_renderer.h	1970-01-01 00:00:00 +0000
@@ -1,48 +0,0 @@
-/*
- * 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.
- *
- */
-
-#ifndef WL_GRAPHIC_GL_GAME_RENDERER_H
-#define WL_GRAPHIC_GL_GAME_RENDERER_H
-
-#include <memory>
-
-#include "graphic/game_renderer.h"
-#include "graphic/gl/utils.h"
-
-class TerrainProgram;
-class DitherProgram;
-class RoadProgram;
-
-/**
- * OpenGL implementation of @ref GameRenderer.
- */
-class GlGameRenderer : public GameRenderer {
-public:
-	GlGameRenderer();
-	virtual ~GlGameRenderer();
-
-private:
-	static std::unique_ptr<TerrainProgram> terrain_program_;
-	static std::unique_ptr<DitherProgram> dither_program_;
-	static std::unique_ptr<RoadProgram> road_program_;
-
-	void draw() override;
-};
-
-#endif  // end of include guard: WL_GRAPHIC_GL_GAME_RENDERER_H

=== modified file 'src/graphic/rendertarget.cc'
--- src/graphic/rendertarget.cc	2014-11-26 09:36:46 +0000
+++ src/graphic/rendertarget.cc	2014-11-28 08:45:54 +0000
@@ -27,7 +27,7 @@
 #include "graphic/surface.h"
 #include "logic/player.h"
 #include "logic/tribe.h"
-#include "wui/mapviewpixelconstants.h"
+// #include "wui/mapviewpixelconstants.h"
 #include "wui/overlay_manager.h"
 
 using Widelands::BaseImmovable;

=== modified file 'src/logic/CMakeLists.txt'
--- src/logic/CMakeLists.txt	2014-11-28 08:45:54 +0000
+++ src/logic/CMakeLists.txt	2014-11-28 08:45:54 +0000
@@ -6,6 +6,7 @@
     base_log
     graphic
     graphic_image_io
+    graphic_minimap_renderer
     graphic_surface
     io_fileread
     io_filesystem
@@ -251,5 +252,7 @@
     ui_basic
     widelands_ball_of_mud
     wui
+    wui_mapview_pixelfunctions
+    wui_overlay_manager
     wui_text_layout
 )

=== modified file 'src/map_io/CMakeLists.txt'
--- src/map_io/CMakeLists.txt	2014-11-28 08:45:54 +0000
+++ src/map_io/CMakeLists.txt	2014-11-28 08:45:54 +0000
@@ -94,6 +94,7 @@
     economy
     graphic
     graphic_image_io
+    graphic_minimap_renderer
     graphic_surface
     helper
     io_fileread

=== modified file 'src/scripting/CMakeLists.txt'
--- src/scripting/CMakeLists.txt	2014-07-25 20:16:31 +0000
+++ src/scripting/CMakeLists.txt	2014-11-28 08:45:54 +0000
@@ -58,4 +58,5 @@
     third_party_eris
     ui_basic
     wui
+    wui_mapview_pixelfunctions
 )

=== modified file 'src/sound/CMakeLists.txt'
--- src/sound/CMakeLists.txt	2014-10-13 15:04:50 +0000
+++ src/sound/CMakeLists.txt	2014-11-28 08:45:54 +0000
@@ -22,4 +22,5 @@
     profile
     random
     wui
+    wui_mapview_pixelfunctions
 )

=== modified file 'src/wui/CMakeLists.txt'
--- src/wui/CMakeLists.txt	2014-10-13 15:04:50 +0000
+++ src/wui/CMakeLists.txt	2014-11-28 08:45:54 +0000
@@ -29,6 +29,29 @@
     wui
 )
 
+wl_library(wui_overlay_manager
+  SRCS
+    overlay_manager.cc
+    overlay_manager.h
+  DEPENDS
+    base_geometry
+    graphic
+    logic
+    logic_widelands_geometry
+)
+
+wl_library(wui_mapview_pixelfunctions
+  SRCS
+    mapviewpixelconstants.h
+    mapviewpixelfunctions.cc
+    mapviewpixelfunctions.h
+    vector.h
+  DEPENDS
+    base_geometry
+    logic
+    logic_widelands_geometry
+)
+
 wl_library(wui
   SRCS
     actionconfirm.cc
@@ -83,16 +106,11 @@
     logmessage.h
     mapview.cc
     mapview.h
-    mapviewpixelconstants.h
-    mapviewpixelfunctions.cc
-    mapviewpixelfunctions.h
     militarysitewindow.cc
     minimap.cc
     minimap.h
     multiplayersetupgroup.cc
     multiplayersetupgroup.h
-    overlay_manager.cc
-    overlay_manager.h
     playerdescrgroup.cc
     playerdescrgroup.h
     plot_area.cc
@@ -117,7 +135,6 @@
     transport_ui.cc
     unique_window_handler.cc
     unique_window_handler.h
-    vector.h
     ware_statistics_menu.cc
     ware_statistics_menu.h
     warehousewindow.cc
@@ -141,7 +158,9 @@
     game_io
     graphic
     graphic_color
+    graphic_game_renderer
     graphic_image
+    graphic_minimap_renderer
     graphic_surface
     io_fileread
     io_filesystem
@@ -158,5 +177,7 @@
     ui_fsmenu
     widelands_ball_of_mud
     wui_chat_ui
+    wui_mapview_pixelfunctions
+    wui_overlay_manager
     wui_text_layout
 )

=== modified file 'src/wui/mapview.cc'
--- src/wui/mapview.cc	2014-11-22 18:36:33 +0000
+++ src/wui/mapview.cc	2014-11-28 08:45:54 +0000
@@ -20,7 +20,7 @@
 #include "wui/mapview.h"
 
 #include "base/macros.h"
-#include "graphic/gl/game_renderer.h"
+#include "graphic/game_renderer.h"
 #include "graphic/graphic.h"
 #include "graphic/rendertarget.h"
 #include "logic/map.h"
@@ -31,16 +31,14 @@
 #include "wui/mapviewpixelfunctions.h"
 #include "wui/overlay_manager.h"
 
-MapView::MapView
-	(UI::Panel * parent,
-	 int32_t x, int32_t y, uint32_t w, uint32_t h,
-	 InteractiveBase & player)
-:
-UI::Panel               (parent, x, y, w, h),
-m_intbase               (player),
-m_viewpoint             (Point(0, 0)),
-m_dragging              (false)
-{}
+MapView::MapView(
+   UI::Panel* parent, int32_t x, int32_t y, uint32_t w, uint32_t h, InteractiveBase& player)
+   : UI::Panel(parent, x, y, w, h),
+     m_renderer(new GameRenderer()),
+     m_intbase(player),
+     m_viewpoint(Point(0, 0)),
+     m_dragging(false) {
+}
 
 MapView::~MapView()
 {
@@ -90,11 +88,8 @@
 
 	egbase.map().overlay_manager().load_graphics();
 
-	if (!m_renderer) {
-		m_renderer.reset(new GlGameRenderer());
-	}
 	if (upcast(InteractivePlayer const, interactive_player, &intbase())) {
-		m_renderer->rendermap(dst, egbase, interactive_player->player(), m_viewpoint);
+		m_renderer->rendermap(dst, egbase, m_viewpoint, interactive_player->player());
 	} else {
 		m_renderer->rendermap(dst, egbase, m_viewpoint);
 	}


Follow ups