← Back to team overview

widelands-dev team mailing list archive

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

 

SirVer has proposed merging lp:~widelands-dev/widelands/glsl1 into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

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

Ports the remaining fixed pipeline OpenGL stuff to OpenGL 2.1. Also some compatibility changes for OpenGL ES 2 to get us closer to that.

Note: this does not yet bring full OpenGL 3/OpenGL 2 core context compatibility, we still use Model matrices in some places.
-- 
https://code.launchpad.net/~widelands-dev/widelands/glsl1/+merge/241179
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/glsl1 into lp:widelands.
=== removed file 'cmake/codecheck/rules/illegal_character_before_opening_brace'
--- cmake/codecheck/rules/illegal_character_before_opening_brace	2010-11-21 11:44:22 +0000
+++ cmake/codecheck/rules/illegal_character_before_opening_brace	1970-01-01 00:00:00 +0000
@@ -1,94 +0,0 @@
-#!/usr/bin/python
-
-
-"""
-This catches an opening brace that comes after a character that is not tab or
-space. It detects code like "if (condition){", which should be "if (condition)
-{". The @ is there because @{ seem to be used in doxygen comments. Characters
-after // are ignored.
-"""
-
-error_msg = "Opening brace should be on the next line."
-
-strip_comments_and_strings = True
-regexp = r"""^([^/#"']|/([^/"']|"([^"]|\\")*"|'(\\[\'0nt]|[^\'])')|"([^"\]|\\"|\\[^"])*"|'(\\[\'0nt]|[^\'])')*(/[^	 /@]|[^	 "'@])\{"""
-
-forbidden = [
-    '/ /{',
-    'if (condition){',
-
-    # Eriks tests
-    ## illegal_character_before_opening_brace.cc
-    'struct A{};',
-    'struct B{};',
-    'struct C{};',
-    'struct D{};',
-    'struct E{};',
-    'struct F{};',
-    'struct G{};',
-    'struct H{};',
-    'struct I{};',
-    'struct J{};',
-    'struct K{};',
-    'struct L{};',
-    'struct M{};',
-    'struct N{};',
-    'struct O{};',
-    'struct P{};',
-    'struct Q{};',
-    'struct R{};',
-    'struct S{};',
-    'struct T{};',
-    'struct U{};',
-    'struct V{};',
-    'struct W{};',
-    'struct X{};',
-    'struct Y{};',
-    'struct Z{};',
-    'struct a{};',
-    'struct b{};',
-    'struct c{};',
-    'struct d{};',
-    'struct e{};',
-    'struct f{};',
-    'struct g{};',
-    'struct h{};',
-    'struct i{};',
-    'struct j{};',
-    'struct k{};',
-    'struct l{};',
-    'struct m{};',
-    'struct n{};',
-    'struct o{};',
-    'struct p{};',
-    'struct q{};',
-    'struct r{};',
-    'struct s{};',
-    'struct t{};',
-    'struct u{};',
-    'struct v{};',
-    'struct w{};',
-    'struct x{};',
-    'struct y{};',
-    'struct z{};',
-    'struct _{};',
-    'struct _0{};',
-    'struct _1{};',
-    'struct _2{};',
-    'struct _3{};',
-    'struct _4{};',
-    'struct _5{};',
-    'struct _6{};',
-    'struct _7{};',
-    'struct _8{};',
-    'struct _9{};',
-]
-
-allowed = [
-    '//{',
-    '// a{b|c}',
-    'if (condition) {',
-    ' * @{',
-    'foo("{}")',
-    "buffer[i] = '{';",
-]

=== modified file 'src/base/rect.h'
--- src/base/rect.h	2014-07-05 16:41:51 +0000
+++ src/base/rect.h	2014-11-08 16:26:16 +0000
@@ -43,4 +43,18 @@
 	uint32_t w, h;
 };
 
+// TODO(sirver): Use a templated type for all kinds of rects.
+struct FloatRect {
+	FloatRect() = default;
+
+	FloatRect(float init_x, float init_y, float init_w, float init_h)
+	   : x(init_x), y(init_y), w(init_w), h(init_h) {
+	}
+
+	float x = 0.;
+	float y = 0.;
+	float w = 0.;
+	float h = 0.;
+};
+
 #endif  // end of include guard: WL_BASE_RECT_H

=== modified file 'src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc'
--- src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc	2014-10-28 12:53:29 +0000
+++ src/editor/ui_menus/editor_tool_set_terrain_options_menu.cc	2014-11-08 16:26:16 +0000
@@ -78,7 +78,7 @@
 		const Image* tex = g_gr->images().get(
 		   g_gr->get_maptexture_data(terrain_descr.get_texture())->get_texture_image());
 		Surface* surf = Surface::create(tex->width(), tex->height());
-		surf->blit(Point(0, 0), tex->surface(), Rect(0, 0, tex->width(), tex->height()), CM_Solid);
+		surf->blit(Point(0, 0), tex->surface(), Rect(0, 0, tex->width(), tex->height()), CM_Copy);
 		Point pt(1, tex->height() - kSmallPicHeight - 1);
 
 		if (ter_is == TerrainDescription::GREEN) {

=== modified file 'src/graphic/CMakeLists.txt'
--- src/graphic/CMakeLists.txt	2014-11-02 20:15:01 +0000
+++ src/graphic/CMakeLists.txt	2014-11-08 16:26:16 +0000
@@ -84,8 +84,16 @@
     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_rect_program.cc
+    gl/draw_rect_program.h
+    gl/draw_line_program.cc
+    gl/draw_line_program.h
+    gl/fill_rect_program.cc
+    gl/fill_rect_program.h
     gl/fields_to_draw.h
     gl/game_renderer.cc
     gl/game_renderer.h
@@ -93,6 +101,7 @@
     gl/road_program.h
     gl/terrain_program.cc
     gl/terrain_program.h
+    gl/system_headers.h
     graphic.cc
     graphic.h
     image_transformations.cc

=== modified file 'src/graphic/compositemode.h'
--- src/graphic/compositemode.h	2014-07-05 16:41:51 +0000
+++ src/graphic/compositemode.h	2014-11-08 16:26:16 +0000
@@ -28,12 +28,7 @@
 	 * Perform a normal blitting operation that respects the alpha
 	 * channel if present.
 	 */
-	CM_Normal = 0,
-
-	/**
-	 * Perform a solid blit that ignores the alpha channel information.
-	 */
-	CM_Solid,
+	CM_UseAlpha = 0,
 
 	/**
 	 * Copy all pixel information, including alpha channel information.

=== added file 'src/graphic/gl/blit_program.cc'
--- src/graphic/gl/blit_program.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/blit_program.cc	2014-11-08 16:26:16 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2006-2014 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 "graphic/gl/blit_program.h"
+
+#include <vector>
+
+#include "base/log.h"
+
+namespace  {
+
+const char kBlitVertexShader[] = R"(
+#version 120
+
+// Attributes.
+attribute vec2 attr_position;
+
+// Uniforms.
+uniform vec4 u_dst_rect;
+uniform vec4 u_src_rect;
+
+varying vec2 out_texture_coordinate;
+
+void main() {
+	out_texture_coordinate = u_src_rect.xy + attr_position.xy * u_src_rect.zw;
+	gl_Position = vec4(u_dst_rect.xy + attr_position.xy * u_dst_rect.zw, 0., 1.);
+}
+)";
+
+const char kBlitFragmentShader[] = R"(
+#version 120
+
+uniform sampler2D u_texture;
+
+varying vec2 out_texture_coordinate;
+
+void main() {
+	gl_FragColor = texture2D(u_texture, out_texture_coordinate);
+}
+)";
+
+}  // namespace
+
+// static
+BlitProgram& BlitProgram::instance() {
+	static BlitProgram blit_program;
+	return blit_program;
+}
+
+BlitProgram::BlitProgram() {
+	gl_program_.build(kBlitVertexShader, kBlitFragmentShader);
+
+	attr_position_ = glGetAttribLocation(gl_program_.object(), "attr_position");
+
+	u_texture_ = glGetUniformLocation(gl_program_.object(), "u_texture");
+	u_dst_rect_ = glGetUniformLocation(gl_program_.object(), "u_dst_rect");
+	u_src_rect_ = glGetUniformLocation(gl_program_.object(), "u_src_rect");
+
+	std::vector<PerVertexData> vertices;
+	vertices.push_back(PerVertexData
+			{0., 1.});
+	vertices.push_back(PerVertexData
+			{1., 1.});
+	vertices.push_back(PerVertexData
+			{0., 0.});
+	vertices.push_back(PerVertexData
+			{1., 0.});
+
+	glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object());
+	glBufferData(
+	   GL_ARRAY_BUFFER, sizeof(PerVertexData) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
+	glVertexAttribPointer(attr_position_,
+								 2,
+								 GL_FLOAT,
+								 GL_FALSE,
+								 sizeof(PerVertexData),
+								 reinterpret_cast<void*>(0));
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void BlitProgram::draw(const FloatRect& gl_dest_rect,
+                       const FloatRect& gl_src_rect,
+                       const GLuint gl_texture,
+                       const Composite composite) {
+	glUseProgram(gl_program_.object());
+	glEnableVertexAttribArray(attr_position_);
+	glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object());
+
+	glVertexAttribPointer(attr_position_,
+								 2,
+								 GL_FLOAT,
+								 GL_FALSE,
+								 sizeof(PerVertexData),
+								 reinterpret_cast<void*>(0));
+
+
+	glUniform1i(u_texture_, 0);
+	glUniform4f(u_dst_rect_, gl_dest_rect.x, gl_dest_rect.y, gl_dest_rect.w, gl_dest_rect.h);
+	glUniform4f(u_src_rect_, gl_src_rect.x, gl_src_rect.y, gl_src_rect.w, gl_src_rect.h);
+
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D, gl_texture);
+
+	if (composite == CM_Copy) {
+		glBlendFunc(GL_ONE, GL_ZERO);
+	}
+
+	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+	if (composite == CM_Copy) {
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	}
+
+	glDisableVertexAttribArray(attr_position_);
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+}

=== added file 'src/graphic/gl/blit_program.h'
--- src/graphic/gl/blit_program.h	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/blit_program.h	2014-11-08 16:26:16 +0000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006-2014 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 WL_GRAPHIC_GL_BLIT_PROGRAM_H
+#define WL_GRAPHIC_GL_BLIT_PROGRAM_H
+
+#include "base/rect.h"
+#include "graphic/color.h"
+#include "graphic/gl/surface_texture.h"
+#include "graphic/gl/utils.h"
+
+class BlitProgram {
+public:
+	// Returns the (singleton) instance of this class.
+	static BlitProgram& instance();
+
+	// Draws the rectangle 'gl_src_rect' from the texture with the name
+	// 'gl_texture' to 'gl_dest_rect' in the currently bound framebuffer. All
+	// coordinates are in the OpenGL frame. The 'composite' defines if the
+	// values are copied or if alpha values are used.
+	void draw(const FloatRect& gl_dest_rect,
+	          const FloatRect& gl_src_rect,
+	          const GLuint gl_texture,
+	          const Composite composite);
+
+private:
+	BlitProgram();
+
+	struct PerVertexData {
+		float x, y;
+	};
+	static_assert(sizeof(PerVertexData) == 8, "Wrong padding.");
+
+	// The buffer that will contain the quad for rendering.
+	Gl::Buffer gl_array_buffer_;
+
+	// The program.
+	Gl::Program gl_program_;
+
+	// Attributes.
+	GLint attr_position_;
+
+	// Uniforms.
+	GLint u_texture_;
+	GLint u_dst_rect_;
+	GLint u_src_rect_;
+
+	DISALLOW_COPY_AND_ASSIGN(BlitProgram);
+};
+
+
+#endif  // end of include guard: WL_GRAPHIC_GL_DRAW_RECT_PROGRAM_H

=== modified file 'src/graphic/gl/dither_program.cc'
--- src/graphic/gl/dither_program.cc	2014-11-02 10:05:52 +0000
+++ src/graphic/gl/dither_program.cc	2014-11-08 16:26:16 +0000
@@ -131,7 +131,6 @@
 		break;
 	default:
 		throw wexception("Never here.");
-		break;
 	}
 }
 
@@ -268,7 +267,4 @@
 	glDisableVertexAttribArray(attr_texture_position_);
 
 	glActiveTexture(GL_TEXTURE0);
-
-	// Release Program object.
-	glUseProgram(0);
 }

=== added file 'src/graphic/gl/draw_line_program.cc'
--- src/graphic/gl/draw_line_program.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/draw_line_program.cc	2014-11-08 16:26:16 +0000
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2006-2014 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 "graphic/gl/draw_line_program.h"
+
+#include <vector>
+
+#include "base/log.h"
+
+namespace  {
+
+const char kDrawLineVertexShader[] = R"(
+#version 120
+
+// Attributes.
+attribute vec2 attr_position;
+
+void main() {
+	gl_Position = vec4(attr_position, 0., 1.);
+}
+)";
+
+const char kDrawLineFragmentShader[] = R"(
+#version 120
+
+uniform ivec3 u_color;
+
+void main() {
+	gl_FragColor = vec4(vec3(u_color) / 255., 1.);
+}
+)";
+
+}  // namespace
+
+// static
+DrawLineProgram& DrawLineProgram::instance() {
+	static DrawLineProgram draw_line_program;
+	return draw_line_program;
+}
+
+DrawLineProgram::DrawLineProgram() {
+	gl_program_.build(kDrawLineVertexShader, kDrawLineFragmentShader);
+
+	attr_position_ = glGetAttribLocation(gl_program_.object(), "attr_position");
+	u_color_ = glGetUniformLocation(gl_program_.object(), "u_color");
+
+}
+
+void DrawLineProgram::draw(const float x1,
+                           const float y1,
+                           const float x2,
+                           const float y2,
+                           const RGBColor& color,
+                           const int line_width) {
+	glUseProgram(gl_program_.object());
+	glEnableVertexAttribArray(attr_position_);
+
+	const std::vector<PerVertexData> vertices = {{x1, y1}, {x2, y2}};
+
+	glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object());
+	glBufferData(
+	   GL_ARRAY_BUFFER, sizeof(PerVertexData) * vertices.size(), vertices.data(), GL_STREAM_DRAW);
+	glVertexAttribPointer(attr_position_,
+								 2,
+								 GL_FLOAT,
+								 GL_FALSE,
+								 sizeof(PerVertexData),
+								 reinterpret_cast<void*>(0));
+
+	glUniform3i(u_color_, color.r, color.g, color.b);
+
+	glLineWidth(line_width);
+	glDrawArrays(GL_LINES, 0, 2);
+
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+	glDisableVertexAttribArray(attr_position_);
+	glUseProgram(0);
+}

=== added file 'src/graphic/gl/draw_line_program.h'
--- src/graphic/gl/draw_line_program.h	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/draw_line_program.h	2014-11-08 16:26:16 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2006-2014 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 WL_GRAPHIC_GL_DRAW_LINE_PROGRAM_H
+#define WL_GRAPHIC_GL_DRAW_LINE_PROGRAM_H
+
+#include "graphic/color.h"
+#include "graphic/gl/utils.h"
+
+class DrawLineProgram {
+public:
+	// Returns the (singleton) instance of this class.
+	static DrawLineProgram& instance();
+
+	// Draws a line from (x1, y1) to (x2, y2) which are in gl
+	// coordinates in 'color' with a 'line_width' in pixels.
+	void draw(float x1, float y1, float x2, float y2, const RGBColor& color, int line_width);
+
+private:
+	DrawLineProgram();
+
+	struct PerVertexData {
+		float x, y;
+	};
+	static_assert(sizeof(PerVertexData) == 8, "Wrong padding.");
+
+	// The buffer that contains the vertices for rendering.
+	Gl::Buffer gl_array_buffer_;
+
+	// The program.
+	Gl::Program gl_program_;
+
+	// Attributes.
+	GLint attr_position_;
+
+	// Uniforms.
+	GLint u_color_;
+
+	DISALLOW_COPY_AND_ASSIGN(DrawLineProgram);
+};
+
+#endif  // end of include guard: WL_GRAPHIC_GL_DRAW_LINE_PROGRAM_H

=== added file 'src/graphic/gl/draw_rect_program.cc'
--- src/graphic/gl/draw_rect_program.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/draw_rect_program.cc	2014-11-08 16:26:16 +0000
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2006-2014 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 "graphic/gl/draw_rect_program.h"
+
+#include <vector>
+
+#include "base/log.h"
+
+namespace  {
+
+const char kDrawRectVertexShader[] = R"(
+#version 120
+
+// Attributes.
+attribute vec2 attr_position;
+
+// Uniforms.
+uniform vec4 u_rect;
+
+
+void main() {
+	float x = u_rect.x + attr_position.x * u_rect.z;
+	float y = u_rect.y + attr_position.y * u_rect.w;
+	gl_Position = vec4(x, y, 0., 1.);
+}
+)";
+
+const char kDrawRectFragmentShader[] = R"(
+#version 120
+
+uniform ivec3 u_color;
+
+void main() {
+	gl_FragColor = vec4(vec3(u_color) / 255., 1.);
+}
+)";
+
+}  // namespace
+
+// static
+DrawRectProgram& DrawRectProgram::instance() {
+	static DrawRectProgram draw_rect_program;
+	return draw_rect_program;
+}
+
+DrawRectProgram::DrawRectProgram() {
+	gl_program_.build(kDrawRectVertexShader, kDrawRectFragmentShader);
+
+	attr_position_ = glGetAttribLocation(gl_program_.object(), "attr_position");
+
+	u_color_ = glGetUniformLocation(gl_program_.object(), "u_color");
+	u_rect_ = glGetUniformLocation(gl_program_.object(), "u_rect");
+
+	std::vector<PerVertexData> vertices;
+	vertices.push_back(PerVertexData
+			{0., 0.});
+	vertices.push_back(PerVertexData
+			{0., 1.});
+	vertices.push_back(PerVertexData
+			{1., 1.});
+	vertices.push_back(PerVertexData
+			{1., 0.});
+
+	glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object());
+	glBufferData(
+	   GL_ARRAY_BUFFER, sizeof(PerVertexData) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
+	glVertexAttribPointer(attr_position_,
+								 2,
+								 GL_FLOAT,
+								 GL_FALSE,
+								 sizeof(PerVertexData),
+								 reinterpret_cast<void*>(0));
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void DrawRectProgram::draw(const FloatRect& gl_dst_rect, const RGBColor& color) {
+	glUseProgram(gl_program_.object());
+	glEnableVertexAttribArray(attr_position_);
+	glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object());
+
+	glVertexAttribPointer(attr_position_,
+								 2,
+								 GL_FLOAT,
+								 GL_FALSE,
+								 sizeof(PerVertexData),
+								 reinterpret_cast<void*>(0));
+
+	glUniform4f(u_rect_, gl_dst_rect.x, gl_dst_rect.y, gl_dst_rect.w, gl_dst_rect.h);
+	glUniform3i(u_color_, color.r, color.g, color.b);
+
+	glLineWidth(1.);
+	glDrawArrays(GL_LINE_LOOP, 0, 4);
+
+	glDisableVertexAttribArray(attr_position_);
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+}

=== added file 'src/graphic/gl/draw_rect_program.h'
--- src/graphic/gl/draw_rect_program.h	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/draw_rect_program.h	2014-11-08 16:26:16 +0000
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2006-2014 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 WL_GRAPHIC_GL_DRAW_RECT_PROGRAM_H
+#define WL_GRAPHIC_GL_DRAW_RECT_PROGRAM_H
+
+#include "base/rect.h"
+#include "graphic/color.h"
+#include "graphic/gl/utils.h"
+
+class DrawRectProgram {
+public:
+	// Returns the (singleton) instance of this class.
+	static DrawRectProgram& instance();
+
+	// Draws a (non-solid) rect in 'color' into the currently activated
+	// framebuffer.
+	void draw(const FloatRect& gl_dst_rect, const RGBColor& color);
+
+private:
+	DrawRectProgram();
+
+	struct PerVertexData {
+		float x, y;
+	};
+	static_assert(sizeof(PerVertexData) == 8, "Wrong padding.");
+
+	// The buffer that will contain the quad for rendering.
+	Gl::Buffer gl_array_buffer_;
+
+	// The program.
+	Gl::Program gl_program_;
+
+	// Attributes.
+	GLint attr_position_;
+
+	// Uniforms.
+	GLint u_rect_;
+	GLint u_color_;
+
+	DISALLOW_COPY_AND_ASSIGN(DrawRectProgram);
+};
+
+
+#endif  // end of include guard: WL_GRAPHIC_GL_DRAW_RECT_PROGRAM_H

=== added file 'src/graphic/gl/fill_rect_program.cc'
--- src/graphic/gl/fill_rect_program.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/fill_rect_program.cc	2014-11-08 16:26:16 +0000
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2006-2014 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 "graphic/gl/fill_rect_program.h"
+
+#include <vector>
+
+#include "base/log.h"
+
+namespace  {
+
+const char kFillRectVertexShader[] = R"(
+#version 120
+
+// Attributes.
+attribute vec2 attr_position;
+
+// Uniforms.
+uniform vec4 u_rect;
+
+
+void main() {
+	float x = u_rect.x + attr_position.x * u_rect.z;
+	float y = u_rect.y + attr_position.y * u_rect.w;
+	gl_Position = vec4(x, y, 0., 1.);
+}
+)";
+
+const char kFillRectFragmentShader[] = R"(
+#version 120
+
+uniform ivec4 u_color;
+
+void main() {
+	gl_FragColor = vec4(u_color) / 255.;
+}
+)";
+
+}  // namespace
+
+// static
+FillRectProgram& FillRectProgram::instance() {
+	static FillRectProgram fill_rect_program;
+	return fill_rect_program;
+}
+
+FillRectProgram::FillRectProgram() {
+	gl_program_.build(kFillRectVertexShader, kFillRectFragmentShader);
+
+	attr_position_ = glGetAttribLocation(gl_program_.object(), "attr_position");
+
+	u_color_ = glGetUniformLocation(gl_program_.object(), "u_color");
+	u_rect_ = glGetUniformLocation(gl_program_.object(), "u_rect");
+
+	std::vector<PerVertexData> vertices;
+	vertices.push_back(PerVertexData
+			{0., 1.});
+	vertices.push_back(PerVertexData
+			{1., 1.});
+	vertices.push_back(PerVertexData
+			{0., 0.});
+	vertices.push_back(PerVertexData
+			{1., 0.});
+
+	glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object());
+	glBufferData(
+	   GL_ARRAY_BUFFER, sizeof(PerVertexData) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
+	glVertexAttribPointer(attr_position_,
+								 2,
+								 GL_FLOAT,
+								 GL_FALSE,
+								 sizeof(PerVertexData),
+								 reinterpret_cast<void*>(0));
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void FillRectProgram::draw(const FloatRect& gl_dst_rect, const RGBAColor& color) {
+	glUseProgram(gl_program_.object());
+	glEnableVertexAttribArray(attr_position_);
+	glBindBuffer(GL_ARRAY_BUFFER, gl_array_buffer_.object());
+
+	glVertexAttribPointer(attr_position_,
+								 2,
+								 GL_FLOAT,
+								 GL_FALSE,
+								 sizeof(PerVertexData),
+								 reinterpret_cast<void*>(0));
+
+	glUniform4f(u_rect_, gl_dst_rect.x, gl_dst_rect.y, gl_dst_rect.w, gl_dst_rect.h);
+	glUniform4i(u_color_, color.r, color.g, color.b, color.a);
+
+	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+	glDisableVertexAttribArray(attr_position_);
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+}

=== added file 'src/graphic/gl/fill_rect_program.h'
--- src/graphic/gl/fill_rect_program.h	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/fill_rect_program.h	2014-11-08 16:26:16 +0000
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2006-2014 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 WL_GRAPHIC_GL_FILL_RECT_PROGRAM_H
+#define WL_GRAPHIC_GL_FILL_RECT_PROGRAM_H
+
+#include "base/rect.h"
+#include "graphic/color.h"
+#include "graphic/gl/utils.h"
+
+class FillRectProgram {
+public:
+	// Returns the (singleton) instance of this class.
+	static FillRectProgram& instance();
+
+	// Fills a solid rect in 'color' into the currently activated
+	// framebuffer.
+	void draw(const FloatRect& gl_dst_rect, const RGBAColor& color);
+
+private:
+	FillRectProgram();
+
+	struct PerVertexData {
+		float x, y;
+	};
+	static_assert(sizeof(PerVertexData) == 8, "Wrong padding.");
+
+	// The buffer that will contain the quad for rendering.
+	Gl::Buffer gl_array_buffer_;
+
+	// The program.
+	Gl::Program gl_program_;
+
+	// Attributes.
+	GLint attr_position_;
+
+	// Uniforms.
+	GLint u_rect_;
+	GLint u_color_;
+
+	DISALLOW_COPY_AND_ASSIGN(FillRectProgram);
+};
+
+
+#endif  // end of include guard: WL_GRAPHIC_GL_FILL_RECT_PROGRAM_H

=== modified file 'src/graphic/gl/road_program.cc'
--- src/graphic/gl/road_program.cc	2014-11-01 20:29:10 +0000
+++ src/graphic/gl/road_program.cc	2014-11-08 16:26:16 +0000
@@ -226,7 +226,4 @@
 	glDisableVertexAttribArray(attr_texture_mix_);
 
 	glActiveTexture(GL_TEXTURE0);
-
-	glUseProgram(0);
-
 }

=== modified file 'src/graphic/gl/surface.cc'
--- src/graphic/gl/surface.cc	2014-09-27 18:53:55 +0000
+++ src/graphic/gl/surface.cc	2014-11-08 16:26:16 +0000
@@ -24,6 +24,10 @@
 #include <cstdlib>
 
 #include "base/macros.h"
+#include "graphic/gl/blit_program.h"
+#include "graphic/gl/draw_line_program.h"
+#include "graphic/gl/draw_rect_program.h"
+#include "graphic/gl/fill_rect_program.h"
 #include "graphic/gl/surface_texture.h"
 #include "graphic/graphic.h"
 
@@ -58,45 +62,35 @@
 	*(reinterpret_cast<uint32_t *>(data)) = clr;
 }
 
-/**
- * Draws the outline of a rectangle
- */
-void GLSurface::draw_rect(const Rect& rc, const RGBColor clr)
+FloatRect GLSurface::to_opengl(const Rect& rect, ConversionMode mode) {
+	const float delta = mode == ConversionMode::kExact ? 0. : 0.5;
+	float x1 = rect.x + delta;
+	float y1 = rect.y + delta;
+	pixel_to_gl(&x1, &y1);
+	float x2 = rect.x + rect.w - delta;
+	float y2 = rect.y + rect.h - delta;
+	pixel_to_gl(&x2, &y2);
+
+	return FloatRect(x1, y1, x2 - x1, y2 - y1);
+}
+
+void GLSurface::draw_rect(const Rect& rc, const RGBColor& clr)
 {
-	assert(g_opengl);
-	glDisable(GL_BLEND);
-	glDisable(GL_TEXTURE_2D);
-	glLineWidth(1);
-
-	glBegin(GL_LINE_LOOP); {
-		glColor3ub(clr.r, clr.g, clr.b);
-		glVertex2f(rc.x + 0.5f,        rc.y + 0.5f);
-		glVertex2f(rc.x + rc.w - 0.5f, rc.y + 0.5f);
-		glVertex2f(rc.x + rc.w - 0.5f, rc.y + rc.h - 0.5f);
-		glVertex2f(rc.x + 0.5f,        rc.y + rc.h - 0.5f);
-	} glEnd();
-	glEnable(GL_TEXTURE_2D);
+	glViewport(0, 0, width(), height());
+	DrawRectProgram::instance().draw(to_opengl(rc, ConversionMode::kMidPoint), clr);
 }
 
-
 /**
  * Draws a filled rectangle
  */
-void GLSurface::fill_rect(const Rect& rc, const RGBAColor clr) {
-	assert(rc.x >= 0);
-	assert(rc.y >= 0);
-	assert(g_opengl);
-	glDisable(GL_TEXTURE_2D);
-	glDisable(GL_BLEND);
-
-	glBegin(GL_QUADS); {
-		glColor4ub(clr.r, clr.g, clr.b, clr.a);
-		glVertex2f(rc.x,        rc.y);
-		glVertex2f(rc.x + rc.w, rc.y);
-		glVertex2f(rc.x + rc.w, rc.y + rc.h);
-		glVertex2f(rc.x,        rc.y + rc.h);
-	} glEnd();
-	glEnable(GL_TEXTURE_2D);
+void GLSurface::fill_rect(const Rect& rc, const RGBAColor& clr) {
+	glViewport(0, 0, width(), height());
+
+	glBlendFunc(GL_ONE, GL_ZERO);
+
+	FillRectProgram::instance().draw(to_opengl(rc, ConversionMode::kExact), clr);
+
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 }
 
 /**
@@ -107,117 +101,69 @@
 	if (!factor)
 		return;
 
-	assert(rc.x >= 0);
-	assert(rc.y >= 0);
-	assert(rc.w >= 1);
-	assert(rc.h >= 1);
-	assert(g_opengl);
+	glViewport(0, 0, width(), height());
 
+	// The simple trick here is to fill the rect, but using a different glBlendFunc that will sum
+	// src and target (or subtract them if factor is negative).
 	if (factor < 0) {
-		if (!g_gr->caps().gl.blendequation)
-			return;
-
 		glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
 	}
 
-	/* glBlendFunc is a very nice feature of opengl. You can specify how the
-	* color is calculated.
-	*
-	* glBlendFunc(GL_ONE, GL_ONE) means the following:
-	* Rnew = Rdest + Rsrc
-	* Gnew = Gdest + Gsrc
-	* Bnew = Bdest + Bsrc
-	* Anew = Adest + Asrc
-	* where Xnew is the new calculated color for destination, Xdest is the old
-	* color of the destination and Xsrc is the color of the source.
-	*/
-	glEnable(GL_BLEND);
-	glDisable(GL_TEXTURE_2D);
 	glBlendFunc(GL_ONE, GL_ONE);
 
-	// And now simply draw a rect with factor as the color
-	// (this is the source color) over the region
-	glBegin(GL_QUADS); {
-		glColor4f
-			((std::abs(factor) / 256.0f),
-			 (std::abs(factor) / 256.0f),
-			 (std::abs(factor) / 256.0f),
-			 0);
-		glVertex2f(rc.x,        rc.y);
-		glVertex2f(rc.x + rc.w, rc.y);
-		glVertex2f(rc.x + rc.w, rc.y + rc.h);
-		glVertex2f(rc.x,        rc.y + rc.h);
-	} glEnd();
+	const int delta = std::abs(factor);
+	FillRectProgram::instance().draw(
+	   to_opengl(rc, ConversionMode::kExact), RGBAColor(delta, delta, delta, 0));
 
-	if (factor < 0)
+	if (factor < 0) {
 		glBlendEquation(GL_FUNC_ADD);
+	}
 
-	glEnable(GL_TEXTURE_2D);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 }
 
 void GLSurface::draw_line
 	(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor& color, uint8_t gwidth)
 {
-	glDisable(GL_BLEND);
-	glDisable(GL_TEXTURE_2D);
-	glLineWidth(gwidth);
-	glBegin(GL_LINES); {
-		glColor3ub(color.r, color.g, color.b);
-		glVertex2f(x1 + 0.5f, y1 + 0.5f);
-		glVertex2f(x2 + 0.5f, y2 + 0.5f);
-	} glEnd();
-
-	glEnable(GL_TEXTURE_2D);
+	float gl_x1 = x1 + 0.5;
+	float gl_y1 = y1 + 0.5;
+	pixel_to_gl(&gl_x1, &gl_y1);
+
+	float gl_x2 = x2 + 0.5;
+	float gl_y2 = y2 + 0.5;
+	pixel_to_gl(&gl_x2, &gl_y2);
+
+	DrawLineProgram::instance().draw(gl_x1, gl_y1, gl_x2, gl_y2, color, gwidth);
+}
+
+// Converts the pixel (x, y) in a texture to a gl coordinate in [0, 1].
+inline void pixel_to_gl_texture(const int width, const int height, float* x, float* y) {
+	*x = (*x / width);
+	*y = (*y / height);
 }
 
 void GLSurface::blit
 	(const Point& dst, const Surface* image, const Rect& srcrc, Composite cm)
 {
-	// Note: This function is highly optimized and therefore does not restore
-	// all state. It also assumes that all other glStuff restores state to make
-	// this function faster.
-
-	assert(g_opengl);
-	const GLSurfaceTexture& surf = *static_cast<const GLSurfaceTexture*>(image);
-
-	/* Set a texture scaling factor. Normally texture coordinates
-	* (see glBegin()...glEnd() Block below) are given in the range 0-1
-	* to avoid the calculation (and let opengl do it) the texture
-	* space is modified. glMatrixMode select which matrixconst  to manipulate
-	* (the texture transformation matrix in this case). glLoadIdentity()
-	* resets the (selected) matrix to the identity matrix. And finally
-	* glScalef() calculates the texture matrix.
-	*/
-	glMatrixMode(GL_TEXTURE);
-	glLoadIdentity();
-	glScalef
-		(1.0f / static_cast<GLfloat>(surf.get_tex_w()),
-		 1.0f / static_cast<GLfloat>(surf.get_tex_h()), 1);
-
-	// Enable Alpha blending
-	if (cm == CM_Normal) {
-		glEnable(GL_BLEND);
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-	} else {
-		glDisable(GL_BLEND);
+	glViewport(0, 0, width(), height());
+
+	// Source Rectangle.
+	const GLSurfaceTexture* const texture = static_cast<const GLSurfaceTexture*>(image);
+	FloatRect gl_src_rect;
+	{
+		float x1 = srcrc.x;
+		float y1 = srcrc.y;
+		pixel_to_gl_texture(texture->width(), texture->height(), &x1, &y1);
+		float x2 = srcrc.x + srcrc.w;
+		float y2 = srcrc.y + srcrc.h;
+		pixel_to_gl_texture(texture->width(), texture->height(), &x2, &y2);
+		gl_src_rect.x = x1;
+		gl_src_rect.y = y1;
+		gl_src_rect.w = x2 - x1;
+		gl_src_rect.h = y2 - y1;
 	}
 
-	glBindTexture(GL_TEXTURE_2D, surf.get_gl_texture());
+	const FloatRect gl_dst_rect = to_opengl(Rect(dst.x, dst.y, srcrc.w, srcrc.h), ConversionMode::kExact);
 
-	glBegin(GL_QUADS); {
-		// set color white, otherwise textures get mixed with color
-		glColor3f(1.0, 1.0, 1.0);
-		// top-left
-		glTexCoord2i(srcrc.x, srcrc.y);
-		glVertex2i(dst.x, dst.y);
-		// top-right
-		glTexCoord2i(srcrc.x + srcrc.w, srcrc.y);
-		glVertex2f(dst.x + srcrc.w, dst.y);
-		// bottom-right
-		glTexCoord2i(srcrc.x + srcrc.w, srcrc.y + srcrc.h);
-		glVertex2f(dst.x + srcrc.w, dst.y + srcrc.h);
-		// bottom-left
-		glTexCoord2i(srcrc.x, srcrc.y + srcrc.h);
-		glVertex2f(dst.x, dst.y + srcrc.h);
-	} glEnd();
+	BlitProgram::instance().draw(gl_dst_rect, gl_src_rect, texture->get_gl_texture(), cm);
 }

=== modified file 'src/graphic/gl/surface.h'
--- src/graphic/gl/surface.h	2014-09-27 18:53:55 +0000
+++ src/graphic/gl/surface.h	2014-11-08 16:26:16 +0000
@@ -22,10 +22,7 @@
 
 #include <memory>
 
-#define NO_SDL_GLEXT
-#include <GL/glew.h>
-#include <SDL_opengl.h>
-
+#include "graphic/gl/system_headers.h"
 #include "graphic/surface.h"
 
 class GLSurface : public Surface {
@@ -38,16 +35,29 @@
 	uint8_t * get_pixels() const override;
 	void set_pixel(uint16_t x, uint16_t y, uint32_t clr) override;
 	uint32_t get_pixel(uint16_t x, uint16_t y) override;
-
 	void blit(const Point&, const Surface*, const Rect& srcrc, Composite cm) override;
-	void fill_rect(const Rect&, RGBAColor) override;
-	void draw_rect(const Rect&, RGBColor) override;
+	void fill_rect(const Rect&, const RGBAColor&) override;
+	void draw_rect(const Rect&, const RGBColor&) override;
 	void brighten_rect(const Rect&, int32_t factor) override;
-
 	virtual void draw_line
 		(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor&, uint8_t width) override;
 
 protected:
+	// Converts the given pixel into an OpenGl point. This might
+	// need some flipping of axis, depending if you want to render
+	// on the screen or not.
+	virtual void pixel_to_gl(float* x, float* y) = 0;
+
+	// Convert the 'rect' in pixel space into opengl space.
+	enum class ConversionMode {
+		// Convert the rect as given.
+		kExact,
+
+		// Convert the rect so that the borders are in the center
+		// of the pixels.
+		kMidPoint,
+	};
+	FloatRect to_opengl(const Rect& rect, ConversionMode mode);
 
 	/// Logical width and height of the surface
 	uint16_t m_w, m_h;

=== modified file 'src/graphic/gl/surface_screen.cc'
--- src/graphic/gl/surface_screen.cc	2014-09-27 18:53:55 +0000
+++ src/graphic/gl/surface_screen.cc	2014-11-08 16:26:16 +0000
@@ -29,6 +29,10 @@
 	m_h = h;
 }
 
+void GLSurfaceScreen::pixel_to_gl(float* x, float* y) {
+	*x = (*x / m_w) * 2. - 1.;
+	*y = 1. - (*y / m_h) * 2.;
+}
 
 /**
  * Swap order of rows in m_pixels, to compensate for the upside-down nature of the

=== modified file 'src/graphic/gl/surface_screen.h'
--- src/graphic/gl/surface_screen.h	2014-09-27 18:53:55 +0000
+++ src/graphic/gl/surface_screen.h	2014-11-08 16:26:16 +0000
@@ -36,6 +36,8 @@
 	const SDL_PixelFormat & format() const override;
 
 private:
+	void pixel_to_gl(float* x, float* y) override;
+
 	void swap_rows();
 };
 

=== modified file 'src/graphic/gl/surface_texture.cc'
--- src/graphic/gl/surface_texture.cc	2014-11-02 20:15:01 +0000
+++ src/graphic/gl/surface_texture.cc	2014-11-08 16:26:16 +0000
@@ -20,57 +20,59 @@
 
 #include <cassert>
 
+#include "base/log.h"
+#include "base/macros.h"
 #include "base/wexception.h"
+#include "graphic/gl/blit_program.h"
 #include "graphic/gl/surface.h"
 #include "graphic/gl/utils.h"
 #include "graphic/graphic.h"
-
-GLuint GLSurfaceTexture::gl_framebuffer_id_;
-
-static bool use_arb_;
+#include "graphic/sdl/utils.h"
 
 namespace  {
 
-// Return the smallest power of two greater than or equal to \p x.
-uint32_t next_power_of_two(uint32_t x)
-{
-	uint32_t pot = 1;
-
-	while (pot < x)
-		pot *= 2;
-
-	return pot;
+class GlFramebuffer {
+public:
+	static GlFramebuffer& instance() {
+		static GlFramebuffer gl_framebuffer;
+		return gl_framebuffer;
+	}
+
+	~GlFramebuffer() {
+		glDeleteFramebuffers(1, &gl_framebuffer_id_);
+	}
+
+	GLuint id() const {
+		return gl_framebuffer_id_;
+	}
+
+private:
+	GlFramebuffer() {
+		// Generate the framebuffer for Offscreen rendering.
+		glGenFramebuffers(1, &gl_framebuffer_id_);
+	}
+
+	GLuint gl_framebuffer_id_;
+
+	DISALLOW_COPY_AND_ASSIGN(GlFramebuffer);
+};
+
+bool is_bgr_surface(const SDL_PixelFormat& fmt) {
+	return (fmt.Bmask == 0x000000ff && fmt.Gmask == 0x0000ff00 && fmt.Rmask == 0x00ff0000);
+}
+
+inline void setup_gl(const GLuint texture) {
+	glBindFramebuffer(GL_FRAMEBUFFER, GlFramebuffer::instance().id());
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+}
+
+inline void reset_gl() {
+	glBindFramebuffer(GL_FRAMEBUFFER, 0);
 }
 
 }  // namespace
 
 /**
- * Initial global resources needed for fast offscreen rendering.
- */
-void GLSurfaceTexture::initialize(bool use_arb) {
-	use_arb_ = use_arb;
-
-	// Generate the framebuffer for Offscreen rendering.
-	if (use_arb) {
-		glGenFramebuffers(1, &gl_framebuffer_id_);
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
-	} else {
-		glGenFramebuffersEXT(1, &gl_framebuffer_id_);
-		glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
-	}
-}
-
-/**
- * Free global resources.
- */
-void GLSurfaceTexture::cleanup() {
-	if (use_arb_)
-		glDeleteFramebuffers(1, &gl_framebuffer_id_);
-	else
-		glDeleteFramebuffersEXT(1, &gl_framebuffer_id_);
-}
-
-/**
  * Initialize an OpenGL texture of the given dimensions.
  *
  * The initial data of the texture is undefined.
@@ -83,7 +85,7 @@
 		return;
 	}
 	glTexImage2D
-		(GL_TEXTURE_2D, 0, GL_RGBA, m_tex_w, m_tex_h, 0, GL_RGBA,
+		(GL_TEXTURE_2D, 0, GL_RGBA, m_w, m_h, 0, GL_RGBA,
 		 GL_UNSIGNED_BYTE, nullptr);
 }
 
@@ -96,18 +98,17 @@
 {
 	init(surface->w, surface->h);
 
-	// Convert image data
+	// Convert image data. BGR Surface support is an extension for
+	// OpenGL ES 2, which we rather not rely on. So we convert our
+	// surfaces in software.
+	// TODO(sirver): SDL_TTF returns all data in BGR format. If we
+	// use freetype directly we might be able to avoid that.
 	uint8_t bpp = surface->format->BytesPerPixel;
 
-	if
-		(surface->format->palette ||
-		 m_tex_w != static_cast<uint32_t>(surface->w) ||
-		 m_tex_h != static_cast<uint32_t>(surface->h) ||
-		 (bpp != 3 && bpp != 4))
-	{
-		SDL_Surface * converted = SDL_CreateRGBSurface
-			(SDL_SWSURFACE, m_tex_w, m_tex_h,
-			 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+	if (surface->format->palette || m_w != static_cast<uint32_t>(surface->w) ||
+	    m_h != static_cast<uint32_t>(surface->h) || (bpp != 3 && bpp != 4) ||
+	    is_bgr_surface(*surface->format)) {
+		SDL_Surface* converted = empty_sdl_surface(m_w, m_h);
 		assert(converted);
 		SDL_SetSurfaceAlphaMod(converted,  SDL_ALPHA_OPAQUE);
 		SDL_SetSurfaceBlendMode(converted, SDL_BLENDMODE_NONE);
@@ -119,64 +120,16 @@
 		bpp = surface->format->BytesPerPixel;
 	}
 
-	const SDL_PixelFormat & fmt = *surface->format;
-	GLenum pixels_format;
-
-	glPushAttrib(GL_PIXEL_MODE_BIT);
-
-	if (bpp == 4) {
-		if
-			(fmt.Rmask == 0x000000ff && fmt.Gmask == 0x0000ff00 &&
-			 fmt.Bmask == 0x00ff0000)
-		{
-			if (fmt.Amask == 0xff000000) {
-				pixels_format = GL_RGBA;
-			} else {
-				pixels_format = GL_RGBA;
-				// Read four bytes per pixel but ignore the alpha value
-				glPixelTransferi(GL_ALPHA_SCALE, 0.0f);
-				glPixelTransferi(GL_ALPHA_BIAS, 1.0f);
-			}
-		} else if
-			(fmt.Bmask == 0x000000ff && fmt.Gmask == 0x0000ff00 &&
-			 fmt.Rmask == 0x00ff0000)
-		{
-			if (fmt.Amask == 0xff000000) {
-				pixels_format = GL_BGRA;
-			} else {
-				pixels_format = GL_BGRA;
-				// Read four bytes per pixel but ignore the alpha value
-				glPixelTransferi(GL_ALPHA_SCALE, 0.0f);
-				glPixelTransferi(GL_ALPHA_BIAS, 1.0f);
-			}
-		} else
-			throw wexception("OpenGL: Unknown pixel format");
-	} else  if (bpp == 3) {
-		if
-			(fmt.Rmask == 0x000000ff && fmt.Gmask == 0x0000ff00 &&
-			 fmt.Bmask == 0x00ff0000)
-		{
-			pixels_format = GL_RGB;
-		} else if
-			(fmt.Bmask == 0x000000ff && fmt.Gmask == 0x0000ff00 &&
-			 fmt.Rmask == 0x00ff0000)
-		{
-			pixels_format = GL_BGR;
-		} else
-			throw wexception("OpenGL: Unknown pixel format");
-	} else
-		throw wexception("OpenGL: Unknown pixel format");
+	const GLenum pixels_format = bpp == 4 ? GL_RGBA : GL_RGB;
 
 	SDL_LockSurface(surface);
 
 	glTexImage2D
-		(GL_TEXTURE_2D, 0, intensity ? GL_INTENSITY : GL_RGBA, m_tex_w, m_tex_h, 0,
+		(GL_TEXTURE_2D, 0, intensity ? GL_INTENSITY : GL_RGBA, m_w, m_h, 0,
 		 pixels_format, GL_UNSIGNED_BYTE, surface->pixels);
 
 	SDL_UnlockSurface(surface);
 	SDL_FreeSurface(surface);
-
-	glPopAttrib();
 }
 
 GLSurfaceTexture::~GLSurfaceTexture()
@@ -184,6 +137,11 @@
 	glDeleteTextures(1, &m_texture);
 }
 
+void GLSurfaceTexture::pixel_to_gl(float* x, float* y) {
+	*x = (*x / m_w) * 2. - 1.;
+	*y = (*y / m_h) * 2. - 1.;
+}
+
 void GLSurfaceTexture::init(uint16_t w, uint16_t h)
 {
 	m_w = w;
@@ -192,14 +150,6 @@
 		return;
 	}
 
-	if (g_gr->caps().gl.tex_power_of_two) {
-		m_tex_w = next_power_of_two(w);
-		m_tex_h = next_power_of_two(h);
-	} else {
-		m_tex_w = w;
-		m_tex_h = h;
-	}
-
 	glGenTextures(1, &m_texture);
 	glBindTexture(GL_TEXTURE_2D, m_texture);
 
@@ -220,7 +170,7 @@
 	}
 	assert(!m_pixels);
 
-	m_pixels.reset(new uint8_t[m_tex_w * m_tex_h * 4]);
+	m_pixels.reset(new uint8_t[m_w * m_h * 4]);
 
 	if (mode == Lock_Normal) {
 		glBindTexture(GL_TEXTURE_2D, m_texture);
@@ -237,7 +187,7 @@
 	if (mode == Unlock_Update) {
 		glBindTexture(GL_TEXTURE_2D, m_texture);
 		glTexImage2D
-			(GL_TEXTURE_2D, 0, GL_RGBA, m_tex_w, m_tex_h, 0, GL_RGBA,
+			(GL_TEXTURE_2D, 0, GL_RGBA, m_w, m_h, 0, GL_RGBA,
 			 GL_UNSIGNED_BYTE,  m_pixels.get());
 	}
 
@@ -245,16 +195,16 @@
 }
 
 uint16_t GLSurfaceTexture::get_pitch() const {
-	return 4 * m_tex_w;
+	return 4 * m_w;
 }
 
-void GLSurfaceTexture::draw_rect(const Rect& rc, const RGBColor clr)
+void GLSurfaceTexture::draw_rect(const Rect& rectangle, const RGBColor& clr)
 {
 	if (m_w <= 0 || m_h <= 0) {
 		return;
 	}
-	setup_gl();
-	GLSurface::draw_rect(rc, clr);
+	setup_gl(m_texture);
+	GLSurface::draw_rect(rectangle, clr);
 	reset_gl();
 }
 
@@ -262,26 +212,28 @@
 /**
  * Draws a filled rectangle
  */
-void GLSurfaceTexture::fill_rect(const Rect& rc, const RGBAColor clr)
+void GLSurfaceTexture::fill_rect(const Rect& rectangle, const RGBAColor& clr)
 {
 	if (m_w <= 0 || m_h <= 0) {
 		return;
 	}
-	setup_gl();
-	GLSurface::fill_rect(rc, clr);
+
+	setup_gl(m_texture);
+	GLSurface::fill_rect(rectangle, clr);
 	reset_gl();
 }
 
 /**
  * Change the brightness of the given rectangle
  */
-void GLSurfaceTexture::brighten_rect(const Rect& rc, const int32_t factor)
+void GLSurfaceTexture::brighten_rect(const Rect& rectangle, const int32_t factor)
 {
 	if (m_w <= 0 || m_h <= 0) {
 		return;
 	}
-	setup_gl();
-	GLSurface::brighten_rect(rc, factor);
+
+	setup_gl(m_texture);
+	GLSurface::brighten_rect(rectangle, factor);
 	reset_gl();
 }
 
@@ -291,7 +243,8 @@
 	if (m_w <= 0 || m_h <= 0) {
 		return;
 	}
-	setup_gl();
+
+	setup_gl(m_texture);
 	GLSurface::draw_line(x1, y1, x2, y2, color, gwidth);
 	reset_gl();
 }
@@ -302,39 +255,8 @@
 	if (m_w <= 0 || m_h <= 0) {
 		return;
 	}
-	setup_gl();
+
+	setup_gl(m_texture);
 	GLSurface::blit(dst, src, srcrc, cm);
 	reset_gl();
 }
-
-void GLSurfaceTexture::setup_gl() {
-	if (use_arb_) {
-		glBindFramebuffer(GL_FRAMEBUFFER, gl_framebuffer_id_);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
-	} else {
-		glBindFramebufferEXT(GL_FRAMEBUFFER, gl_framebuffer_id_);
-		glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
-	}
-
-	// Note: we do not want to reverse y for textures, we only want this for
-	// the screen.
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	glLoadIdentity();
-	glOrtho(0, get_tex_w(), 0, get_tex_h(), -1, 1);
-
-	glPushAttrib(GL_VIEWPORT_BIT);
-	glViewport(0, 0, get_tex_w(), get_tex_h());
-}
-
-void GLSurfaceTexture::reset_gl() {
-	if (use_arb_)
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
-	else
-		glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
-
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-
-	glPopAttrib();
-}

=== modified file 'src/graphic/gl/surface_texture.h'
--- src/graphic/gl/surface_texture.h	2014-10-11 13:26:59 +0000
+++ src/graphic/gl/surface_texture.h	2014-11-08 16:26:16 +0000
@@ -25,11 +25,6 @@
 
 class GLSurfaceTexture : public GLSurface {
 public:
-	// Call this once before using any instance of this class and cleanup once
-	// before the program exits.
-	static void initialize(bool use_arb);
-	static void cleanup();
-
 	GLSurfaceTexture(SDL_Surface * surface, bool intensity = false);
 	GLSurfaceTexture(int w, int h);
 
@@ -49,28 +44,20 @@
 	// especially for blit which is called very often and mostly on the screen,
 	// this costs two virtual function calls which makes a notable difference in
 	// profiles.
-	void fill_rect(const Rect&, RGBAColor) override;
-	void draw_rect(const Rect&, RGBColor) override;
+	void fill_rect(const Rect&, const RGBAColor&) override;
+	void draw_rect(const Rect&, const RGBColor&) override;
 	void brighten_rect(const Rect&, int32_t factor) override;
 	virtual void draw_line
 		(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor&, uint8_t width) override;
 	void blit(const Point&, const Surface*, const Rect& srcrc, Composite cm) override;
 
 	GLuint get_gl_texture() const {return m_texture;}
-	uint16_t get_tex_w() const {return m_tex_w;}
-	uint16_t get_tex_h() const {return m_tex_h;}
 
 private:
+	void pixel_to_gl(float* x, float* y) override;
 	void init(uint16_t w, uint16_t h);
-	void setup_gl();
-	void reset_gl();
 
-	static GLuint gl_framebuffer_id_;
 	GLuint m_texture;
-
-	/// Keep the size of the opengl texture. This is necessary because some
-	/// systems support only a power of two for texture sizes.
-	uint16_t m_tex_w, m_tex_h;
 };
 
 #endif  // end of include guard: WL_GRAPHIC_GL_SURFACE_TEXTURE_H

=== added file 'src/graphic/gl/system_headers.h'
--- src/graphic/gl/system_headers.h	1970-01-01 00:00:00 +0000
+++ src/graphic/gl/system_headers.h	2014-11-08 16:26:16 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006-2014 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 WL_GRAPHIC_GL_SYSTEM_HEADERS_H
+#define WL_GRAPHIC_GL_SYSTEM_HEADERS_H
+
+// This includes the correct OpenGL headers for us. Use this instead of
+// including any system OpenGL headers yourself.
+
+// We do not want to include SDL_opengl.h because it defines the
+// fixed pipeline only which we do not want to use.
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <OpenGL/glext.h>
+#else
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <GL/gl.h>
+#include <GL/glext.h>
+#endif
+
+#endif  // end of include guard: WL_GRAPHIC_GL_SYSTEM_HEADERS_H

=== modified file 'src/graphic/gl/terrain_program.cc'
--- src/graphic/gl/terrain_program.cc	2014-11-01 19:51:53 +0000
+++ src/graphic/gl/terrain_program.cc	2014-11-08 16:26:16 +0000
@@ -129,8 +129,6 @@
 	glDisableVertexAttribArray(attr_position_);
 	glDisableVertexAttribArray(attr_texture_position_);
 	glDisableVertexAttribArray(attr_brightness_);
-
-	glUseProgram(0);
 }
 
 void TerrainProgram::draw(const DescriptionMaintainer<TerrainDescription>& terrains,

=== modified file 'src/graphic/gl/utils.h'
--- src/graphic/gl/utils.h	2014-09-27 18:53:55 +0000
+++ src/graphic/gl/utils.h	2014-11-08 16:26:16 +0000
@@ -19,15 +19,12 @@
 #ifndef WL_GRAPHIC_GL_UTILS_H
 #define WL_GRAPHIC_GL_UTILS_H
 
-#define NO_SDL_GLEXT
-
 #include <memory>
 
-#include <GL/glew.h>
-#include <SDL_opengl.h>
 #include <stdint.h>
 
 #include "base/macros.h"
+#include "graphic/gl/system_headers.h"
 
 struct SDL_PixelFormat;
 

=== modified file 'src/graphic/graphic.cc'
--- src/graphic/graphic.cc	2014-11-02 20:15:01 +0000
+++ src/graphic/graphic.cc	2014-11-08 16:26:16 +0000
@@ -100,10 +100,12 @@
 	if (opengl) {
 		log("Graphics: Trying opengl\n");
 
-		// TODO(sirver): We should explicitly request an OpenGL 2.? core context
-		// here instead of relying on SDL to give us whatever.
-
 		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+		// Request an OpenGL 2 context.
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+
 		flags |= SDL_WINDOW_OPENGL;
 	}
 
@@ -166,46 +168,10 @@
 	if (0 != (SDL_GetWindowFlags(m_sdlwindow) & SDL_WINDOW_FULLSCREEN))
 		log("Graphics: FULLSCREEN ENABLED\n");
 
-	bool use_arb = true;
-	const char * extensions = nullptr;
-
 	if (opengl && 0 != (SDL_GetWindowFlags(m_sdlwindow) & SDL_WINDOW_OPENGL)) {
 		//  We have successful opened an opengl screen. Print some information
 		//  about opengl and set the rendering capabilities.
 		log ("Graphics: OpenGL: OpenGL enabled\n");
-
-		// See http://stackoverflow.com/questions/13558073/program-crash-on-glgenvertexarrays-call for
-		// the next line.
-		glewExperimental = GL_TRUE;
-		GLenum err = glewInit();
-		if (err != GLEW_OK) {
-			log("glewInit returns %i\nYour OpenGL installation must be __very__ broken. %s\n",
-				 err, glewGetErrorString(err));
-			throw wexception("glewInit returns %i: Broken OpenGL installation.", err);
-		}
-
-		extensions = reinterpret_cast<const char *>(glGetString (GL_EXTENSIONS));
-
-		if (strstr(extensions, "GL_ARB_framebuffer_object") != nullptr) {
-			use_arb = true;
-		} else if (strstr(extensions, "GL_EXT_framebuffer_object") != nullptr) {
-			use_arb = false;
-		} else {
-			log
-			("Graphics: Neither GL_ARB_framebuffer_object or GL_EXT_framebuffer_object supported! "
-			"Switching off OpenGL!\n"
-			);
-			flags &= ~SDL_WINDOW_OPENGL;
-			m_fallback_settings_in_effect = true;
-			SDL_DestroyWindow(m_sdlwindow);
-			m_sdlwindow = SDL_CreateWindow("Widelands Window",
-													 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
-													 kFallbackGraphicsWidth, kFallbackGraphicsHeight, flags);
-			m_fallback_settings_in_effect = true;
-			if (!m_sdlwindow) {
-				throw wexception("Graphics: could not set video mode: %s", SDL_GetError());
-			}
-		}
 	}
 	Surface::display_format_is_now_defined();
 
@@ -214,44 +180,17 @@
 		//  We now really have a working opengl screen...
 		g_opengl = true;
 
+		log("Graphics: OpenGL: Version \"%s\"\n",
+		    reinterpret_cast<const char*>(glGetString(GL_VERSION)));
+
 		GLboolean glBool;
 		glGetBooleanv(GL_DOUBLEBUFFER, &glBool);
-		log
-			("Graphics: OpenGL: Double buffering %s\n",
-			 (glBool == GL_TRUE)?"enabled":"disabled");
+		log("Graphics: OpenGL: Double buffering %s\n", (glBool == GL_TRUE) ? "enabled" : "disabled");
 
 		GLint glInt;
 		glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glInt);
 		log("Graphics: OpenGL: Max texture size: %u\n", glInt);
-		m_caps.gl.tex_max_size = glInt;
-
-		glGetIntegerv(GL_AUX_BUFFERS, &glInt);
-		log("Graphics: OpenGL: Number of aux buffers: %u\n", glInt);
-		m_caps.gl.aux_buffers = glInt;
-
-		glGetIntegerv(GL_STENCIL_BITS, &glInt);
-		log("Graphics: OpenGL: Number of stencil buffer bits: %u\n", glInt);
-		m_caps.gl.stencil_buffer_bits = glInt;
-
-		const char * str = reinterpret_cast<const char *>(glGetString(GL_VERSION));
-		m_caps.gl.major_version = atoi(str);
-		m_caps.gl.minor_version = strstr(str, ".")?atoi(strstr(str, ".") + 1):0;
-		log
-			("Graphics: OpenGL: Version %d.%d \"%s\"\n",
-			 m_caps.gl.major_version, m_caps.gl.minor_version, str);
-
-		// extensions will be valid if we ever succeeded in runnning glewInit.
-		m_caps.gl.tex_power_of_two =
-			(m_caps.gl.major_version < 2) &&
-			(strstr(extensions, "GL_ARB_texture_non_power_of_two") == nullptr);
-		log("Graphics: OpenGL: Textures ");
-		log
-			(m_caps.gl.tex_power_of_two?"must have a size power of two\n":
-			 "may have any size\n");
-
-DIAG_OFF("-Wold-style-cast")
-		m_caps.gl.blendequation = GLEW_VERSION_1_4 || GLEW_ARB_imaging;
-DIAG_ON ("-Wold-style-cast")
+
 	}
 
 	/* Information about the video capabilities. */
@@ -297,14 +236,12 @@
 		glDisable(GL_DEPTH_TEST);
 		glDrawBuffer(GL_BACK);
 
-		// Clear the screen before running the game.
-		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 		SDL_GL_SetSwapInterval(1);
 		SDL_GL_SwapWindow(m_sdlwindow);
+
 		glEnable(GL_TEXTURE_2D);
-
-		GLSurfaceTexture::initialize(use_arb);
+		glEnable(GL_BLEND);
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 	}
 
 	if (g_opengl)
@@ -341,9 +278,6 @@
 	if (UI::g_fh)
 		UI::g_fh->flush();
 
-	if (g_opengl) {
-		GLSurfaceTexture::cleanup();
-	}
 	if (m_sdl_texture) {
 		SDL_DestroyTexture(m_sdl_texture);
 		m_sdl_texture = nullptr;

=== modified file 'src/graphic/graphic.h'
--- src/graphic/graphic.h	2014-11-02 20:15:01 +0000
+++ src/graphic/graphic.h	2014-11-08 16:26:16 +0000
@@ -39,35 +39,6 @@
 class StreamWrite;
 struct Texture;
 
-/// Stores the capabilities of opengl
-struct GLCaps
-{
-	/// The OpenGL major version
-	int major_version;
-	/// The OpenGL minor version
-	int minor_version;
-	/// The maximum texture size
-	int tex_max_size;
-	/// If true sizes of texture must be a power of two
-	bool tex_power_of_two;
-	/// How many bits the stencil buffer support
-	int stencil_buffer_bits;
-	/// How many Aux Buffers the opengl context support
-	int aux_buffers;
-	/// Whether the BlendEquation support is available
-	bool blendequation;
-};
-
-/**
- * A structure to store the capabilities of the current rendere. This is set
- * during init() and can be retrieved by g_gr->get_caps()
- */
-struct GraphicCaps
-{
-	/// The capabilities of the opengl hardware and drive
-	GLCaps gl;
-};
-
 /**
  * This class is a kind of Swiss Army knife for your graphics need. It
  * initializes the graphic system and provides access to resolutions. It has an
@@ -110,8 +81,6 @@
 
 	Surface& get_road_texture(int32_t roadtex);
 
-	const GraphicCaps& caps() const {return m_caps;}
-
 	bool check_fallback_settings_in_effect();
 
 private:
@@ -135,8 +104,6 @@
 	std::unique_ptr<RenderTarget> m_rendertarget;
 	/// This marks the complete screen for updating.
 	bool m_update;
-	/// stores which features the current renderer has
-	GraphicCaps m_caps;
 
 	/// Volatile cache of Hardware dependant surfaces.
 	std::unique_ptr<SurfaceCache> surface_cache_;

=== modified file 'src/graphic/rendertarget.h'
--- src/graphic/rendertarget.h	2014-07-05 16:41:51 +0000
+++ src/graphic/rendertarget.h	2014-11-08 16:26:16 +0000
@@ -64,9 +64,9 @@
 	void fill_rect(const Rect&, const RGBAColor&);
 	void brighten_rect(const Rect&, int32_t factor);
 
-	void blit(const Point& dst, const Image* image, Composite cm = CM_Normal, UI::Align = UI::Align_TopLeft);
-	void blitrect(const Point& dst, const Image* image, const Rect& src, Composite cm = CM_Normal);
-	void tile(const Rect&, const Image* image, const Point& ofs, Composite cm = CM_Normal);
+	void blit(const Point& dst, const Image* image, Composite cm = CM_UseAlpha, UI::Align = UI::Align_TopLeft);
+	void blitrect(const Point& dst, const Image* image, const Rect& src, Composite cm = CM_UseAlpha);
+	void tile(const Rect&, const Image* image, const Point& ofs, Composite cm = CM_UseAlpha);
 
 	void drawanim(const Point& dst, uint32_t animation, uint32_t time, const Widelands::Player* = 0);
 	void drawanimrect

=== modified file 'src/graphic/sdl/surface.cc'
--- src/graphic/sdl/surface.cc	2014-11-02 20:15:01 +0000
+++ src/graphic/sdl/surface.cc	2014-11-08 16:26:16 +0000
@@ -150,7 +150,7 @@
 Draws the outline of a rectangle
 ===============
 */
-void SDLSurface::draw_rect(const Rect& rc, const RGBColor clr) {
+void SDLSurface::draw_rect(const Rect& rc, const RGBColor& clr) {
 	assert(m_surface);
 	assert(rc.x >= 0);
 	assert(rc.y >= 0);
@@ -175,7 +175,7 @@
 Draws a filled rectangle
 ===============
 */
-void SDLSurface::fill_rect(const Rect& rc, const RGBAColor clr) {
+void SDLSurface::fill_rect(const Rect& rc, const RGBAColor& clr) {
 	assert(m_surface);
 	assert(rc.x >= 0);
 	assert(rc.y >= 0);
@@ -337,7 +337,7 @@
 
 	bool alpha = false;
 	uint8_t alphaval = 0;
-	if (cm == CM_Solid || cm == CM_Copy) {
+	if (cm == CM_Copy) {
 		SDL_BlendMode bm;
 		SDL_GetSurfaceBlendMode(sdlsurf, &bm);
 		alpha = bm & SDL_BLENDMODE_BLEND;
@@ -348,7 +348,7 @@
 
 	SDL_BlitSurface(sdlsurf, &srcrect, m_surface, &dstrect);
 
-	if (cm == CM_Solid || cm == CM_Copy) {
+	if (cm == CM_Copy) {
 		SDL_SetSurfaceAlphaMod(sdlsurf, alphaval);
 		SDL_SetSurfaceBlendMode(sdlsurf, alpha ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
 	}

=== modified file 'src/graphic/sdl/surface.h'
--- src/graphic/sdl/surface.h	2014-11-02 20:15:01 +0000
+++ src/graphic/sdl/surface.h	2014-11-08 16:26:16 +0000
@@ -45,10 +45,10 @@
 
 	// Implements Surface
 	void blit(const Point&, const Surface*, const Rect& srcrc, Composite cm) override;
-	void fill_rect(const Rect&, RGBAColor) override;
+	void fill_rect(const Rect&, const RGBAColor&) override;
 
 	// Implements Surface
-	void draw_rect(const Rect&, RGBColor) override;
+	void draw_rect(const Rect&, const RGBColor&) override;
 	virtual void draw_line
 		(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const RGBColor&, uint8_t width) override;
 	void brighten_rect(const Rect&, int32_t factor) override;

=== modified file 'src/graphic/sdl/utils.cc'
--- src/graphic/sdl/utils.cc	2014-09-27 18:53:55 +0000
+++ src/graphic/sdl/utils.cc	2014-11-08 16:26:16 +0000
@@ -24,24 +24,7 @@
 #include <SDL.h>
 
 SDL_Surface * empty_sdl_surface(int16_t w, int16_t h) {
-	SDL_Surface* surface;
-	uint32_t rmask, gmask, bmask, amask;
-	/* SDL interprets each pixel as a 32-bit number, so our masks must depend
-		on the endianness (byte order) of the machine */
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-	rmask = 0xff000000;
-	gmask = 0x00ff0000;
-	bmask = 0x0000ff00;
-	amask = 0x000000ff;
-#else
-	rmask = 0x000000ff;
-	gmask = 0x0000ff00;
-	bmask = 0x00ff0000;
-	amask = 0xff000000;
-#endif
-
-	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, rmask, gmask, bmask, amask);
-	assert(surface);
-
+	SDL_Surface* const surface =
+	   SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
 	return surface;
 }

=== modified file 'src/graphic/surface.h'
--- src/graphic/surface.h	2014-07-15 05:12:37 +0000
+++ src/graphic/surface.h	2014-11-08 16:26:16 +0000
@@ -53,13 +53,14 @@
 	virtual uint16_t height() const = 0;
 
 	/// This draws a part of another surface to this surface
-	virtual void blit(const Point&, const Surface*, const Rect& srcrc, Composite cm = CM_Normal) = 0;
+	virtual void blit(const Point&, const Surface*, const Rect& srcrc, Composite cm = CM_UseAlpha) = 0;
 
-	/// Draws a filled rect to the surface.
-	virtual void fill_rect(const Rect&, RGBAColor) = 0;
+	/// Draws a filled rect to the surface. No blending takes place, the values
+	//in the target are just replaced (i.e. / Composite would be CM_Copy).
+	virtual void fill_rect(const Rect&, const RGBAColor&) = 0;
 
 	/// Draws a rect (frame only) to the surface.
-	virtual void draw_rect(const Rect&, RGBColor) = 0;
+	virtual void draw_rect(const Rect&, const RGBColor&) = 0;
 
 	/// draw a line to the surface
 	virtual void draw_line

=== modified file 'src/graphic/text/rt_render.cc'
--- src/graphic/text/rt_render.cc	2014-09-14 11:31:58 +0000
+++ src/graphic/text/rt_render.cc	2014-11-08 16:26:16 +0000
@@ -361,7 +361,7 @@
 	Surface* rv = Surface::create(m_w, m_h);
 	for (uint16_t curx = 0; curx < m_w; curx += t.width()) {
 		Rect srcrect(Point(0, 0), min<int>(t.width(), m_w - curx), m_h);
-		rv->blit(Point(curx, 0), &t, srcrect, CM_Solid);
+		rv->blit(Point(curx, 0), &t, srcrect, CM_Copy);
 	}
 	return rv;
 }
@@ -430,7 +430,7 @@
 				dst.y = 0;
 				srcrect.w = min<int>(m_bg->width(), m_w - curx);
 				srcrect.h = m_h;
-				rv->blit(dst, m_bg->surface(), srcrect, CM_Solid);
+				rv->blit(dst, m_bg->surface(), srcrect, CM_Copy);
 			}
 		} else {
 			rv->fill_rect(Rect(0, 0, m_w, m_h), RGBAColor(255, 255, 255, 0));
@@ -490,7 +490,7 @@
 					dst.x = curx; dst.y = cury;
 					src.w = min<int>(m_bg_img->width(), m_w + m_margin.left - curx);
 					src.h = min<int>(m_bg_img->height(), m_h + m_margin.top - cury);
-					rv->blit(dst, m_bg_img->surface(), src, CM_Solid);
+					rv->blit(dst, m_bg_img->surface(), src, CM_Copy);
 				}
 			}
 			set_alpha = false;
@@ -502,7 +502,7 @@
 				Point dst = Point(n->x() + m_margin.left, n->y() + m_margin.top);
 				Rect src = Rect(0, 0, nsur->width(), nsur->height());
 
-				rv->blit(dst, nsur, src, set_alpha ? CM_Solid : CM_Normal);
+				rv->blit(dst, nsur, src, set_alpha ? CM_Copy : CM_UseAlpha);
 				delete nsur;
 			}
 			delete n;

=== modified file 'src/logic/building.cc'
--- src/logic/building.cc	2014-09-20 09:37:47 +0000
+++ src/logic/building.cc	2014-11-08 16:26:16 +0000
@@ -732,7 +732,7 @@
 	if (dpyflags & InteractiveBase::dfShowCensus) {
 		const std::string info = info_string(igbase.building_census_format());
 		if (!info.empty()) {
-			dst.blit(pos - Point(0, 48), UI::g_fh1->render(info), CM_Normal, UI::Align_Center);
+			dst.blit(pos - Point(0, 48), UI::g_fh1->render(info), CM_UseAlpha, UI::Align_Center);
 		}
 	}
 
@@ -744,7 +744,7 @@
 				return;
 		const std::string info = info_string(igbase.building_statistics_format());
 		if (!info.empty()) {
-			dst.blit(pos - Point(0, 35), UI::g_fh1->render(info), CM_Normal, UI::Align_Center);
+			dst.blit(pos - Point(0, 35), UI::g_fh1->render(info), CM_UseAlpha, UI::Align_Center);
 		}
 	}
 }

=== modified file 'src/logic/immovable.cc'
--- src/logic/immovable.cc	2014-09-20 09:37:47 +0000
+++ src/logic/immovable.cc	2014-11-08 16:26:16 +0000
@@ -570,7 +570,7 @@
 			 % UI_FONT_CLR_DARK_HEX % (boost::format(_("%i%% built")) % percent).str())
 			 .str();
 		m_construct_string = as_uifont(m_construct_string);
-		dst.blit(pos - Point(0, 48), UI::g_fh1->render(m_construct_string), CM_Normal, UI::Align_Center);
+		dst.blit(pos - Point(0, 48), UI::g_fh1->render(m_construct_string), CM_UseAlpha, UI::Align_Center);
 	}
 }
 

=== modified file 'src/ui_basic/button.cc'
--- src/ui_basic/button.cc	2014-10-14 06:30:20 +0000
+++ src/ui_basic/button.cc	2014-11-08 16:26:16 +0000
@@ -253,7 +253,6 @@
 			dst.fill_rect(Rect(Point(0, 2), 2, get_h() - 2), shade);
 			dst.fill_rect(Rect(Point(0, get_h() - 2), get_w(), get_h()), shade);
 			dst.fill_rect(Rect(Point(get_w() - 2, 0), get_w(), get_h()), shade);
-			//dst.draw_rect(Rect(Point(0, 0), get_w(), get_h()), m_clr_down);
 		}
 	}
 }

=== modified file 'src/ui_basic/checkbox.cc'
--- src/ui_basic/checkbox.cc	2014-07-20 07:46:24 +0000
+++ src/ui_basic/checkbox.cc	2014-11-08 16:26:16 +0000
@@ -101,19 +101,18 @@
 {
 	if (m_flags & Has_Custom_Picture) {
 		// center picture
-		uint16_t w = m_pic_graphics->width();
-		uint16_t h = m_pic_graphics->height();
-
-		dst.blit
-			(Point((get_inner_w() - w) / 2, (get_inner_h() - h) / 2),
-			 m_pic_graphics);
-
-		if (m_flags & Is_Checked)
+		const uint16_t w = m_pic_graphics->width();
+		const uint16_t h = m_pic_graphics->height();
+
+		dst.blit(Point((get_inner_w() - w) / 2, (get_inner_h() - h) / 2), m_pic_graphics);
+
+		if (m_flags & Is_Checked) {
 			dst.draw_rect
 				(Rect(Point(0, 0), get_w(), get_h()), RGBColor(229, 116,   2));
-		else if (m_flags & Is_Highlighted)
+		} else if (m_flags & Is_Highlighted) {
 			dst.draw_rect
 				(Rect(Point(0, 0), get_w(), get_h()), RGBColor(100, 100,  80));
+		}
 	} else {
 		static_assert(0 <= STATEBOX_WIDTH, "assert(0 <= STATEBOX_WIDTH) failed.");
 		static_assert(0 <= STATEBOX_HEIGHT, "assert(0 <= STATEBOX_HEIGHT) failed.");

=== modified file 'src/ui_basic/progressbar.cc'
--- src/ui_basic/progressbar.cc	2014-09-10 14:48:40 +0000
+++ src/ui_basic/progressbar.cc	2014-11-08 16:26:16 +0000
@@ -109,6 +109,6 @@
 	const std::string progress_text =
 		(boost::format("<font color=%1$s>%2$i%%</font>") % "ffffff" % percent).str();
 	const Point pos(get_w() / 2, get_h() / 2);
-	dst.blit(pos, UI::g_fh1->render(as_uifont(progress_text)), CM_Normal, Align_Center);
+	dst.blit(pos, UI::g_fh1->render(as_uifont(progress_text)), CM_UseAlpha, Align_Center);
 }
 }

=== modified file 'src/ui_basic/window.cc'
--- src/ui_basic/window.cc	2014-10-14 06:30:20 +0000
+++ src/ui_basic/window.cc	2014-11-08 16:26:16 +0000
@@ -321,7 +321,7 @@
 		dst.blit
 			(Point(get_lborder() + get_inner_w() / 2, TP_B_PIXMAP_THICKNESS / 2),
 				UI::g_fh1->render(m_title),
-				CM_Normal,
+				CM_UseAlpha,
 				Align_Center);
 	}
 

=== modified file 'src/wlapplication.cc'
--- src/wlapplication.cc	2014-11-04 12:33:12 +0000
+++ src/wlapplication.cc	2014-11-08 16:26:16 +0000
@@ -505,10 +505,8 @@
 		switch (ev.type) {
 		case SDL_KEYDOWN:
 		case SDL_KEYUP:
-			if
-				(ev.key.keysym.scancode	 == SDL_SCANCODE_F10 &&
-				 (get_key_state(SDL_SCANCODE_LCTRL) || get_key_state(SDL_SCANCODE_RCTRL)))
-			{
+			if (ev.key.keysym.scancode == SDL_SCANCODE_F10 &&
+			    (get_key_state(SDL_SCANCODE_LCTRL) || get_key_state(SDL_SCANCODE_RCTRL))) {
 				//  get out of here quick
 				if (ev.type == SDL_KEYDOWN)
 					m_should_die = true;

=== modified file 'src/wui/buildingwindow.cc'
--- src/wui/buildingwindow.cc	2014-10-28 12:53:29 +0000
+++ src/wui/buildingwindow.cc	2014-11-08 16:26:16 +0000
@@ -119,7 +119,7 @@
 
 	const Image* dark_frame = ImageTransformations::change_luminosity
 		(&anim.representative_image(building().owner().get_playercolor()), 1.22, true);
-	dst.blit(Point(get_inner_w() / 2, get_inner_h() / 2), dark_frame, CM_Normal, UI::Align_Center);
+	dst.blit(Point(get_inner_w() / 2, get_inner_h() / 2), dark_frame, CM_UseAlpha, UI::Align_Center);
 }
 
 /*

=== modified file 'src/wui/interactive_base.cc'
--- src/wui/interactive_base.cc	2014-11-04 12:33:12 +0000
+++ src/wui/interactive_base.cc	2014-11-08 16:26:16 +0000
@@ -413,7 +413,7 @@
 	if (get_display_flag(dfDebug) || !dynamic_cast<const Game*>(&egbase())) {
 		const std::string gametime(gametimestring(egbase().get_gametime()));
 		const std::string gametime_text = as_uifont(gametime, UI_FONT_SIZE_SMALL);
-		dst.blit(Point(5, 5), UI::g_fh1->render(gametime_text), CM_Normal, UI::Align_TopLeft);
+		dst.blit(Point(5, 5), UI::g_fh1->render(gametime_text), CM_UseAlpha, UI::Align_TopLeft);
 		static boost::format node_format("(%i, %i)");
 
 		const std::string node_text = as_uifont
@@ -421,7 +421,7 @@
 		dst.blit(
 			Point(get_w() - 5, get_h() - 5),
 			UI::g_fh1->render(node_text),
-			CM_Normal,
+			CM_UseAlpha,
 			UI::Align_BottomRight
 		);
 	}
@@ -433,7 +433,7 @@
 			((fps_format %
 			  (1000.0 / m_frametime) % (1000.0 / (m_avg_usframetime / 1000)))
 			 .str(), UI_FONT_SIZE_SMALL);
-		dst.blit(Point(5, 25), UI::g_fh1->render(fps_text), CM_Normal, UI::Align_Left);
+		dst.blit(Point(5, 25), UI::g_fh1->render(fps_text), CM_UseAlpha, UI::Align_Left);
 	}
 }
 

=== modified file 'src/wui/plot_area.cc'
--- src/wui/plot_area.cc	2014-10-27 08:06:06 +0000
+++ src/wui/plot_area.cc	2014-11-08 16:26:16 +0000
@@ -142,7 +142,7 @@
  */
 void draw_value(const string& value, const RGBColor& color, const Point& pos, RenderTarget & dst) {
 	const Image* pic = UI::g_fh1->render(ytick_text_style(value, color));
-	dst.blit(pos, pic, CM_Normal, UI::Align_CenterRight);
+	dst.blit(pos, pic, CM_UseAlpha, UI::Align_CenterRight);
 }
 
 /**
@@ -223,7 +223,7 @@
 			(xtick_text_style((boost::format("-%u ") % (max_x / how_many_ticks * i)).str()));
 		dst.blit
 			(Point(static_cast<int32_t>(posx), inner_h - space_at_bottom + 10),
-			 xtick, CM_Normal, UI::Align_Center);
+			 xtick, CM_UseAlpha, UI::Align_Center);
 
 		posx -= sub;
 	}
@@ -242,7 +242,7 @@
 
 	//  print the used unit
 	const Image* xtick = UI::g_fh1->render(xtick_text_style(get_unit_name(unit)));
-	dst.blit(Point(2, spacing + 2), xtick, CM_Normal, UI::Align_CenterLeft);
+	dst.blit(Point(2, spacing + 2), xtick, CM_UseAlpha, UI::Align_CenterLeft);
 }
 
 }  // namespace
@@ -515,7 +515,7 @@
 	const uint32_t time_ms = get_plot_time();
 	draw_diagram(time_ms, get_inner_w(), get_inner_h(), xline_length, dst);
 
-	//draw zero line
+	// draw zero line
 	dst.draw_line
 		(get_inner_w() - space_at_right,
 		 yoffset,


Follow ups