changeset 1977:f3cca4b3f17a

Allow use of NPOT textures as a config option. Useful for some mobile GPUs
author Michael Pavone <pavone@retrodev.com>
date Sat, 09 May 2020 21:15:33 -0700
parents 3dd9c68472fb
children 33d5b9b77aef
files default.cfg render_sdl.c shaders/crt.f.glsl shaders/crt.v.glsl shaders/default.f.glsl shaders/default.v.glsl shaders/sharp.f.glsl
diffstat 7 files changed, 68 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/default.cfg	Sat May 09 13:15:49 2020 -0700
+++ b/default.cfg	Sat May 09 21:15:33 2020 -0700
@@ -296,6 +296,9 @@
 	gl on
 	#scaling can be linear (for linear interpolation) or nearest (for nearest neighbor)
 	scaling linear
+	#When off, a 512x512 texture is used for each field, when turned on a smaller texture is used
+	#turning this on seems to help performance on certain mobile GPUs like Mali
+	npot_textures off
 	ntsc {
 		overscan {
 			#these values will result in square pixels in H40 mode
--- a/render_sdl.c	Sat May 09 13:15:49 2020 -0700
+++ b/render_sdl.c	Sat May 09 21:15:33 2020 -0700
@@ -273,7 +273,8 @@
 }
 
 #ifndef DISABLE_OPENGL
-static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, un_height, at_pos;
+static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, un_height, un_texsize, at_pos;
+static int tex_width, tex_height;
 
 static GLfloat vertex_data_default[] = {
 	-1.0f, -1.0f,
@@ -379,6 +380,15 @@
 	char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval;
 	GLint filter = strcmp(scaling, "linear") ? GL_NEAREST : GL_LINEAR;
 	glGenTextures(3, textures);
+	def.ptrval = "off";
+	char *npot_textures = tern_find_path_default(config, "video\0npot_textures\0", def, TVAL_PTR).ptrval;
+	if (!strcmp(npot_textures, "on")) {
+		tex_width = LINEBUF_SIZE;
+		tex_height = 294; //PAL height with full borders
+	} else {
+		tex_width = tex_height = 512;
+	}
+	printf("Using %dx%d textures\n", tex_width, tex_height);
 	for (int i = 0; i < 3; i++)
 	{
 		glBindTexture(GL_TEXTURE_2D, textures[i]);
@@ -388,7 +398,7 @@
 		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, INTERNAL_FORMAT, 512, 512, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf);
+			glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, tex_width, tex_height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, texture_buf);
 		} else {
 			uint32_t blank = 255 << 24;
 			glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, 1, 1, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, &blank);
@@ -417,6 +427,7 @@
 	un_textures[1] = glGetUniformLocation(program, "textures[1]");
 	un_width = glGetUniformLocation(program, "width");
 	un_height = glGetUniformLocation(program, "height");
+	un_texsize = glGetUniformLocation(program, "texsize");
 	at_pos = glGetAttribLocation(program, "pos");
 }
 
@@ -1377,7 +1388,7 @@
 			if (num_buffers) {
 				buffer = frame_buffers[--num_buffers];
 			} else {
-				buffer = calloc(512*512, sizeof(uint32_t));
+				buffer = calloc(tex_width*(tex_height + 1), sizeof(uint32_t));
 			}
 		SDL_UnlockMutex(free_buffer_mutex);
 		locked_pixels = buffer;
@@ -1733,6 +1744,7 @@
 
 		glUniform1f(un_width, render_emulated_width());
 		glUniform1f(un_height, last_height);
+		glUniform2f(un_texsize, tex_width, tex_height);
 
 		glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
 		glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
--- a/shaders/crt.f.glsl	Sat May 09 13:15:49 2020 -0700
+++ b/shaders/crt.f.glsl	Sat May 09 21:15:33 2020 -0700
@@ -1,5 +1,3 @@
-#version 110
-
 /* Subtle CRT shader usable in fullscreen - Anaƫl Seghezzi [anael(at)maratis3d.com]
    This shader is free software distributed under the terms of the GNU General Public
    License version 3 or higher. This gives you the right to redistribute and/or
@@ -10,63 +8,64 @@
 #define M_PI 3.14159265358979323846
 
 uniform sampler2D textures[2];
-uniform float width, height;
-varying vec2 texcoord;
-varying vec2 screencoord;
+uniform mediump float width, height;
+uniform mediump vec2 texsize;
+varying mediump vec2 texcoord;
+varying mediump vec2 screencoord;
 
 
-float nrand(vec2 n) {
+mediump float nrand(vec2 n) {
 	return fract(sin(dot(n.xy, vec2(12.9898, 78.233))) * 43758.5453);
 }
 
-float scanline(vec2 texco)
+mediump float scanline(vec2 texco)
 {
-	return (1.0 - abs(cos(texco.y * 512.0 * M_PI)));
+	return (1.0 - abs(cos(texco.y * texsize.y * M_PI)));
 }
 
-vec2 sharp_coord(vec2 texco, vec2 dim, vec2 sharpness)
+mediump vec2 sharp_coord(mediump vec2 texco, mediump vec2 dim, mediump vec2 sharpness)
 {
-	vec2 texcoif = texco * dim;
-	vec2 texcoi = floor(texcoif);
-	vec2 mu = (texcoif - 0.5) - texcoi;
-	vec2 mub = pow(abs(mu) * 2.0, sharpness) * sign(mu) * 0.5;
+	mediump vec2 texcoif = texco * dim;
+	mediump vec2 texcoi = floor(texcoif);
+	mediump vec2 mu = (texcoif - 0.5) - texcoi;
+	mediump vec2 mub = pow(abs(mu) * 2.0, sharpness) * sign(mu) * 0.5;
 	return (texcoi + mub + 0.5) / dim;	
 }
 
 void main()
 {
-	float v = 1.0 / 512.0;
-	float yforce = 0.175;
-	float vign = length(screencoord);
+	mediump float v = 1.0 / texsize.y;
+	mediump float yforce = 0.175;
+	mediump float vign = length(screencoord);
 
 	// monitor deformation
-	vec2 monitorcoord = (screencoord + screencoord * vign * 0.025);
+	mediump vec2 monitorcoord = (screencoord + screencoord * vign * 0.025);
 	
 	if (monitorcoord.x < -1.0 || monitorcoord.y < -1.0 || monitorcoord.x > 1.0 || monitorcoord.y > 1.0) {
 		gl_FragColor = vec4(0.0);
 		return;
 	}
 
-	vec2 texco = monitorcoord * vec2(width/1024.0, height/-1024.0) + vec2(width/1024.0, height/1024.0);
+	mediump vec2 texco = monitorcoord * vec2(0.5*width/texsize.x, -0.5 * height/texsize.y) + vec2(0.5*width/texsize.x, 0.5*height/texsize.y);
 
 	// mask
-	float maskx = 1.0 - pow(abs(monitorcoord.x), 200.0);
-	float masky = 1.0 - pow(abs(-monitorcoord.y), 200.0);
-	float mask = clamp(maskx * masky, 0.0, 1.0);
+	mediump float maskx = 1.0 - pow(abs(monitorcoord.x), 200.0);
+	mediump float masky = 1.0 - pow(abs(-monitorcoord.y), 200.0);
+	mediump float mask = clamp(maskx * masky, 0.0, 1.0);
 
 	// sharp texcoord
-	vec2 texco_sharp0 = sharp_coord(texco, vec2(512.0, 512.0), vec2(4.0, 8.0));
-	vec2 texco_sharp1 = sharp_coord(texco - vec2(0.0, 1.0 / 1024.0), vec2(512.0, 512.0), vec2(4.0, 8.0));
+	mediump vec2 texco_sharp0 = sharp_coord(texco, texsize, vec2(4.0, 8.0));
+	mediump vec2 texco_sharp1 = sharp_coord(texco - vec2(0.0, 0.5 / texsize.y), texsize, vec2(4.0, 8.0));
 
-	vec4 src0 = texture2D(textures[0], texco_sharp0);
-	vec4 src1 = texture2D(textures[1], texco_sharp1);
+	mediump vec4 src0 = texture2D(textures[0], texco_sharp0);
+	mediump vec4 src1 = texture2D(textures[1], texco_sharp1);
 
 	// interlace mix
-	float interlace = cos((texco.y * 1024.0) * M_PI);
-	vec4 src_mix = mix(src0, src1, interlace * 0.5 + 0.5);
+	mediump float interlace = cos((texco.y * 2.0 * texsize.y) * M_PI);
+	mediump vec4 src_mix = mix(src0, src1, interlace * 0.5 + 0.5);
 
 	// blur
-	vec4 src_blur = mix(texture2D(textures[0], texco), texture2D(textures[1], texco), 0.5);
+	mediump vec4 src_blur = mix(texture2D(textures[0], texco), texture2D(textures[1], texco), 0.5);
 
 #ifdef NO_SCANLINE
 
@@ -75,11 +74,11 @@
 #else
 	// multisample scanline with grain
 	// TODO: offset grain with time (needs a "frame" uniform)
-	float cosy;
-	cosy  = scanline(texco + vec2(0.125, v * (nrand(texcoord + vec2(0.0, 1.0)) * 0.25) + 0.3333));
-	cosy += scanline(texco + vec2(0.25, v * (nrand(texcoord + vec2(0.0, 2.0)) * 0.25) + 0.25));
-	cosy += scanline(texco + vec2(0.50, v * (nrand(texcoord + vec2(0.0, 3.0)) * 0.25) + 0.6666));
-	cosy += scanline(texco + vec2(0.75, v * (nrand(texcoord + vec2(0.0, 4.0)) * 0.25) + 0.75));
+	mediump float cosy;
+	cosy  = scanline(texco + vec2(0.125, v * (nrand(texcoord + vec2(0.0, 512.0/texsize.y)) * 0.25) + 512.0*0.3333/texsize.y));
+	cosy += scanline(texco + vec2(0.25, v * (nrand(texcoord + vec2(0.0, 1024.0/texsize.y)) * 0.25) + 512.0*0.25/texsize.y));
+	cosy += scanline(texco + vec2(0.50, v * (nrand(texcoord + vec2(0.0, 1536.0/texsize.y)) * 0.25) + 512.0*0.6666/texsize.y));
+	cosy += scanline(texco + vec2(0.75, v * (nrand(texcoord + vec2(0.0, 2048.0/texsize.y)) * 0.25) + 512.0*0.75/texsize.y));
 	cosy *= 0.25;
 
 	// final scanline + burn
--- a/shaders/crt.v.glsl	Sat May 09 13:15:49 2020 -0700
+++ b/shaders/crt.v.glsl	Sat May 09 21:15:33 2020 -0700
@@ -1,13 +1,13 @@
-#version 110
 
 attribute vec2 pos;
-varying vec2 texcoord;
-varying vec2 screencoord;
-uniform float width, height;
+varying mediump vec2 texcoord;
+varying mediump vec2 screencoord;
+uniform mediump float width, height;
+uniform mediump vec2 texsize;
 
 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(0.5*width/texsize.x, -0.5*height/texsize.y) + vec2(0.5*width/texsize.x, 0.5*height/texsize.y);
 	screencoord = sign(pos);
 }
\ No newline at end of file
--- a/shaders/default.f.glsl	Sat May 09 13:15:49 2020 -0700
+++ b/shaders/default.f.glsl	Sat May 09 21:15:33 2020 -0700
@@ -1,15 +1,16 @@
 
 uniform sampler2D textures[2];
+uniform mediump vec2 texsize;
 
 varying mediump vec2 texcoord;
 
 void main()
 {
-	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);
+	mediump vec2 modifiedCoord0 = vec2(texcoord.x, (floor(texcoord.y * texsize.y + 0.25) + 0.5)/texsize.y);
+	mediump vec2 modifiedCoord1 = vec2(texcoord.x, (floor(texcoord.y * texsize.y - 0.25) + 0.5)/texsize.y);
 	gl_FragColor = mix(
 		texture2D(textures[1], modifiedCoord1),
 		texture2D(textures[0], modifiedCoord0),
-		(sin(texcoord.y * 1024.0 * 3.14159265359) + 1.0) * 0.5
+		(sin(texcoord.y * texsize.y * 6.283185307) + 1.0) * 0.5
 	);
 }
--- a/shaders/default.v.glsl	Sat May 09 13:15:49 2020 -0700
+++ b/shaders/default.v.glsl	Sat May 09 21:15:33 2020 -0700
@@ -2,9 +2,10 @@
 attribute vec2 pos;
 varying mediump vec2 texcoord;
 uniform mediump float width, height;
+uniform mediump vec2 texsize;
 
 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(0.5 * width / texsize.x, -0.5 * height / texsize.y) + vec2(0.5 * width / texsize.x, 0.5 * height / texsize.y);
 }
--- a/shaders/sharp.f.glsl	Sat May 09 13:15:49 2020 -0700
+++ b/shaders/sharp.f.glsl	Sat May 09 21:15:33 2020 -0700
@@ -1,20 +1,18 @@
 
 uniform sampler2D textures[2];
+uniform mediump vec2 texsize;
 
 varying mediump vec2 texcoord;
 
 void main()
 {
-	mediump float x0 = (floor(texcoord.x * 512.0 - 0.25) + 0.5)/512.0;
-	mediump float x1 = (floor(texcoord.x * 512.0 + 0.25) + 0.5)/512.0;
-	mediump float y0 = (floor(texcoord.y * 512.0 + 0.25) + 0.5)/512.0;
-	mediump float y1 = (floor(texcoord.y * 512.0 - 0.25) + 0.5)/512.0;
+	mediump float x0 = (floor(texcoord.x * texsize.x - 0.25) + 0.5)/texsize.x;
+	mediump float x1 = (floor(texcoord.x * texsize.x + 0.25) + 0.5)/texsize.x;
+	mediump float y0 = (floor(texcoord.y * texsize.y + 0.25) + 0.5)/texsize.y;
+	mediump float y1 = (floor(texcoord.y * texsize.y - 0.25) + 0.5)/texsize.y;
 	
-	
-	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);
-	mediump float ymix = (sin(texcoord.y * 1024.0 * 3.14159265359) + 1.0) * 0.5;
-	mediump float xmix = (sin(texcoord.x * 1024.0 * 3.14159265359) + 1.0) * 0.5;
+	mediump float ymix = (sin(texcoord.y * texsize.y * 6.283185307) + 1.0) * 0.5;
+	mediump float xmix = (sin(texcoord.x * texsize.x * 6.283185307) + 1.0) * 0.5;
 	gl_FragColor = mix(
 		mix(
 			texture2D(textures[1], vec2(x0, y1)),