changeset 798:062a2199daf6

Use SDL2 renderer as a fallback
author =?UTF-8?q?Higor=20Eur=C3=ADpedes?= <heuripedes@gmail.com>
date Sun, 26 Jul 2015 13:08:22 -0700
parents 65181c3ee560
children 0b692b5d154b
files render_sdl.c
diffstat 1 files changed, 152 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/render_sdl.c	Sun Jul 26 13:05:05 2015 -0700
+++ b/render_sdl.c	Sun Jul 26 13:08:22 2015 -0700
@@ -12,19 +12,19 @@
 #include "io.h"
 #include "util.h"
 
+#ifndef DISABLE_OPENGL
 #include <GL/glew.h>
+#endif
 
 SDL_Window *main_window;
-#ifdef DISABLE_OPENGL
 SDL_Renderer *main_renderer;
 SDL_Texture  *main_texture;
 SDL_Rect      main_clip;
-#else
 SDL_GLContext *main_context;
-#endif
 
 uint8_t render_dbg = 0;
 uint8_t debug_pal = 0;
+uint8_t render_gl = 1;
 
 uint32_t last_frame = 0;
 
@@ -101,6 +101,7 @@
 	return 255 << 24 | r << 16 | g << 8 | b;
 }
 
+#ifndef DISABLE_OPENGL
 GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, at_pos;
 
 GLfloat vertex_data[] = {
@@ -154,6 +155,7 @@
 	}
 	return ret;
 }
+#endif
 
 void render_alloc_surfaces(vdp_context * context)
 {
@@ -161,48 +163,52 @@
 	memset(context->oddbuf, 0, 512 * 256 * 4 * 2);
 	context->evenbuf = ((char *)context->oddbuf) + 512 * 256 * 4;
 
-#ifdef DISABLE_OPENGL
+#ifndef DISABLE_OPENGL
+	if (render_gl) {
+		glGenTextures(3, textures);
+		for (int i = 0; i < 3; i++)
+		{
+			glBindTexture(GL_TEXTURE_2D, textures[i]);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
+			if (i < 2) {
+				glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, i ? context->evenbuf : context->oddbuf);
+			} else {
+				uint32_t blank = 255 << 24;
+				glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank);
+			}
+		}
+		glGenBuffers(2, buffers);
+		glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
+		glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
+		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);
+		tern_val def = {.ptrval = "default.v.glsl"};
+		vshader = load_shader(tern_find_path_default(config, "video\0vertex_shader\0", def).ptrval, GL_VERTEX_SHADER);
+		def.ptrval = "default.f.glsl";
+		fshader = load_shader(tern_find_path_default(config, "video\0fragment_shader\0", def).ptrval, GL_FRAGMENT_SHADER);
+		program = glCreateProgram();
+		glAttachShader(program, vshader);
+		glAttachShader(program, fshader);
+		glLinkProgram(program);
+		GLint link_status;
+		glGetProgramiv(program, GL_LINK_STATUS, &link_status);
+		if (!link_status) {
+			fputs("Failed to link shader program\n", stderr);
+			exit(1);
+		}
+		un_textures[0] = glGetUniformLocation(program, "textures[0]");
+		un_textures[1] = glGetUniformLocation(program, "textures[1]");
+		un_width = glGetUniformLocation(program, "width");
+		at_pos = glGetAttribLocation(program, "pos");
+	} else {
+#endif
 	/* height=480 to fit interlaced output */
-	main_texture = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 480);
-#else
-	glGenTextures(3, textures);
-	for (int i = 0; i < 3; i++)
-	{
-		glBindTexture(GL_TEXTURE_2D, textures[i]);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
-		if (i < 2) {
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, i ? context->evenbuf : context->oddbuf);
-		} else {
-			uint32_t blank = 255 << 24;
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank);
-		}
+		main_texture = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 480);
+#ifndef DISABLE_OPENGL
 	}
-	glGenBuffers(2, buffers);
-	glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
-	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
-	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);
-	tern_val def = {.ptrval = "default.v.glsl"};
-	vshader = load_shader(tern_find_path_default(config, "video\0vertex_shader\0", def).ptrval, GL_VERTEX_SHADER);
-	def.ptrval = "default.f.glsl";
-	fshader = load_shader(tern_find_path_default(config, "video\0fragment_shader\0", def).ptrval, GL_FRAGMENT_SHADER);
-	program = glCreateProgram();
-	glAttachShader(program, vshader);
-	glAttachShader(program, fshader);
-	glLinkProgram(program);
-	GLint link_status;
-	glGetProgramiv(program, GL_LINK_STATUS, &link_status);
-	if (!link_status) {
-		fputs("Failed to link shader program\n", stderr);
-		exit(1);
-	}
-	un_textures[0] = glGetUniformLocation(program, "textures[0]");
-	un_textures[1] = glGetUniformLocation(program, "textures[1]");
-	un_width = glGetUniformLocation(program, "width");
-	at_pos = glGetAttribLocation(program, "pos");
 #endif
 }
 
@@ -238,18 +244,9 @@
 		height = mode.h;
 	}
 
-#ifdef DISABLE_OPENGL
-	SDL_CreateWindowAndRenderer(width, height, flags, &main_window, &main_renderer);
+	render_gl = 0;
 
-	if (!main_window || !main_renderer) {
-		fprintf(stderr, "unable to create SDL window: %s\n", SDL_GetError());
-		SDL_Quit();
-		exit(1);
-	}
-	main_clip.x = main_clip.y = 0;
-	main_clip.w = width;
-	main_clip.h = height;
-#else
+#ifndef DISABLE_OPENGL
 	flags |= SDL_WINDOW_OPENGL;
 	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
 	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
@@ -266,15 +263,30 @@
 	GLenum res = glewInit();
 	if (res != GLEW_OK) {
 		fprintf(stderr, "Initialization of GLEW failed with code %d\n", res);
-		SDL_Quit();
-		exit(1);
+		SDL_DestroyWindow(main_window);
+	}
+
+	if (GLEW_VERSION_2_0) {
+		render_gl = 1;
 	}
-	if (!GLEW_VERSION_2_0) {
-		fputs("BlastEm requires at least OpenGL 2.0, but it is unavailable\n", stderr);
-		SDL_Quit();
-		exit(1);
+	else {
+		SDL_DestroyWindow(main_window);
+		fputs("OpenGL 2.0 is unavailable, falling back to SDL2 renderer\n", stderr);
+#endif
+		SDL_CreateWindowAndRenderer(width, height, flags, &main_window, &main_renderer);
+
+		if (!main_window || !main_renderer) {
+			fprintf(stderr, "unable to create SDL window: %s\n", SDL_GetError());
+			SDL_Quit();
+			exit(1);
+		}
+		main_clip.x = main_clip.y = 0;
+		main_clip.w = width;
+		main_clip.h = height;
+#ifndef DISABLE_OPENGL
 	}
 #endif
+
 	SDL_GetWindowSize(main_window, &width, &height);
 	printf("Window created with size: %d x %d\n", width, height);
 	float src_aspect = 4.0/3.0;
@@ -282,28 +294,31 @@
 	tern_val def = {.ptrval = "normal"};
 	int stretch = fabs(aspect - src_aspect) > 0.01 && !strcmp(tern_find_path_default(config, "video\0aspect\0", def).ptrval, "stretch");
 
-#ifdef DISABLE_OPENGL
 	if (!stretch) {
-		float scale_x = (float)width / 320.0;
-		float scale_y = (float)height / 240.0;
-		float scale   = scale_x > scale_y ? scale_y : scale_x;
-		main_clip.w = 320.0 * scale;
-		main_clip.h = 240.0 * scale;
-		main_clip.x = (width  - main_clip.w) / 2;
-		main_clip.y = (height - main_clip.h) / 2;
+#ifndef DISABLE_OPENGL
+		if (render_gl) {
+			for (int i = 0; i < 4; i++)
+			{
+				if (aspect > src_aspect) {
+					vertex_data[i*2] *= src_aspect/aspect;
+				} else {
+					vertex_data[i*2+1] *= aspect/src_aspect;
+				}
+			}
+		} else {
+#endif
+			float scale_x = (float)width / 320.0;
+			float scale_y = (float)height / 240.0;
+			float scale   = scale_x > scale_y ? scale_y : scale_x;
+			main_clip.w = 320.0 * scale;
+			main_clip.h = 240.0 * scale;
+			main_clip.x = (width  - main_clip.w) / 2;
+			main_clip.y = (height - main_clip.h) / 2;
+#ifndef DISABLE_OPENGL
+		}
+#endif
 	}
-#else
-	if (!stretch) {
-		for (int i = 0; i < 4; i++)
-		{
-			if (aspect > src_aspect) {
-				vertex_data[i*2] *= src_aspect/aspect;
-			} else {
-				vertex_data[i*2+1] *= aspect/src_aspect;
-			}
-		}
-	}
-#endif
+
 	caption = title;
 	min_delay = 0;
 	for (int i = 0; i < 100; i++) {
@@ -376,75 +391,77 @@
 	int height = 240;
 
 	last_frame = SDL_GetTicks();
-#ifdef DISABLE_OPENGL
-	SDL_Rect area;
-
-	area.x = area.y = 0;
-	area.w = width;
-	area.h = height;
+#ifndef DISABLE_OPENGL
+	if (render_gl) {
+		glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]);
+		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);;
 
-	if (context->regs[REG_MODE_4] & BIT_INTERLACE)
-	{
-		unsigned skip;
-		uint32_t *src = (uint32_t*)context->framebuf;
-		uint8_t  *dst;
-		int i;
+		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+		glClear(GL_COLOR_BUFFER_BIT);
 
-		area.h *= 2;
+		glUseProgram(program);
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D, textures[0]);
+		glUniform1i(un_textures[0], 0);
 
-		SDL_LockTexture(main_texture, &area, (void**)&dst, &skip);
+		glActiveTexture(GL_TEXTURE1);
+		glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]);
+		glUniform1i(un_textures[1], 1);
 
-		if (context->framebuf == context->evenbuf)
-			dst += skip;
+		glUniform1f(un_width, width);
 
-		skip *= 2;
+		glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
+		glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
+		glEnableVertexAttribArray(at_pos);
 
-		for (i = 0; i < 240; ++i)
-		{
-			memcpy(dst, src, width*sizeof(uint32_t));
-			src += 320;
-			dst += skip;
-		}
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
+		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0);
+
+		glDisableVertexAttribArray(at_pos);
 
-		SDL_UnlockTexture(main_texture);
-	}
-	else /* possibly faster path for non-interlaced output */
-		SDL_UpdateTexture(main_texture, &area, context->framebuf, 320*sizeof(uint32_t));
+		SDL_GL_SwapWindow(main_window);
+	} else {
+#endif
+		SDL_Rect area;
 
-	SDL_RenderClear(main_renderer);
-	SDL_RenderCopy(main_renderer, main_texture, &area, &main_clip);
-	SDL_RenderPresent(main_renderer);
-#else
-	glBindTexture(GL_TEXTURE_2D, textures[context->framebuf == context->oddbuf ? 0 : 1]);
-	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, context->framebuf);;
+		area.x = area.y = 0;
+		area.w = width;
+		area.h = height;
 
-	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-	glClear(GL_COLOR_BUFFER_BIT);
+		if (context->regs[REG_MODE_4] & BIT_INTERLACE) {
+			unsigned skip;
+			uint32_t *src = (uint32_t*)context->framebuf;
+			uint8_t  *dst;
+			int i;
 
-	glUseProgram(program);
-	glActiveTexture(GL_TEXTURE0);
-	glBindTexture(GL_TEXTURE_2D, textures[0]);
-	glUniform1i(un_textures[0], 0);
+			area.h *= 2;
+
+			SDL_LockTexture(main_texture, &area, (void**)&dst, &skip);
+
+			if (context->framebuf == context->evenbuf)
+				dst += skip;
+
+			skip *= 2;
 
-	glActiveTexture(GL_TEXTURE1);
-	glBindTexture(GL_TEXTURE_2D, (context->regs[REG_MODE_4] & BIT_INTERLACE) ? textures[1] : textures[2]);
-	glUniform1i(un_textures[1], 1);
-
-	glUniform1f(un_width, width);
-
-	glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
-	glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
-	glEnableVertexAttribArray(at_pos);
+			for (i = 0; i < 240; ++i) {
+				memcpy(dst, src, width*sizeof(uint32_t));
+				src += 320;
+				dst += skip;
+			}
 
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
-	glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0);
-
-	glDisableVertexAttribArray(at_pos);
+			SDL_UnlockTexture(main_texture);
+		}
+		else /* possibly faster path for non-interlaced output */
+			SDL_UpdateTexture(main_texture, &area, context->framebuf, 320*sizeof(uint32_t));
 
-	SDL_GL_SwapWindow(main_window);
+		SDL_RenderClear(main_renderer);
+		SDL_RenderCopy(main_renderer, main_texture, &area, &main_clip);
+		SDL_RenderPresent(main_renderer);
+#ifndef DISABLE_OPENGL
+	}
 #endif
-	if (context->regs[REG_MODE_4] & BIT_INTERLACE)
-	{
+
+	if (context->regs[REG_MODE_4] & BIT_INTERLACE) {
 		context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf;
 	}
 }