changeset 1658:fa9ae059e4d3

Added support for GLES in addition to desktop GL
author Mike Pavone <pavone@retrodev.com>
date Sun, 30 Dec 2018 21:10:44 -0800
parents 774096402918
children 19331a21da3a
files Makefile nuklear_ui/blastem_nuklear.c nuklear_ui/nuklear_sdl_gles2.h render_sdl.c shaders/default.f.glsl shaders/default.v.glsl
diffstat 6 files changed, 98 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun Dec 30 19:40:32 2018 -0800
+++ b/Makefile	Sun Dec 30 21:10:44 2018 -0800
@@ -31,23 +31,36 @@
 NET:=net.o
 EXE:=
 
+HAS_PROC:=$(shell if [ -d /proc ]; then /bin/echo -e -DHAS_PROC; fi)
+CFLAGS:=-std=gnu99 -Wreturn-type -Werror=return-type -Werror=implicit-function-declaration -Wno-unused-value $(HAS_PROC) -DHAVE_UNISTD_H
+
 ifeq ($(OS),Darwin)
 LIBS=sdl2 glew
 FONT:=nuklear_ui/font_mac.o
 else
+ifdef USE_GLES
+LIBS=sdl2 glesv2
+CFLAGS+= -DUSE_GLES
+else
 LIBS=sdl2 glew gl
+endif #USE_GLES
 FONT:=nuklear_ui/font.o
 endif #Darwin
 
-HAS_PROC:=$(shell if [ -d /proc ]; then /bin/echo -e -DHAS_PROC; fi)
-CFLAGS:=-std=gnu99 -Wreturn-type -Werror=return-type -Werror=implicit-function-declaration -Wno-unused-value $(HAS_PROC) -DHAVE_UNISTD_H
 ifeq ($(OS),Darwin)
 #This should really be based on whether or not the C compiler is clang rather than based on the OS
 CFLAGS+= -Wno-logical-op-parentheses
 endif
 ifdef PORTABLE
+ifdef USE_GLES
+ifndef GLES_LIB
+GLES_LIB:=$(shell pkg-config --libs glesv2)
+endif
+LDFLAGS:=-lm $(GLES_LIB)
+else
 CFLAGS+= -DGLEW_STATIC -Iglew/include
 LDFLAGS:=-lm glew/lib/libGLEW.a
+endif
 
 ifeq ($(OS),Darwin)
 CFLAGS+= -IFrameworks/SDL2.framework/Headers
@@ -55,7 +68,10 @@
 FIXUP:=install_name_tool -change @rpath/SDL2.framework/Versions/A/SDL2 @executable_path/Frameworks/SDL2.framework/Versions/A/SDL2
 else
 CFLAGS+= -Isdl/include
-LDFLAGS+= -Wl,-rpath='$$ORIGIN/lib' -Llib -lSDL2 $(shell pkg-config --libs gl)
+LDFLAGS+= -Wl,-rpath='$$ORIGIN/lib' -Llib -lSDL2
+ifndef USE_GLES
+LDFLAGS+= $(shell pkg-config --libs gl)
+endif
 endif #Darwin
 
 else
--- a/nuklear_ui/blastem_nuklear.c	Sun Dec 30 19:40:32 2018 -0800
+++ b/nuklear_ui/blastem_nuklear.c	Sun Dec 30 21:10:44 2018 -0800
@@ -1789,10 +1789,12 @@
 
 void blastem_nuklear_render(void)
 {
-	nk_input_end(context);
-	current_view(context);
-	nk_sdl_render(NK_ANTI_ALIASING_ON, 512 * 1024, 128 * 1024);
-	nk_input_begin(context);
+	if (current_view != view_play) {
+		nk_input_end(context);
+		current_view(context);
+		nk_sdl_render(NK_ANTI_ALIASING_ON, 512 * 1024, 128 * 1024);
+		nk_input_begin(context);
+	}
 }
 
 void ui_idle_loop(void)
@@ -1849,7 +1851,11 @@
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#ifdef USE_GLES
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+#else
 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, buf);
+#endif
 	return nk_image_id((int)tex);
 }
 
@@ -1929,6 +1935,14 @@
 		}
 		ui_image *this_image = ui_images[num_ui_images-1] = calloc(1, sizeof(ui_image));
 		this_image->image_data = load_png(buf, buf_size, &this_image->width, &this_image->height);
+#ifdef USE_GLES
+		uint32_t *cur = this_image->image_data;
+		for (int i = 0; i < this_image->width*this_image->height; i++, cur++)
+		{
+			uint32_t pixel = *cur;
+			*cur = (pixel & 0xFF00FF00) | (pixel << 16 & 0xFF0000) | (pixel >> 16 & 0xFF);
+		}
+#endif
 		free(buf);
 		if (!this_image->image_data) {
 			num_ui_images--;
--- a/nuklear_ui/nuklear_sdl_gles2.h	Sun Dec 30 19:40:32 2018 -0800
+++ b/nuklear_ui/nuklear_sdl_gles2.h	Sun Dec 30 21:10:44 2018 -0800
@@ -17,8 +17,12 @@
 
 #include <SDL.h>
 #ifndef DISABLE_OPENGL
+#ifdef USE_GLES
+#include <SDL_opengles2.h>
+#else
 #include <GL/glew.h>
 #endif
+#endif
 
 
 NK_API struct nk_context*   nk_sdl_init(SDL_Window *win);
--- a/render_sdl.c	Sun Dec 30 19:40:32 2018 -0800
+++ b/render_sdl.c	Sun Dec 30 21:10:44 2018 -0800
@@ -19,8 +19,12 @@
 #include "controller_info.h"
 
 #ifndef DISABLE_OPENGL
+#ifdef USE_GLES
+#include <SDL_opengles2.h>
+#else
 #include <GL/glew.h>
 #endif
+#endif
 
 #define MAX_EVENT_POLL_PER_FRAME 2
 
@@ -437,7 +441,11 @@
 
 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
 {
+#ifdef USE_GLES
+	return 255 << 24 | b << 16 | g << 8 | r;
+#else
 	return 255 << 24 | r << 16 | g << 8 | b;
+#endif
 }
 
 #ifndef DISABLE_OPENGL
@@ -454,6 +462,16 @@
 
 static const GLushort element_data[] = {0, 1, 2, 3};
 
+static const GLchar shader_prefix[] =
+#ifdef USE_GLES
+	"#version 100\n";
+#else
+	"#version 110\n"
+	"#define lowp\n"
+	"#define mediump\n"
+	"#define highp\n";
+#endif
+
 static GLuint load_shader(char * fname, GLenum shader_type)
 {
 	char const * parts[] = {get_home_dir(), "/.config/blastem/shaders/", fname};
@@ -478,6 +496,12 @@
 		free(text);
 		return 0;
 	}
+	if (strncmp(text, "#version", strlen("#version"))) {
+		GLchar *tmp = text;
+		text = alloc_concat(shader_prefix, tmp);
+		free(tmp);
+		fsize += strlen(shader_prefix);
+	}
 	GLuint ret = glCreateShader(shader_type);
 	glShaderSource(ret, 1, (const GLchar **)&text, (const GLint *)&fsize);
 	free(text);
@@ -499,6 +523,15 @@
 
 static uint32_t texture_buf[512 * 513];
 #ifndef DISABLE_OPENGL
+#ifdef USE_GLES
+#define INTERNAL_FORMAT GL_RGBA
+#define SRC_FORMAT GL_RGBA
+#define RENDER_FORMAT SDL_PIXELFORMAT_ABGR8888
+#else
+#define INTERNAL_FORMAT GL_RGBA8
+#define SRC_FORMAT GL_BGRA
+#define RENDER_FORMAT SDL_PIXELFORMAT_ARGB8888
+#endif
 static void gl_setup()
 {
 	tern_val def = {.ptrval = "linear"};
@@ -514,10 +547,10 @@
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 		if (i < 2) {
 			//TODO: Fixme for PAL + invalid display mode
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_BGRA, GL_UNSIGNED_BYTE, texture_buf);
+			glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 512, 512, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf);
 		} else {
 			uint32_t blank = 255 << 24;
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank);
+			glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, &blank);
 		}
 	}
 	glGenBuffers(2, buffers);
@@ -575,7 +608,7 @@
 		char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval;
 		SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, scaling);
 		//TODO: Fixme for invalid display mode
-		sdl_textures[0] = sdl_textures[1] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, LINEBUF_SIZE, 588);
+		sdl_textures[0] = sdl_textures[1] = SDL_CreateTexture(main_renderer, RENDER_FORMAT, SDL_TEXTUREACCESS_STREAMING, LINEBUF_SIZE, 588);
 #ifndef DISABLE_OPENGL
 	}
 #endif
@@ -1066,6 +1099,11 @@
 		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
 		SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
 		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+#ifdef USE_GLES
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#endif
 	}
 #endif
 	main_window = SDL_CreateWindow(caption, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, main_width, main_height, flags);
@@ -1076,13 +1114,19 @@
 	if (gl_enabled)
 	{
 		main_context = SDL_GL_CreateContext(main_window);
+#ifdef USE_GLES
+		int major_version;
+		if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major_version) == 0 && major_version >= 2) {
+#else
 		GLenum res = glewInit();
 		if (res != GLEW_OK) {
 			warning("Initialization of GLEW failed with code %d\n", res);
 		}
 
 		if (res == GLEW_OK && GLEW_VERSION_2_0) {
+#endif
 			render_gl = 1;
+			SDL_GL_MakeCurrent(main_window, main_context);
 			if (!strcmp("tear", vsync)) {
 				if (SDL_GL_SetSwapInterval(-1) < 0) {
 					warning("late tear is not available (%s), using normal vsync\n", SDL_GetError());
@@ -1111,6 +1155,9 @@
 		if (!main_renderer) {
 			fatal_error("unable to create SDL renderer: %s\n", SDL_GetError());
 		}
+		SDL_RendererInfo rinfo;
+		SDL_GetRendererInfo(main_renderer, &rinfo);
+		printf("SDL2 Render Driver: %s\n", rinfo.name);
 		main_clip.x = main_clip.y = 0;
 		main_clip.w = main_width;
 		main_clip.h = main_height;
@@ -1484,7 +1531,7 @@
 	if (render_gl && which <= FRAMEBUFFER_EVEN) {
 		SDL_GL_MakeCurrent(main_window, main_context);
 		glBindTexture(GL_TEXTURE_2D, textures[which]);
-		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, GL_BGRA, GL_UNSIGNED_BYTE, texture_buf + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]);
+		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, LINEBUF_SIZE, height, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard]);
 		
 		if (screenshot_file) {
 			//properly supporting interlaced modes here is non-trivial, so only save the odd field for now
--- a/shaders/default.f.glsl	Sun Dec 30 19:40:32 2018 -0800
+++ b/shaders/default.f.glsl	Sun Dec 30 21:10:44 2018 -0800
@@ -1,13 +1,12 @@
-#version 110
 
 uniform sampler2D textures[2];
 
-varying vec2 texcoord;
+varying mediump vec2 texcoord;
 
 void main()
 {
-	vec2 modifiedCoord0 = vec2(texcoord.x, (floor(texcoord.y * 512.0 + 0.25) + 0.5)/512.0);
-	vec2 modifiedCoord1 = vec2(texcoord.x, (floor(texcoord.y * 512.0 - 0.25) + 0.5)/512.0);
+	mediump vec2 modifiedCoord0 = vec2(texcoord.x, (floor(texcoord.y * 512.0 + 0.25) + 0.5)/512.0);
+	mediump vec2 modifiedCoord1 = vec2(texcoord.x, (floor(texcoord.y * 512.0 - 0.25) + 0.5)/512.0);
 	gl_FragColor = mix(
 		texture2D(textures[1], modifiedCoord1),
 		texture2D(textures[0], modifiedCoord0),
--- a/shaders/default.v.glsl	Sun Dec 30 19:40:32 2018 -0800
+++ b/shaders/default.v.glsl	Sun Dec 30 21:10:44 2018 -0800
@@ -1,11 +1,10 @@
-#version 110
 
 attribute vec2 pos;
-varying vec2 texcoord;
-uniform float width, height;
+varying mediump vec2 texcoord;
+uniform mediump float width, height;
 
 void main()
 {
 	gl_Position = vec4(pos, 0.0, 1.0);
-	texcoord = sign(pos) * vec2(width/1024.0, height/-1024.0) + vec2(width/1024.0, height/1024.0);
+	texcoord = sign(pos) * vec2(width / 1024.0, height / -1024.0) + vec2(width / 1024.0, height / 1024.0);
 }