From 25effd17ef1a1a05d671382b9a51be29734226a0 Mon Sep 17 00:00:00 2001
From: Ludovic Pouzenc <ludovic@pouzenc.fr>
Date: Sat, 7 Sep 2019 10:49:21 +0200
Subject: Multi-process done. GL has to be done cleanly now.

---
 Makefile      |  2 +-
 src/main.c    | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 src/main.h    |  2 ++
 src/scene00.c | 18 ++++++------
 src/scene01.c | 34 ++++++++--------------
 5 files changed, 102 insertions(+), 44 deletions(-)

diff --git a/Makefile b/Makefile
index 5b0297c..b655db0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS=-Wall -Werror -g
+CFLAGS=-Wall -Werror -g -DDEBUG
 PKGLIBS=caca sdl2 glu
 
 all: demoscene-eo
diff --git a/src/main.c b/src/main.c
index 9b151b1..d519034 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,8 +32,18 @@
 #include <stdint.h>    // uint32_t
 #include <stdio.h>     // printf()
 
-
+#ifdef DEBUG
 #define TRACE(hint) printf("%s(): %s\n", __func__, hint)
+#else
+#define TRACE(hint)
+#endif
+
+#ifdef DEBUG_SEM
+#define TRACE_SEM(sem,op,hint) printf("%s(): %s(%s) %s\n", __func__, op, #sem, hint)
+#else
+#define TRACE_SEM(sem,op,hint)
+#endif
+
 #define SCENE_COUNT 3
 #define SCENE_NEXT do { shm->scene = (shm->scene+1)%SCENE_COUNT; } while(0)
 
@@ -42,13 +52,13 @@
 
 #define SEM_POST(sem,errcode) \
 	do { \
-		/* printf("%s(): sem_post(%s,%i)\n", __func__, #sem, errcode); */ \
+		TRACE_SEM(sem,"sem_post",""); \
 		if ( sem_post(sem) == -1 ) { return errcode; } \
 	} while(0)
 
 #define SEM_WAIT(sem,errcode) \
 	do { \
-		/* printf("%s(): sem_wait(%s,%i) call\n", __func__, #sem, errcode); */\
+		TRACE_SEM(sem,"sem_wait","call"); \
 		while ( sem_wait(sem) == -1 ) { \
 			switch(errno) { \
 				case EINTR: \
@@ -58,7 +68,7 @@
 					return errcode; \
 			} \
 		} \
-		/* printf("%s(): sem_wait(%s,%i) done\n", __func__, #sem, errcode); */\
+		TRACE_SEM(sem,"sem_wait","done"); \
 	} while(0)
 
 typedef struct {
@@ -140,7 +150,6 @@ int parent() {
 			// init / free if scene transition
 			if ( lastscene != shm->scene ) {
 				switch(lastscene) {
-					//FIXME call free_gl and free_sdl in respective processes too
 					case 0: scene00_free_caca(&shm->ge, &shm->s00e); break;
 					case 1: scene01_free_caca(&shm->ge, &shm->s01e); break;
 					case 2: scene02_free_caca(&shm->ge, &shm->s02e); break;
@@ -150,7 +159,6 @@ int parent() {
 				shm->ge.sdl_ticks = SDL_GetTicks();
 				shm->ge.sc_framecount = 0;
 				switch(shm->scene) {
-					//FIXME call init_gl and init_sdl in respective processes too
 					case 0: res = scene00_init_caca(&shm->ge, &shm->s00e); break;
 					case 1: res = scene01_init_caca(&shm->ge, &shm->s01e); break;
 					case 2: res = scene02_init_caca(&shm->ge, &shm->s02e); break;
@@ -220,8 +228,8 @@ int parent() {
 }
 
 int worker_sdl() {
-	int res;
-	Uint32 sdl_win_flags = 0; //XXX for final version, consider sdl_win_flags = SDL_WINDOW_HIDDEN;
+	int lastscene=-1, res;
+	Uint32 sdl_win_flags = 0; //XXX for final version, consider adding SDL_WINDOW_HIDDEN
 	SDL_RendererInfo renderer_info;
 	SDL_Event sdl_ev;
 
@@ -247,6 +255,30 @@ int worker_sdl() {
 		//FIXME change for TRYWAIT for event handling (+delay)
 		SEM_WAIT(&shm->worker_sdl_can_render,20);
 
+		if (!shm->paused) {
+			// init / free if scene transition
+			if ( lastscene != shm->scene ) {
+				switch(lastscene) {
+					case 0: scene00_free_sdl(&shm->ge, &shm->s00e); break;
+					case 1: scene01_free_sdl(&shm->ge, &shm->s01e); break;
+					case 2: scene02_free_sdl(&shm->ge, &shm->s02e); break;
+				}
+			}
+			while ( lastscene != shm->scene ) {
+				shm->ge.sdl_ticks = SDL_GetTicks();
+				shm->ge.sc_framecount = 0;
+				switch(shm->scene) {
+					case 0: res = scene00_init_sdl(&shm->ge, &shm->s00e); break;
+					case 1: res = scene01_init_sdl(&shm->ge, &shm->s01e); break;
+					case 2: res = scene02_init_sdl(&shm->ge, &shm->s02e); break;
+				}
+				// If scene init fail, skip to the next one
+				if (res) SCENE_NEXT; else lastscene = shm->scene;
+			}
+		}
+
+		TRACE("before next_sdl");
+		printf("DEBUG shm->scene : %i\n", shm->scene);
 		// Compute current scene frame (sdl part)
 		switch(shm->scene) {
 			case 0: res = scene00_next_sdl(&shm->ge, &shm->s00e); break;
@@ -254,6 +286,7 @@ int worker_sdl() {
 			case 2: res = scene02_next_sdl(&shm->ge, &shm->s02e); break;
 		}
 		if (res) SCENE_NEXT;
+		TRACE("after next_sdl");
 
 		// Event handling for the SDL window (debug purposes)
 		while(SDL_PollEvent(&sdl_ev)) {
@@ -272,8 +305,10 @@ int worker_sdl() {
 					break;
 			}
 		}
+		TRACE("after SDL_PollEvent loop");
 
 		SEM_POST(&shm->parent_can_read_result, 21);
+		TRACE("after sem_post");
 	}
 
 	SDL_DestroyRenderer(shm->ge.sdl_rndr);
@@ -284,8 +319,9 @@ int worker_sdl() {
 }
 
 int worker_gl() {
-	int res;
-	//Uint32 sdl_win_flags = SDL_WINDOW_OPENGL;
+	int lastscene=-1, res;
+	Uint32 sdl_win_flags = SDL_WINDOW_OPENGL; //XXX for final version, consider adding SDL_WINDOW_HIDDEN
+	SDL_RendererInfo renderer_info;
 	SDL_Event gl_ev;
 
 	TRACE("call");
@@ -307,7 +343,17 @@ int worker_gl() {
 	SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
 
 	// Initialize OpenGL
-	shm->ge.gl_win = SDL_CreateWindow("GL Debug", SDL_WINDOWPOS_CENTERED, 0, FBUF_W, FBUF_H, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
+	//shm->ge.gl_win = SDL_CreateWindow("GL Debug", SDL_WINDOWPOS_CENTERED, 0, FBUF_W, FBUF_H, sdl_win_flags);
+
+	res = SDL_CreateWindowAndRenderer(FBUF_W, FBUF_H, sdl_win_flags, &shm->ge.gl_win, &shm->ge.gl_rndr);
+	if ( res == -1) return 4;
+	SDL_SetWindowTitle(shm->ge.gl_win, "GL debug");
+	res = SDL_GetRendererInfo(shm->ge.gl_rndr, &renderer_info);
+	if ( res < 0 ) return 5;
+	if ( !(renderer_info.flags & SDL_RENDERER_ACCELERATED)) return 6;
+	if ( !(renderer_info.flags & SDL_RENDERER_TARGETTEXTURE)) return 7;
+	shm->ge.gl_target = SDL_CreateTexture(shm->ge.gl_rndr, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, FBUF_W, FBUF_H);
+	if ( shm->ge.gl_target == NULL ) return 9;
 	shm->ge.gl_ctx = SDL_GL_CreateContext(shm->ge.gl_win);
 	if ( shm->ge.gl_ctx == NULL ) return 11;
 
@@ -315,6 +361,28 @@ int worker_gl() {
 		//FIXME change for TRYWAIT for event handling (+delay)
 		SEM_WAIT(&shm->worker_gl_can_render,10);
 
+		if (!shm->paused) {
+			// init / free if scene transition
+			if ( lastscene != shm->scene ) {
+				switch(lastscene) {
+					case 0: scene00_free_gl(&shm->ge, &shm->s00e); break;
+					case 1: scene01_free_gl(&shm->ge, &shm->s01e); break;
+					case 2: scene02_free_gl(&shm->ge, &shm->s02e); break;
+				}
+			}
+			while ( lastscene != shm->scene ) {
+				shm->ge.sdl_ticks = SDL_GetTicks();
+				shm->ge.sc_framecount = 0;
+				switch(shm->scene) {
+					case 0: res = scene00_init_gl(&shm->ge, &shm->s00e); break;
+					case 1: res = scene01_init_gl(&shm->ge, &shm->s01e); break;
+					case 2: res = scene02_init_gl(&shm->ge, &shm->s02e); break;
+				}
+				// If scene init fail, skip to the next one
+				if (res) SCENE_NEXT; else lastscene = shm->scene;
+			}
+		}
+
 		// Compute current scene frame (gl part)
 		switch(shm->scene) {
 			case 0: res = scene00_next_gl(&shm->ge, &shm->s00e); break;
diff --git a/src/main.h b/src/main.h
index 4510b19..363a614 100644
--- a/src/main.h
+++ b/src/main.h
@@ -24,6 +24,8 @@ typedef struct {
 	// OpenGL worker
 	SDL_Window* gl_win;
 	SDL_GLContext gl_ctx;
+	SDL_Renderer *gl_rndr;
+	SDL_Texture *gl_target;
 	// framebuffer to inject OpenGL or SDL result in caca canvas
 	uint32_t raw_target[FBUF_W*FBUF_H];
 	// Timing
diff --git a/src/scene00.c b/src/scene00.c
index b1e4e57..f8df185 100644
--- a/src/scene00.c
+++ b/src/scene00.c
@@ -51,11 +51,7 @@ int scene00_next_gl(graphical_env_t *ge, scene00_env_t *se) {
 
 int scene00_next_sdl(graphical_env_t *ge, scene00_env_t *se) {
 	// Shorthands
-	caca_canvas_t *cv = ge->cv;
-	int w = ge->w, h = ge->h;
 	SDL_Renderer *r = ge->sdl_rndr;
-	// Local vars
-	int res;
 
 	// https://gist.github.com/Twinklebear/8265888
 	// https://forums.libsdl.org/viewtopic.php?p=51634
@@ -65,17 +61,16 @@ int scene00_next_sdl(graphical_env_t *ge, scene00_env_t *se) {
 	SDL_RenderCopy(r, se->eo1, NULL, NULL);
 	// [...]
 
-	// Copy the SDL screen to SDL debug window (and display it, not mandatory)
+#ifdef DEBUG
+	// Copy the target texture to SDL debug window (and display it, not mandatory)
 	SDL_SetRenderTarget(r, NULL);
 	SDL_RenderCopy(r, ge->sdl_target, NULL, NULL);
 	SDL_RenderPresent(r);
+	SDL_SetRenderTarget(r, ge->sdl_target);
+#endif
 	
 	// Download the rendered texture from videocard to main memory
-	SDL_SetRenderTarget(r, ge->sdl_target);
-	res = SDL_RenderReadPixels(r, NULL, 0, ge->raw_target, 256*4);
-
-	// "convert" the raw pixel stream to ASCII art on caca canevas
-	if ( res == 0 ) caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target);
+	SDL_RenderReadPixels(r, NULL, 0, ge->raw_target, FBUF_W*4);
 
 	return 0;
 }
@@ -86,6 +81,9 @@ int scene00_next_caca(graphical_env_t *ge, scene00_env_t *se) {
 	int w = ge->w, h = ge->h;
 	Uint32 frame = ge->sc_framecount;
 
+	// "convert" the raw pixel stream from SDL to ASCII art on caca canevas
+	caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target);
+
 	// Add things on top of caca canvas
 	caca_set_color_ansi(cv, CACA_BLACK, CACA_WHITE);
 	caca_put_str(cv, (w-17)/2, h/2, "This is a message");
diff --git a/src/scene01.c b/src/scene01.c
index 527e81a..7a6aed1 100644
--- a/src/scene01.c
+++ b/src/scene01.c
@@ -169,35 +169,20 @@ void scene01_free_caca(graphical_env_t *ge, scene01_env_t *se) {
 }
 
 int scene01_next_gl(graphical_env_t *ge, scene01_env_t *se) {
-	// Shorthands
-	caca_canvas_t *cv = ge->cv;
-	int w = ge->w, h = ge->h;
-	SDL_Renderer *r = ge->sdl_rndr;
-	// Local vars
-	int res;
+	SDL_Renderer *r = ge->gl_rndr;
 
 	// https://gist.github.com/Twinklebear/8265888
 	// https://forums.libsdl.org/viewtopic.php?p=51634
 
-	// Render all the stuff on target texture
-	SDL_SetRenderTarget(r, ge->sdl_target);
-
-	glClear( GL_COLOR_BUFFER_BIT );
-	glBindVertexArray( se->vao );
-	glDrawArrays( GL_TRIANGLES, 0, 6 );
+	glClear(GL_COLOR_BUFFER_BIT);
+	glBindVertexArray(se->vao);
+	glDrawArrays(GL_TRIANGLES, 0, 6);
+	// [...]
 
-	// Copy the SDL screen to SDL debug window (and display it, not mandatory)
-	SDL_SetRenderTarget(r, NULL);
-	SDL_RenderCopy(r, ge->sdl_target, NULL, NULL);
-	SDL_RenderPresent(r);
+	SDL_GL_SwapWindow(ge->gl_win);
 	
 	// Download the rendered texture from videocard to main memory
-	SDL_SetRenderTarget(r, ge->sdl_target);
-	res = SDL_RenderReadPixels(r, NULL, 0, ge->raw_target, 256*4);
-
-	// "convert" the raw pixel stream to ASCII art on caca canevas
-	caca_set_dither_gamma(ge->d, 1.0);
-	if ( res == 0 ) caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target);
+	SDL_RenderReadPixels(r, NULL, 0, ge->raw_target, FBUF_W*4);
 
 	return 0;
 }
@@ -212,6 +197,11 @@ int scene01_next_caca(graphical_env_t *ge, scene01_env_t *se) {
 	int w = ge->w, h = ge->h;
 	Uint32 frame = ge->sc_framecount;
 
+	// "convert" the raw pixel stream from SDL to ASCII art on caca canevas
+	caca_set_dither_gamma(ge->d, 1.0);
+	caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target);
+
+	// Add things on top of caca canvas
 	caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK);
 	caca_put_str(cv, (w-17)/2, h/2, "This is a message");
 
-- 
cgit v1.2.3