shithub: cstory

Download patch

ref: 4cbc56e272c4e90348cdfd7ab88edf243d881df1
parent: 0352af333bbf52f59cde973dfe489b8f57b98eef
author: Clownacy <[email protected]>
date: Mon Jan 20 08:13:56 EST 2020

Add OpenGL ES 2.0 renderer

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,7 +14,7 @@
 option(JAPANESE "Enable the Japanese-language build (instead of the unofficial Aeon Genesis English translation)" OFF)
 option(FIX_BUGS "Fix various bugs in the game" OFF)
 option(DEBUG_SAVE "Re-enable the ability to drag-and-drop save files onto the window" OFF)
-set(RENDERER "SDLTexture" CACHE STRING "Which renderer the game should use: 'OpenGL3' for an OpenGL 3.2 renderer, 'SDLTexture' for SDL2's hardware-accelerated Texture API, 'SDLSurface' for SDL2's software-rendered Surface API, or 'Software' for a handwritten software renderer")
+set(RENDERER "SDLTexture" CACHE STRING "Which renderer the game should use: 'OpenGL3' for an OpenGL 3.2 renderer, 'OpenGLES2' for an OpenGL ES 2.0 renderer, 'SDLTexture' for SDL2's hardware-accelerated Texture API, 'SDLSurface' for SDL2's software-rendered Surface API, or 'Software' for a handwritten software renderer")
 
 option(WARNINGS "Enable common compiler warnings (for GCC-compatible compilers and MSVC only)" OFF)
 option(WARNINGS_ALL "Enable ALL compiler warnings (for Clang and MSVC only)" OFF)
@@ -337,6 +337,8 @@
 
 if(RENDERER MATCHES "OpenGL3")
 	target_sources(CSE2 PRIVATE "src/Backends/Rendering/OpenGL3.cpp")
+elseif(RENDERER MATCHES "OpenGLES2")
+	target_sources(CSE2 PRIVATE "src/Backends/Rendering/OpenGLES2.cpp")
 elseif(RENDERER MATCHES "SDLTexture")
 	target_sources(CSE2 PRIVATE "src/Backends/Rendering/SDLTexture.cpp")
 elseif(RENDERER MATCHES "SDLSurface")
@@ -502,6 +504,12 @@
 
 	find_package(OpenGL REQUIRED)
 	target_link_libraries(CSE2 OpenGL::GL)
+endif()
+
+if(RENDERER MATCHES "OpenGLES2")
+	find_package(OpenGLES2 REQUIRED)
+	target_include_directories(CSE2 PRIVATE ${OPENGLES2_INCLUDE_DIR})
+	target_link_libraries(CSE2 ${OPENGLES2_LIBRARIES})
 endif()
 
 ##
--- a/Makefile
+++ b/Makefile
@@ -243,6 +243,11 @@
   else
     CSE2_LIBS += -lGL -ldl
   endif
+else ifeq ($(RENDERER), OpenGLES2)
+  SOURCES += src/Backends/Rendering/OpenGLES2.cpp
+  CSE2_CFLAGS += $(shell $(PKGCONFIG) --cflags glesv2)
+  CSE2_CXXFLAGS += $(shell $(PKGCONFIG) --cflags glesv2)
+  CSE2_LIBS += $(shell $(PKGCONFIG) --libs glesv2)
 else ifeq ($(RENDERER), SDLTexture)
   SOURCES += src/Backends/Rendering/SDLTexture.cpp
 else ifeq ($(RENDERER), SDLSurface)
--- a/README.md
+++ b/README.md
@@ -64,6 +64,7 @@
 `-DFIX_BUGS=ON` | Fix various bugs in the game
 `-DDEBUG_SAVE=ON` | Re-enable the ability to drag-and-drop save files onto the window
 `-DRENDERER=OpenGL3` | Use the hardware-accelerated OpenGL 3.2 renderer
+`-DRENDERER=OpenGLES2` | Use the hardware-accelerated OpenGL ES 2.0 renderer
 `-DRENDERER=SDLTexture` | Use the hardware-accelerated SDL2 Texture API renderer (default)
 `-DRENDERER=SDLSurface` | Use the software-rendered SDL2 Surface API renderer
 `-DRENDERER=Software` | Use the handwritten software renderer
@@ -97,6 +98,7 @@
 `WINDOWS=1` | Build for Windows
 `DEBUG_SAVE=1` | Re-enable the ability to drag-and-drop save files onto the window
 `RENDERER=OpenGL3` | Use the hardware-accelerated OpenGL 3.2 renderer
+`RENDERER=OpenGLES2` | Use the hardware-accelerated OpenGL ES 2.0 renderer
 `RENDERER=SDLTexture` | Use the hardware-accelerated SDL2 Texture API renderer (default)
 `RENDERER=SDLSurface` | Use the software-rendered SDL2 Surface API renderer
 `RENDERER=Software` | Use the hand-written software renderer
--- /dev/null
+++ b/cmake/FindOpenGLES2.cmake
@@ -1,0 +1,120 @@
+#-------------------------------------------------------------------
+# This file is stolen from part of the CMake build system for OGRE (Object-oriented Graphics Rendering Engine) http://www.ogre3d.org/
+#
+# The contents of this file are placed in the public domain. Feel
+# free to make use of it in any way you like.
+#-------------------------------------------------------------------
+
+# - Try to find OpenGLES and EGL
+# Once done this will define
+#
+#  OPENGLES2_FOUND        - system has OpenGLES
+#  OPENGLES2_INCLUDE_DIR  - the GL include directory
+#  OPENGLES2_LIBRARIES    - Link these to use OpenGLES
+#
+#  EGL_FOUND        - system has EGL
+#  EGL_INCLUDE_DIR  - the EGL include directory
+#  EGL_LIBRARIES    - Link these to use EGL
+
+# Win32, Apple, and Android are not tested!
+# Linux tested and works
+
+if(WIN32)
+	if(CYGWIN)
+		find_path(OPENGLES2_INCLUDE_DIR GLES2/gl2.h)
+		find_library(OPENGLES2_LIBRARY libGLESv2)
+	else()
+		if(BORLAND)
+			set(OPENGLES2_LIBRARY import32 CACHE STRING "OpenGL ES 2.x library for Win32")
+		else()
+			# TODO
+			# set(OPENGLES_LIBRARY ${SOURCE_DIR}/Dependencies/lib/release/libGLESv2.lib CACHE STRING "OpenGL ES 2.x library for win32"
+		endif()
+	endif()
+elseif(APPLE)
+	create_search_paths(/Developer/Platforms)
+	findpkg_framework(OpenGLES2)
+	set(OPENGLES2_LIBRARY "-framework OpenGLES")
+else()
+	find_path(OPENGLES2_INCLUDE_DIR GLES2/gl2.h
+		PATHS /usr/openwin/share/include
+			/opt/graphics/OpenGL/include
+			/opt/vc/include
+			/usr/X11R6/include
+			/usr/include
+	)
+
+	find_library(OPENGLES2_LIBRARY
+		NAMES GLESv2
+		PATHS /opt/graphics/OpenGL/lib
+			/usr/openwin/lib
+			/usr/shlib /usr/X11R6/lib
+			/opt/vc/lib
+			/usr/lib/aarch64-linux-gnu
+			/usr/lib/arm-linux-gnueabihf
+			/usr/lib
+	)
+
+	if(NOT BUILD_ANDROID)
+		find_path(EGL_INCLUDE_DIR EGL/egl.h
+			PATHS /usr/openwin/share/include
+				/opt/graphics/OpenGL/include
+				/opt/vc/include
+				/usr/X11R6/include
+				/usr/include
+		)
+
+		find_library(EGL_LIBRARY
+			NAMES EGL
+			PATHS /opt/graphics/OpenGL/lib
+				/usr/openwin/lib
+				/usr/shlib
+				/usr/X11R6/lib
+				/opt/vc/lib
+				/usr/lib/aarch64-linux-gnu
+				/usr/lib/arm-linux-gnueabihf
+				/usr/lib
+		)
+
+		# On Unix OpenGL usually requires X11.
+		# It doesn't require X11 on OSX.
+
+		if(OPENGLES2_LIBRARY)
+			if(NOT X11_FOUND)
+				include(FindX11)
+			endif()
+			if(X11_FOUND)
+				set(OPENGLES2_LIBRARIES ${X11_LIBRARIES})
+			endif()
+		endif()
+	endif()
+endif()
+
+set(OPENGLES2_LIBRARIES ${OPENGLES2_LIBRARIES} ${OPENGLES2_LIBRARY})
+
+if(BUILD_ANDROID)
+	if(OPENGLES2_LIBRARY)
+		set(EGL_LIBRARIES)
+		set(OPENGLES2_FOUND TRUE)
+	endif()
+else()
+	if(OPENGLES2_LIBRARY AND EGL_LIBRARY)
+		set(OPENGLES2_LIBRARIES ${OPENGLES2_LIBRARY} ${OPENGLES2_LIBRARIES})
+		set(EGL_LIBRARIES ${EGL_LIBRARY} ${EGL_LIBRARIES})
+		set(OPENGLES2_FOUND TRUE)
+	endif()
+endif()
+
+mark_as_advanced(
+	OPENGLES2_INCLUDE_DIR
+	OPENGLES2_LIBRARY
+	EGL_INCLUDE_DIR
+	EGL_LIBRARY
+)
+
+if(OPENGLES2_FOUND)
+	message(STATUS "Found system OpenGL ES 2 library: ${OPENGLES2_LIBRARIES}")
+else()
+	set(OPENGLES2_LIBRARIES "")
+endif()
+
--- a/src/Backends/Rendering/OpenGL3.cpp
+++ b/src/Backends/Rendering/OpenGL3.cpp
@@ -1,3 +1,5 @@
+// Dual OpenGL 3.2 and OpenGL ES 2.0 renderer
+
 #include "../Rendering.h"
 
 #include <stddef.h>
@@ -5,7 +7,12 @@
 #include <stdlib.h>
 #include <string.h>
 
+#ifdef USE_OPENGLES2
+#include <GLES2/gl2.h>
+#else
 #include <glad/glad.h>
+#endif
+
 #include "SDL.h"
 
 #include "../../WindowsWrapper.h"
@@ -67,7 +74,9 @@
 static GLint program_glyph_normal_uniform_colour;
 static GLint program_glyph_subpixel_part2_uniform_colour;
 
+#ifndef USE_OPENGLES2
 static GLuint vertex_array_id;
+#endif
 static GLuint vertex_buffer_id;
 static GLuint framebuffer_id;
 
@@ -78,7 +87,101 @@
 
 static Backend_Surface framebuffer;
 
+#ifdef USE_OPENGLES2
 static const GLchar *vertex_shader_plain = " \
+#version 100\n \
+attribute vec2 input_vertex_coordinates; \
+void main() \
+{ \
+	gl_Position = vec4(input_vertex_coordinates.x, input_vertex_coordinates.y, 0.0, 1.0); \
+} \
+";
+
+static const GLchar *vertex_shader_texture = " \
+#version 100\n \
+attribute vec2 input_vertex_coordinates; \
+attribute vec2 input_texture_coordinates; \
+varying vec2 texture_coordinates; \
+void main() \
+{ \
+	texture_coordinates = input_texture_coordinates; \
+	gl_Position = vec4(input_vertex_coordinates.x, input_vertex_coordinates.y, 0.0, 1.0); \
+} \
+";
+
+static const GLchar *fragment_shader_texture = " \
+#version 100\n \
+precision mediump float; \
+uniform sampler2D tex; \
+varying vec2 texture_coordinates; \
+void main() \
+{ \
+	gl_FragColor = texture2D(tex, texture_coordinates); \
+} \
+";
+
+static const GLchar *fragment_shader_texture_colour_key = " \
+#version 100\n \
+precision mediump float; \
+uniform sampler2D tex; \
+varying vec2 texture_coordinates; \
+void main() \
+{ \
+	vec4 colour = texture2D(tex, texture_coordinates); \
+\
+	if (colour.xyz == vec3(0.0f, 0.0f, 0.0f)) \
+		discard; \
+\
+	gl_FragColor = colour; \
+} \
+";
+
+static const GLchar *fragment_shader_colour_fill = " \
+#version 100\n \
+precision mediump float; \
+uniform vec4 colour; \
+void main() \
+{ \
+	gl_FragColor = colour; \
+} \
+";
+
+static const GLchar *fragment_shader_glyph_normal = " \
+#version 100\n \
+precision mediump float; \
+uniform sampler2D tex; \
+uniform vec4 colour; \
+varying vec2 texture_coordinates; \
+void main() \
+{ \
+	gl_FragColor = colour * vec4(1.0, 1.0, 1.0, texture2D(tex, texture_coordinates).r); \
+} \
+";
+
+static const GLchar *fragment_shader_glyph_subpixel_part1 = " \
+#version 100\n \
+precision mediump float; \
+uniform sampler2D tex; \
+varying vec2 texture_coordinates; \
+void main() \
+{ \
+	gl_FragColor = texture2D(tex, texture_coordinates); \
+} \
+";
+
+static const GLchar *fragment_shader_glyph_subpixel_part2 = " \
+#version 100\n \
+precision mediump float; \
+uniform sampler2D tex; \
+uniform vec4 colour; \
+varying vec2 texture_coordinates; \
+void main() \
+{ \
+	gl_FragColor = colour * texture2D(tex, texture_coordinates); \
+} \
+";
+#else
+static const GLchar *vertex_shader_plain = " \
 #version 150 core\n \
 in vec2 input_vertex_coordinates; \
 void main() \
@@ -170,6 +273,7 @@
 	fragment = colour * texture(tex, texture_coordinates); \
 } \
 ";
+#endif
 /*
 static void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void* userParam)
 {
@@ -195,7 +299,12 @@
 
 	glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &shader_status);
 	if (shader_status != GL_TRUE)
+	{
+		char buffer[0x200];
+		glGetShaderInfoLog(vertex_shader, sizeof(buffer), NULL, buffer);
+		printf("Vertex shader: %s", buffer);
 		return 0;
+	}
 
 	glAttachShader(program_id, vertex_shader);
 
@@ -205,7 +314,12 @@
 
 	glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &shader_status);
 	if (shader_status != GL_TRUE)
+	{
+		char buffer[0x200];
+		glGetShaderInfoLog(fragment_shader, sizeof(buffer), NULL, buffer);
+		printf("Fragment shader: %s", buffer);
 		return 0;
+	}
 
 	glAttachShader(program_id, fragment_shader);
 
@@ -216,7 +330,12 @@
 
 	glGetProgramiv(program_id, GL_LINK_STATUS, &shader_status);
 	if (shader_status != GL_TRUE)
+	{
+		char buffer[0x200];
+		glGetProgramInfoLog(program_id, sizeof(buffer), NULL, buffer);
+		printf("Shader linker: %s", buffer);
 		return 0;
+	}
 
 	return program_id;
 }
@@ -271,10 +390,17 @@
 
 SDL_Window* Backend_CreateWindow(const char *title, int width, int height)
 {
+#ifdef USE_OPENGLES2
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#else
 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+#endif
 
 	return SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
 }
@@ -292,11 +418,22 @@
 	{
 		if (SDL_GL_MakeCurrent(window, context) == 0)
 		{
+		#ifndef USE_OPENGLES2
 			if (gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
+		#endif
 			{
+			#ifndef USE_OPENGLES2
 				// Check if the platform supports OpenGL 3.2
 				if (GLAD_GL_VERSION_3_2)
+			#endif
 				{
+				#ifndef NDEBUG
+					printf("GL_VENDOR = %s\n", glGetString(GL_VENDOR));
+					printf("GL_RENDERER = %s\n", glGetString(GL_RENDERER));
+					printf("GL_VERSION = %s\n", glGetString(GL_VERSION));
+					printf("GL_SHADING_LANGUAGE_VERSION = %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
+				#endif
+
 					//glEnable(GL_DEBUG_OUTPUT);
 					//glDebugMessageCallback(MessageCallback, 0);
 
@@ -303,9 +440,11 @@
 					glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 					glClear(GL_COLOR_BUFFER_BIT);
 
+				#ifndef USE_OPENGLES2
 					// Set up Vertex Array Object
 					glGenVertexArrays(1, &vertex_array_id);
 					glBindVertexArray(vertex_array_id);
+				#endif
 
 					// Set up Vertex Buffer Object
 					glGenBuffers(1, &vertex_buffer_id);
@@ -343,12 +482,18 @@
 						// Set up framebuffer screen texture (used for screen-to-surface blitting)
 						glGenTextures(1, &framebuffer.texture_id);
 						glBindTexture(GL_TEXTURE_2D, framebuffer.texture_id);
+					#ifdef USE_OPENGLES2
+						glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window_width, window_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+					#else
 						glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, window_width, window_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+					#endif
 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+					#ifndef USE_OPENGLES2
 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+					#endif
 
 						framebuffer.width = window_width;
 						framebuffer.height = window_height;
@@ -378,7 +523,9 @@
 						glDeleteProgram(program_texture);
 
 					glDeleteBuffers(1, &vertex_buffer_id);
+				#ifndef USE_OPENGLES2
 					glDeleteVertexArrays(1, &vertex_array_id);
+				#endif
 				}
 			}
 		}
@@ -400,7 +547,9 @@
 	glDeleteProgram(program_texture_colour_key);
 	glDeleteProgram(program_texture);
 	glDeleteBuffers(1, &vertex_buffer_id);
+#ifndef USE_OPENGLES2
 	glDeleteVertexArrays(1, &vertex_array_id);
+#endif
 	SDL_GL_DeleteContext(context);
 }
 
@@ -475,12 +624,18 @@
 
 	glGenTextures(1, &surface->texture_id);
 	glBindTexture(GL_TEXTURE_2D, surface->texture_id);
+#ifdef USE_OPENGLES2
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+#else
 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+#endif
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#ifndef USE_OPENGLES2
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+#endif
 
 	surface->width = width;
 	surface->height = height;
@@ -684,7 +839,11 @@
 	if (glyph == NULL)
 		return NULL;
 
+#ifdef USE_OPENGLES2
+	const unsigned int destination_pitch = ((width * 3) + 3) & ~3;	// Round up to the nearest 4 (OpenGL needs this)
+#else
 	const unsigned int destination_pitch = (width + 3) & ~3;	// Round up to the nearest 4 (OpenGL needs this)
+#endif
 
 	unsigned char *buffer = (unsigned char*)malloc(destination_pitch * height);
 
@@ -691,12 +850,31 @@
 	switch (pixel_mode)
 	{
 		case FONT_PIXEL_MODE_LCD:
+			for (unsigned int y = 0; y < height; ++y)
+			{
+				const unsigned char *source_pointer = pixels + y * pitch;
+				unsigned char *destination_pointer = buffer + y * destination_pitch;
+				memcpy(destination_pointer, source_pointer, width);
+			}
+
+			break;
+
 		case FONT_PIXEL_MODE_GRAY:
 			for (unsigned int y = 0; y < height; ++y)
 			{
 				const unsigned char *source_pointer = pixels + y * pitch;
 				unsigned char *destination_pointer = buffer + y * destination_pitch;
+
+			#ifdef USE_OPENGLES2
+				for (unsigned int x = 0; x < width; ++x)
+				{
+					*destination_pointer++ = *source_pointer++;
+					*destination_pointer++ = 0;
+					*destination_pointer++ = 0;
+				}
+			#else
 				memcpy(destination_pointer, source_pointer, width);
+			#endif
 			}
 
 			break;
@@ -708,7 +886,13 @@
 				unsigned char *destination_pointer = buffer + y * destination_pitch;
 
 				for (unsigned int x = 0; x < width; ++x)
+				{
 					*destination_pointer++ = (*source_pointer++ ? 0xFF : 0);
+				#ifdef USE_OPENGLES2
+					*destination_pointer++ = 0;
+					*destination_pointer++ = 0;
+				#endif
+				}
 			}
 
 			break;
@@ -719,15 +903,25 @@
 
 	glGenTextures(1, &glyph->texture_id);
 	glBindTexture(GL_TEXTURE_2D, glyph->texture_id);
+#ifdef USE_OPENGLES2
 	if (pixel_mode == FONT_PIXEL_MODE_LCD)
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width / 3, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+	else
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);	// OpenGL ES 2.0 doesn't support GL_RED
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+#else
+	if (pixel_mode == FONT_PIXEL_MODE_LCD)
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width / 3, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
 	else
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, buffer);
+#endif
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#ifndef USE_OPENGLES2
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+#endif
 
 	glyph->width = (pixel_mode == FONT_PIXEL_MODE_LCD ? width / 3 : width);
 	glyph->height = height;
--- /dev/null
+++ b/src/Backends/Rendering/OpenGLES2.cpp
@@ -1,0 +1,4 @@
+// I would use -DUSE_OPENGLES2 when RENDERER=OpenGLES2 is passed instead, but CMake likes to rebuild the entire
+// project if I do that, and Make doesn't bother rebuilding anything at all. This method avoid both of those problems.
+#define USE_OPENGLES2
+#include "OpenGL3.cpp"