summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2019-09-05 23:09:28 +0200
committerLudovic Pouzenc <ludovic@pouzenc.fr>2019-09-05 23:09:28 +0200
commit5fc35fb36f6658dc486bf2c5e05510c575f3efec (patch)
treea6e974ada149c65db790e6f20a1d5a08f90436d3
parent818ce700109c959bb670b48e2b6a7e2adaafeb1c (diff)
downloaddemoscene-eo-5fc35fb36f6658dc486bf2c5e05510c575f3efec.tar.gz
demoscene-eo-5fc35fb36f6658dc486bf2c5e05510c575f3efec.tar.bz2
demoscene-eo-5fc35fb36f6658dc486bf2c5e05510c575f3efec.zip
Unfinished integration of multi-process approach
-rw-r--r--Makefile2
-rw-r--r--src/main.c362
-rw-r--r--src/main.h15
-rw-r--r--src/scene00.c17
-rw-r--r--src/scene00.h4
-rw-r--r--src/scene01.c248
-rw-r--r--src/scene01.h4
-rw-r--r--src/scene02.c10
-rw-r--r--src/scene02.h4
9 files changed, 445 insertions, 221 deletions
diff --git a/Makefile b/Makefile
index 41a09e5..5b0297c 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ server: demoscene-eo
demoscene-eo: src/main.c src/main.h $(wildcard src/scene*.[ch]) Makefile
pkg-config --libs --cflags $(PKGLIBS)
- gcc $(CFLAGS) `pkg-config --libs --cflags $(PKGLIBS)` src/main.c $(wildcard src/scene*.c) -o $@
+ gcc $(CFLAGS) `pkg-config --libs --cflags $(PKGLIBS)` src/main.c $(wildcard src/scene*.c) -pthread -o $@
clean:
rm -f demoscene-eo
diff --git a/src/main.c b/src/main.c
index 3f18052..94d6195 100644
--- a/src/main.c
+++ b/src/main.c
@@ -18,127 +18,178 @@
* along with demoscene-eo. If not, see <http://www.gnu.org/licenses/>
*/
#include "main.h"
-#include "scene00.h"
-#include "scene01.h"
-#include "scene02.h"
+
+#include <stdlib.h> // calloc()
+#include <strings.h> // bzero()
+#include <sys/mman.h> // mmap()
+#include <semaphore.h> // sem_t, sem_init(), Link with -pthread
+#include <unistd.h> // fork()
+#include <sys/wait.h> // wait()
+#include <errno.h> // errno
+#include <stdint.h> // uint32_t
+#include <stdio.h> // printf()
+
+#define TRACE(hint) printf("%s(): %s\n", __func__, hint)
#define SCENE_COUNT 3
-#define SCENE_NEXT do { scene = (scene+1)%SCENE_COUNT; } while(0)
+#define SCENE_NEXT do { shm->scene = (shm->scene+1)%SCENE_COUNT; } while(0)
-#define EXPR_MIN_SIZE ( ge.w<80 || ge.h<25 )
+#define EXPR_MIN_SIZE ( shm->ge.w<80 || shm->ge.h<25 )
#define TEXT_MIN_SIZE "80x25"
-int main(void)
-{
- int done=0, lastscene=-1, scene=0, paused=0, res;
- Uint32 sdl_win_flags = SDL_WINDOW_OPENGL;
+#define SEM_POST(sem,errcode) \
+ do { \
+ printf("%s(): sem_post(%s,%i) call\n", __func__, #sem, errcode);\
+ if ( sem_post(sem) == -1 ) { return errcode; } \
+ printf("%s(): sem_post(%s,%i) done\n", __func__, #sem, errcode);\
+ } while(0)
+
+#define SEM_WAIT(sem,errcode) \
+ do { \
+ printf("%s(): sem_wait(%s,%i) call\n", __func__, #sem, errcode);\
+ while ( sem_wait(&shm->parent_can_read_result) == -1 ) { \
+ switch(errno) { \
+ case EINTR: \
+ case EAGAIN: \
+ break; \
+ default: \
+ return errcode; \
+ } \
+ } \
+ printf("%s(): sem_wait(%s,%i) done\n", __func__, #sem, errcode);\
+ } while(0)
+
+typedef struct {
+ sem_t worker_gl_can_render, worker_sdl_can_render, parent_can_read_result;
+ int scene, paused, done;
graphical_env_t ge;
scene00_env_t s00e;
scene01_env_t s01e;
scene02_env_t s02e;
+} shm_t;
- caca_event_t caca_ev;
- SDL_RendererInfo renderer_info;
- SDL_Event sdl_ev;
+int do_fork1();
+int do_fork2();
+int parent();
+int worker_sdl();
+int worker_gl();
- // Initialize libcaca (http://caca.zoy.org/doxygen/libcaca/caca_8h.html)
- ge.dp = caca_create_display(NULL);
- if(!ge.dp) return 1;
- caca_set_display_title(ge.dp, "demoscene-eo");
- caca_set_display_time(ge.dp, 16666); // 1e6µs/60 = 16666.66... It is ~60 fps
- ge.cv = caca_get_canvas(ge.dp);
+shm_t *shm;
- ge.d = caca_create_dither(32, 256, 256, 256*4, 0x00ff0000, 0x0000ff00, 0x000000ff, 0);
- if ( !ge.d ) return 2;
- caca_set_dither_color(ge.d, "16");
+int main() {
+ TRACE("call");
+ shm = mmap(NULL, sizeof(shm_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
+ if ( shm == NULL ) return 1;
+ bzero(shm, sizeof(shm_t));
- // Initialize SDL (http://wiki.libsdl.org/SDL_CreateWindowAndRenderer)
- // Useful snippet : https://gist.github.com/koute/7391344
- res = SDL_Init(SDL_INIT_VIDEO);
- if ( res == -1) return 3;
- SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
- SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 );
- SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
- SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
- SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
- SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
- SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
- SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
- SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
+ if (sem_init(&shm->worker_gl_can_render, 1, 0) < 0) return 2;
+ if (sem_init(&shm->worker_sdl_can_render, 1, 0) < 0) return 3;
+ if (sem_init(&shm->parent_can_read_result, 1, 0) < 0) return 4;
- //XXX for final version, consider sdl_win_flags |= SDL_WINDOW_HIDDEN;
- res = SDL_CreateWindowAndRenderer(256, 256, sdl_win_flags, &ge.sdl_win, &ge.sdl_rndr);
- if ( res == -1) return 4;
- SDL_SetWindowTitle(ge.sdl_win, "SDL/GL debug");
- res = SDL_GetRendererInfo(ge.sdl_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;
- ge.sdl_target = SDL_CreateTexture(ge.sdl_rndr, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 256, 256);
- if ( ge.sdl_target == NULL ) return 9;
- ge.raw_target = malloc(256*256*4);
- if ( ge.raw_target == NULL ) return 10;
+ shm->ge.raw_target = calloc(FBUF_W*FBUF_H, sizeof(uint32_t));
+ if ( shm->ge.raw_target == NULL ) return 5;
- // Initialize OpenGL
- ge.gl_ctx = SDL_GL_CreateContext(ge.sdl_win);
- if ( ge.gl_ctx == NULL ) return 11;
+ return do_fork1();
+}
- // Main libcaca loop for caca window (OpenGL could be used in sceneN_next())
- ge.framecount=0;
+int do_fork1() {
+ TRACE("call");
+ switch (fork()) {
+ case -1: return 4; break;
+ case 0: return worker_sdl(); break;
+ default: return do_fork2(); break;
+ }
+}
+
+int do_fork2() {
+ TRACE("call");
+ switch (fork()) {
+ case -1: return 5; break;
+ case 0: return worker_gl(); break;
+ default: return parent(); break;
+ }
+}
+
+int parent() {
+ int lastscene=-1, res, child_status;
+ caca_event_t caca_ev;
+
+ TRACE("call");
+
+ // Initialize libcaca (http://caca.zoy.org/doxygen/libcaca/caca_8h.html)
+ shm->ge.dp = caca_create_display(NULL);
+ if(!shm->ge.dp) return 1;
+ caca_set_display_title(shm->ge.dp, "demoscene-eo");
+ caca_set_display_time(shm->ge.dp, 16666); // 1e6µs/60 = 16666.66... It is ~60 fps
+ shm->ge.cv = caca_get_canvas(shm->ge.dp);
+
+ shm->ge.d = caca_create_dither(32, FBUF_W, FBUF_H, FBUF_W*4, 0x00ff0000, 0x0000ff00, 0x000000ff, 0);
+ if ( !shm->ge.d ) return 2;
+ caca_set_dither_color(shm->ge.d, "16");
+
+ // Main libcaca loop for caca window
+ shm->ge.framecount=0;
do {
// Check canvas size at every frame because of unreliable CACA_EVENT_RESIZE
- ge.w = caca_get_canvas_width(ge.cv);
- ge.h = caca_get_canvas_height(ge.cv);
+ shm->ge.w = caca_get_canvas_width(shm->ge.cv);
+ shm->ge.h = caca_get_canvas_height(shm->ge.cv);
if ( EXPR_MIN_SIZE ) {
- caca_set_color_ansi(ge.cv, CACA_BLACK, CACA_WHITE);
- caca_put_str(ge.cv, 0, 0, "Need a minimum of " TEXT_MIN_SIZE " terminal");
- } else if (!paused) {
+ caca_set_color_ansi(shm->ge.cv, CACA_BLACK, CACA_WHITE);
+ caca_put_str(shm->ge.cv, 0, 0, "Need a minimum of " TEXT_MIN_SIZE " terminal");
+ } else if (!shm->paused) {
// init / free if scene transition
- if ( lastscene != scene ) {
+ if ( lastscene != shm->scene ) {
switch(lastscene) {
- case 0: scene00_free(&ge, &s00e); break;
- case 1: scene01_free(&ge, &s01e); break;
- case 2: scene02_free(&ge, &s02e); break;
+ case 0: scene00_free(&shm->ge, &shm->s00e); break;
+ case 1: scene01_free(&shm->ge, &shm->s01e); break;
+ case 2: scene02_free(&shm->ge, &shm->s02e); break;
}
}
- while ( lastscene != scene ) {
- ge.sdl_ticks = SDL_GetTicks();
- ge.sc_framecount = 0;
- switch(scene) {
- case 0: res = scene00_init(&ge, &s00e); break;
- case 1: res = scene01_init(&ge, &s01e); break;
- case 2: res = scene02_init(&ge, &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(&shm->ge, &shm->s00e); break;
+ case 1: res = scene01_init(&shm->ge, &shm->s01e); break;
+ case 2: res = scene02_init(&shm->ge, &shm->s02e); break;
}
// If scene init fail, skip to the next one
- if (res) SCENE_NEXT; else lastscene = scene;
+ if (res) SCENE_NEXT; else lastscene = shm->scene;
}
- // Compute current scene0 frame
- ge.sdl_ticks = SDL_GetTicks(); // This value wraps if the program runs for more than ~49 days
- switch(scene) {
- case 0: res = scene00_next(&ge, &s00e); break;
- case 1: res = scene01_next(&ge, &s01e); break;
- case 2: res = scene02_next(&ge, &s02e); break;
+ shm->ge.sdl_ticks = SDL_GetTicks(); // This value wraps if the program runs for more than ~49 days
+
+ SEM_POST(&shm->worker_gl_can_render,30);
+ SEM_WAIT(&shm->parent_can_read_result,31);
+
+ SEM_POST(&shm->worker_sdl_can_render,32);
+ SEM_WAIT(&shm->parent_can_read_result,33);
+
+ // Compute current scene frame (caca part)
+ switch(shm->scene) {
+ case 0: res = scene00_next_caca(&shm->ge, &shm->s00e); break;
+ case 1: res = scene01_next_caca(&shm->ge, &shm->s01e); break;
+ case 2: res = scene02_next_caca(&shm->ge, &shm->s02e); break;
}
if (res) SCENE_NEXT;
- ge.framecount++;
- ge.sc_framecount++;
+ shm->ge.framecount++;
+ shm->ge.sc_framecount++;
}
// Display it
- caca_refresh_display(ge.dp); // Auto framerate limiting (see caca_set_display_time())
+ caca_refresh_display(shm->ge.dp); // Auto framerate limiting (see caca_set_display_time())
// Event handling for the libcaca "window" (depending on CACA_DRIVER env variable)
- if ( caca_get_event(ge.dp, CACA_EVENT_KEY_PRESS|CACA_EVENT_RESIZE|CACA_EVENT_QUIT, &caca_ev, 0) ) {
+ if ( caca_get_event(shm->ge.dp, CACA_EVENT_KEY_PRESS|CACA_EVENT_RESIZE|CACA_EVENT_QUIT, &caca_ev, 0) ) {
switch(caca_get_event_type(&caca_ev)) {
case CACA_EVENT_QUIT:
- done = 1;
+ shm->done = 1;
break;
case CACA_EVENT_KEY_PRESS:
switch(caca_get_event_key_ch(&caca_ev)) {
- case 'q': done = 1; break;
- case 'p': paused = !paused; break;
+ case 'q': shm->done = 1; break;
+ case 'p': shm->paused = !shm->paused; break;
case CACA_KEY_ESCAPE: SCENE_NEXT; break;
}
break;
- /* On Debian 10, no CACA_EVENT_RESIZE when using x11 CACA_DRIVER
+ /* On Debian 10, no CACA_EVENT_RESIZE fired when using x11 CACA_DRIVER
case CACA_EVENT_RESIZE:
w = caca_get_event_resize_width(&caca_ev);
h = caca_get_event_resize_height(&caca_ev);
@@ -149,16 +200,68 @@ int main(void)
break;
}
}
- // Event handling for the SDL/GL window (debug purposes)
+ } while(!shm->done);
+
+ caca_free_dither(shm->ge.d);
+ caca_free_display(shm->ge.dp);
+ shm->ge.cv=NULL;
+
+ // reap forked processes (order doesn't matter)
+ if ( wait(&child_status) != -1 ) {
+ if ( child_status > 0 ) return child_status;
+ }
+ if ( wait(&child_status) != -1 ) {
+ if ( child_status > 0 ) return child_status;
+ }
+ return 0;
+}
+
+int worker_sdl() {
+ int res;
+ Uint32 sdl_win_flags = 0; //XXX for final version, consider sdl_win_flags = SDL_WINDOW_HIDDEN;
+ SDL_RendererInfo renderer_info;
+ SDL_Event sdl_ev;
+
+ TRACE("call");
+
+ // Initialize SDL (http://wiki.libsdl.org/SDL_CreateWindowAndRenderer)
+ // Useful snippet : https://gist.github.com/koute/7391344
+ res = SDL_Init(SDL_INIT_VIDEO);
+ if ( res == -1) return 3;
+ atexit(SDL_Quit);
+
+ res = SDL_CreateWindowAndRenderer(FBUF_W, FBUF_H, sdl_win_flags, &shm->ge.sdl_win, &shm->ge.sdl_rndr);
+ if ( res == -1) return 4;
+ SDL_SetWindowTitle(shm->ge.sdl_win, "SDL debug");
+ res = SDL_GetRendererInfo(shm->ge.sdl_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.sdl_target = SDL_CreateTexture(shm->ge.sdl_rndr, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, FBUF_W, FBUF_H);
+ if ( shm->ge.sdl_target == NULL ) return 9;
+
+ while ( !shm->done ) {
+ //FIXME change for TRYWAIT for event handling (+delay)
+ SEM_WAIT(&shm->worker_sdl_can_render,20);
+
+ // Compute current scene frame (sdl part)
+ switch(shm->scene) {
+ case 0: res = scene00_next_sdl(&shm->ge, &shm->s00e); break;
+ case 1: res = scene01_next_sdl(&shm->ge, &shm->s01e); break;
+ case 2: res = scene02_next_sdl(&shm->ge, &shm->s02e); break;
+ }
+ if (res) SCENE_NEXT;
+
+ // Event handling for the SDL window (debug purposes)
while(SDL_PollEvent(&sdl_ev)) {
switch(sdl_ev.type) {
case SDL_QUIT:
- done = 1;
+ shm->done = 1;
break;
case SDL_KEYDOWN:
switch(sdl_ev.key.keysym.sym) {
- case SDLK_q: done = 1; break;
- case SDLK_p: paused = !paused; break;
+ case SDLK_q: shm->done = 1; break;
+ case SDLK_p: shm->paused = !shm->paused; break;
case SDLK_ESCAPE: SCENE_NEXT; break;
}
break;
@@ -166,15 +269,82 @@ int main(void)
break;
}
}
- } while(!done);
-
- caca_free_dither(ge.d);
- caca_free_display(ge.dp);
- ge.cv=NULL;
- SDL_GL_DeleteContext(ge.gl_ctx);
- SDL_DestroyTexture(ge.sdl_target);
- SDL_DestroyRenderer(ge.sdl_rndr);
- SDL_DestroyWindow(ge.sdl_win);
- SDL_Quit();
+
+ SEM_POST(&shm->parent_can_read_result, 21);
+ }
+
+ SDL_DestroyRenderer(shm->ge.sdl_rndr);
+ SDL_DestroyTexture(shm->ge.sdl_target);
+ SDL_DestroyWindow(shm->ge.sdl_win);
+
+ return 0;
+}
+
+int worker_gl() {
+ int res;
+ //Uint32 sdl_win_flags = SDL_WINDOW_OPENGL;
+ SDL_Event gl_ev;
+
+ TRACE("call");
+
+ // Initialize SDL (http://wiki.libsdl.org/SDL_CreateWindowAndRenderer)
+ // Useful snippet : https://gist.github.com/koute/7391344
+ res = SDL_Init(SDL_INIT_VIDEO);
+ if ( res == -1) return 3;
+ atexit(SDL_Quit);
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 );
+ SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
+ SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
+ SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
+ SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
+ SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
+ SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
+ SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
+
+ // Initialize OpenGL
+ shm->ge.gl_win = SDL_CreateWindow("GL Debug", 0, SDL_WINDOWPOS_CENTERED, FBUF_W, FBUF_H, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
+ shm->ge.gl_ctx = SDL_GL_CreateContext(shm->ge.gl_win);
+ if ( shm->ge.gl_ctx == NULL ) return 11;
+
+ while ( !shm->done ) {
+ //FIXME change for TRYWAIT for event handling (+delay)
+ SEM_WAIT(&shm->worker_gl_can_render,10);
+
+ // Compute current scene frame (gl part)
+ switch(shm->scene) {
+ case 0: res = scene00_next_gl(&shm->ge, &shm->s00e); break;
+ case 1: res = scene01_next_gl(&shm->ge, &shm->s01e); break;
+ case 2: res = scene02_next_gl(&shm->ge, &shm->s02e); break;
+ }
+ if (res) SCENE_NEXT;
+
+
+ // Event handling for the GL window (debug purposes)
+ while(SDL_PollEvent(&gl_ev)) {
+ switch(gl_ev.type) {
+ case SDL_QUIT:
+ shm->done = 1;
+ break;
+ case SDL_KEYDOWN:
+ switch(gl_ev.key.keysym.sym) {
+ case SDLK_q: shm->done = 1; break;
+ case SDLK_p: shm->paused = !shm->paused; break;
+ case SDLK_ESCAPE: SCENE_NEXT; break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ SEM_POST(&shm->parent_can_read_result, 11);
+ }
+
+ //SDL_DestroyTexture(shm->ge.gl_target);
+ SDL_GL_DeleteContext(shm->ge.gl_ctx);
+ SDL_DestroyWindow(shm->ge.gl_win);
+
return 0;
}
diff --git a/src/main.h b/src/main.h
index 1ff41ec..907bc53 100644
--- a/src/main.h
+++ b/src/main.h
@@ -9,17 +9,30 @@
#include <GL/glu.h>
typedef struct {
+ // libcaca
caca_display_t *dp;
caca_canvas_t *cv;
caca_dither_t *d;
int w, h; // caca terminal size in characters
+ // SDL worker
SDL_Window* sdl_win;
SDL_Renderer *sdl_rndr;
SDL_Texture *sdl_target;
- void *raw_target;
+ // OpenGL worker
+ SDL_Window* gl_win;
SDL_GLContext gl_ctx;
+ // framebuffer to inject OpenGL or SDL result in caca canvas
+ uint32_t *raw_target;
+ // Timing
Uint32 sdl_ticks;
Uint32 framecount;
Uint32 sc_framecount;
} graphical_env_t;
+
+#define FBUF_W 256
+#define FBUF_H 256
+
+#include "scene00.h"
+#include "scene01.h"
+#include "scene02.h"
#endif
diff --git a/src/scene00.c b/src/scene00.c
index 746db29..7bb1738 100644
--- a/src/scene00.c
+++ b/src/scene00.c
@@ -31,11 +31,14 @@ void scene00_free(graphical_env_t *ge, scene00_env_t *se) {
SDL_DestroyTexture(se->eo1); se->eo1=NULL;
}
-int scene00_next(graphical_env_t *ge, scene00_env_t *se) {
+int scene00_next_gl(graphical_env_t *ge, scene00_env_t *se) {
+ return 0;
+}
+
+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;
- Uint32 frame = ge->sc_framecount;
SDL_Renderer *r = ge->sdl_rndr;
// Local vars
int res;
@@ -54,11 +57,21 @@ int scene00_next(graphical_env_t *ge, scene00_env_t *se) {
SDL_RenderPresent(r);
// 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);
+ return 0;
+}
+
+int scene00_next_caca(graphical_env_t *ge, scene00_env_t *se) {
+ // Shorthands
+ caca_canvas_t *cv = ge->cv;
+ int w = ge->w, h = ge->h;
+ Uint32 frame = ge->sc_framecount;
+
// 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/scene00.h b/src/scene00.h
index b1c9d9d..ec6eb9a 100644
--- a/src/scene00.h
+++ b/src/scene00.h
@@ -8,5 +8,7 @@ typedef struct {
int scene00_init(graphical_env_t *ge, scene00_env_t *se);
void scene00_free(graphical_env_t *ge, scene00_env_t *se);
-int scene00_next(graphical_env_t *ge, scene00_env_t *se);
+int scene00_next_gl(graphical_env_t *ge, scene00_env_t *se);
+int scene00_next_sdl(graphical_env_t *ge, scene00_env_t *se);
+int scene00_next_caca(graphical_env_t *ge, scene00_env_t *se);
#endif
diff --git a/src/scene01.c b/src/scene01.c
index 80cbae2..b817e71 100644
--- a/src/scene01.c
+++ b/src/scene01.c
@@ -24,130 +24,129 @@ typedef float t_mat4x4[16];
static inline void mat4x4_ortho( t_mat4x4 out, float left, float right, float bottom, float top, float znear, float zfar )
{
- #define T(a, b) (a * 4 + b)
+ #define T(a, b) (a * 4 + b)
- out[T(0,0)] = 2.0f / (right - left);
- out[T(0,1)] = 0.0f;
- out[T(0,2)] = 0.0f;
- out[T(0,3)] = 0.0f;
+ out[T(0,0)] = 2.0f / (right - left);
+ out[T(0,1)] = 0.0f;
+ out[T(0,2)] = 0.0f;
+ out[T(0,3)] = 0.0f;
- out[T(1,1)] = 2.0f / (top - bottom);
- out[T(1,0)] = 0.0f;
- out[T(1,2)] = 0.0f;
- out[T(1,3)] = 0.0f;
+ out[T(1,1)] = 2.0f / (top - bottom);
+ out[T(1,0)] = 0.0f;
+ out[T(1,2)] = 0.0f;
+ out[T(1,3)] = 0.0f;
- out[T(2,2)] = -2.0f / (zfar - znear);
- out[T(2,0)] = 0.0f;
- out[T(2,1)] = 0.0f;
- out[T(2,3)] = 0.0f;
+ out[T(2,2)] = -2.0f / (zfar - znear);
+ out[T(2,0)] = 0.0f;
+ out[T(2,1)] = 0.0f;
+ out[T(2,3)] = 0.0f;
- out[T(3,0)] = -(right + left) / (right - left);
- out[T(3,1)] = -(top + bottom) / (top - bottom);
- out[T(3,2)] = -(zfar + znear) / (zfar - znear);
- out[T(3,3)] = 1.0f;
+ out[T(3,0)] = -(right + left) / (right - left);
+ out[T(3,1)] = -(top + bottom) / (top - bottom);
+ out[T(3,2)] = -(zfar + znear) / (zfar - znear);
+ out[T(3,3)] = 1.0f;
- #undef T
+ #undef T
}
static const char * vertex_shader =
- "#version 130\n"
- "in vec2 i_position;\n"
- "in vec4 i_color;\n"
- "out vec4 v_color;\n"
- "uniform mat4 u_projection_matrix;\n"
- "void main() {\n"
- " v_color = i_color;\n"
- " gl_Position = u_projection_matrix * vec4( i_position, 0.0, 1.0 );\n"
- "}\n";
+ "#version 130\n"
+ "in vec2 i_position;\n"
+ "in vec4 i_color;\n"
+ "out vec4 v_color;\n"
+ "uniform mat4 u_projection_matrix;\n"
+ "void main() {\n"
+ " v_color = i_color;\n"
+ " gl_Position = u_projection_matrix * vec4( i_position, 0.0, 1.0 );\n"
+ "}\n";
static const char * fragment_shader =
- "#version 130\n"
- "in vec4 v_color;\n"
- "out vec4 o_color;\n"
- "void main() {\n"
- " o_color = v_color;\n"
- "}\n";
+ "#version 130\n"
+ "in vec4 v_color;\n"
+ "out vec4 o_color;\n"
+ "void main() {\n"
+ " o_color = v_color;\n"
+ "}\n";
typedef enum t_attrib_id
{
- attrib_position,
- attrib_color
+ attrib_position,
+ attrib_color
} t_attrib_id;
int scene01_init(graphical_env_t *ge, scene01_env_t *se) {
- int width = 256, height = 256;
- GLuint vs, fs, program;
-
- vs = glCreateShader( GL_VERTEX_SHADER );
- fs = glCreateShader( GL_FRAGMENT_SHADER );
-
- int length = strlen( vertex_shader );
- glShaderSource( vs, 1, ( const GLchar ** )&vertex_shader, &length );
- glCompileShader( vs );
-
- GLint status;
- glGetShaderiv( vs, GL_COMPILE_STATUS, &status );
- if( status == GL_FALSE )
- {
- fprintf( stderr, "vertex shader compilation failed\n" );
- return 1;
- }
-
- length = strlen( fragment_shader );
- glShaderSource( fs, 1, ( const GLchar ** )&fragment_shader, &length );
- glCompileShader( fs );
-
- glGetShaderiv( fs, GL_COMPILE_STATUS, &status );
- if( status == GL_FALSE )
- {
- fprintf( stderr, "fragment shader compilation failed\n" );
- return 1;
- }
-
- program = glCreateProgram();
- glAttachShader( program, vs );
- glAttachShader( program, fs );
-
- glBindAttribLocation( program, attrib_position, "i_position" );
- glBindAttribLocation( program, attrib_color, "i_color" );
- glLinkProgram( program );
-
- glUseProgram( program );
-
- glDisable( GL_DEPTH_TEST );
- //glClearColor( 0.5, 0.0, 0.0, 0.0 );
- glClearColor( 0.5, 0.5, 0.0, 0.0 );
- glViewport( 0, 0, width, height );
-
- GLuint vbo;
-
- glGenVertexArrays( 1, &(se->vao) );
- glGenBuffers( 1, &vbo );
- glBindVertexArray( se->vao );
- glBindBuffer( GL_ARRAY_BUFFER, vbo );
-
- glEnableVertexAttribArray( attrib_position );
- glEnableVertexAttribArray( attrib_color );
-
- glVertexAttribPointer( attrib_color, 4, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, 0 );
- glVertexAttribPointer( attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, ( void * )(4 * sizeof(float)) );
-
- const GLfloat g_vertex_buffer_data[] = {
- /* R, G, B, A, X, Y */
- 1, 0, 0, 1, 0, 0,
- 0, 1, 0, 1, width, 0,
- 0, 0, 1, 1, width, height,
-
- 1, 0, 0, 1, 0, 0,
- 0, 0, 1, 1, width, height,
- 1, 1, 1, 1, 0, height
- };
-
- glBufferData( GL_ARRAY_BUFFER, sizeof( g_vertex_buffer_data ), g_vertex_buffer_data, GL_STATIC_DRAW );
-
- t_mat4x4 projection_matrix;
- mat4x4_ortho( projection_matrix, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 100.0f );
- glUniformMatrix4fv( glGetUniformLocation( program, "u_projection_matrix" ), 1, GL_FALSE, projection_matrix );
+ GLuint vs, fs, program;
+
+ vs = glCreateShader( GL_VERTEX_SHADER );
+ fs = glCreateShader( GL_FRAGMENT_SHADER );
+
+ int length = strlen( vertex_shader );
+ glShaderSource( vs, 1, ( const GLchar ** )&vertex_shader, &length );
+ glCompileShader( vs );
+
+ GLint status;
+ glGetShaderiv( vs, GL_COMPILE_STATUS, &status );
+ if( status == GL_FALSE )
+ {
+ fprintf( stderr, "vertex shader compilation failed\n" );
+ return 1;
+ }
+
+ length = strlen( fragment_shader );
+ glShaderSource( fs, 1, ( const GLchar ** )&fragment_shader, &length );
+ glCompileShader( fs );
+
+ glGetShaderiv( fs, GL_COMPILE_STATUS, &status );
+ if( status == GL_FALSE )
+ {
+ fprintf( stderr, "fragment shader compilation failed\n" );
+ return 1;
+ }
+
+ program = glCreateProgram();
+ glAttachShader( program, vs );
+ glAttachShader( program, fs );
+
+ glBindAttribLocation( program, attrib_position, "i_position" );
+ glBindAttribLocation( program, attrib_color, "i_color" );
+ glLinkProgram( program );
+
+ glUseProgram( program );
+
+ glDisable( GL_DEPTH_TEST );
+ //glClearColor( 0.5, 0.0, 0.0, 0.0 );
+ glClearColor( 0.5, 0.5, 0.0, 0.0 );
+ glViewport( 0, 0, FBUF_W, FBUF_H );
+
+ GLuint vbo;
+
+ glGenVertexArrays( 1, &(se->vao) );
+ glGenBuffers( 1, &vbo );
+ glBindVertexArray( se->vao );
+ glBindBuffer( GL_ARRAY_BUFFER, vbo );
+
+ glEnableVertexAttribArray( attrib_position );
+ glEnableVertexAttribArray( attrib_color );
+
+ glVertexAttribPointer( attrib_color, 4, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, 0 );
+ glVertexAttribPointer( attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, ( void * )(4 * sizeof(float)) );
+
+ const GLfloat g_vertex_buffer_data[] = {
+ /* R, G, B, A, X, Y */
+ 1, 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, FBUF_W, 0,
+ 0, 0, 1, 1, FBUF_W, FBUF_H,
+
+ 1, 0, 0, 1, 0, 0,
+ 0, 0, 1, 1, FBUF_W, FBUF_H,
+ 1, 1, 1, 1, 0, FBUF_H
+ };
+
+ glBufferData( GL_ARRAY_BUFFER, sizeof( g_vertex_buffer_data ), g_vertex_buffer_data, GL_STATIC_DRAW );
+
+ t_mat4x4 projection_matrix;
+ mat4x4_ortho( projection_matrix, 0.0f, (float)FBUF_W, (float)FBUF_H, 0.0f, 0.0f, 100.0f );
+ glUniformMatrix4fv( glGetUniformLocation( program, "u_projection_matrix" ), 1, GL_FALSE, projection_matrix );
return 0;
}
@@ -155,35 +154,50 @@ void scene01_free(graphical_env_t *ge, scene01_env_t *se) {
//FIXME scene00 cannot be rendered coorectly after scene01_init done once
}
-int scene01_next(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;
- Uint32 frame = ge->sc_framecount;
SDL_Renderer *r = ge->sdl_rndr;
- // Locals
+ // Local vars
int res;
+ // 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);
+ SDL_SetRenderTarget(r, ge->sdl_target);
glClear( GL_COLOR_BUFFER_BIT );
glBindVertexArray( se->vao );
glDrawArrays( GL_TRIANGLES, 0, 6 );
- SDL_GL_SwapWindow( ge->sdl_win );
// 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_SetRenderTarget(r, NULL);
+ SDL_RenderCopy(r, ge->sdl_target, NULL, NULL);
+ SDL_RenderPresent(r);
// 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, (100-frame%100)/100.0);
+ caca_set_dither_gamma(ge->d, 1.0);
if ( res == 0 ) caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target);
+ return 0;
+}
+
+int scene01_next_sdl(graphical_env_t *ge, scene01_env_t *se) {
+ return 0;
+}
+
+int scene01_next_caca(graphical_env_t *ge, scene01_env_t *se) {
+ // Shorthands
+ caca_canvas_t *cv = ge->cv;
+ int w = ge->w, h = ge->h;
+ Uint32 frame = ge->sc_framecount;
+
caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK);
caca_put_str(cv, (w-17)/2, h/2, "This is a message");
diff --git a/src/scene01.h b/src/scene01.h
index ecad8df..f6544fb 100644
--- a/src/scene01.h
+++ b/src/scene01.h
@@ -8,5 +8,7 @@ typedef struct {
int scene01_init(graphical_env_t *ge, scene01_env_t *se);
void scene01_free(graphical_env_t *ge, scene01_env_t *se);
-int scene01_next(graphical_env_t *ge, scene01_env_t *se);
+int scene01_next_gl(graphical_env_t *ge, scene01_env_t *se);
+int scene01_next_sdl(graphical_env_t *ge, scene01_env_t *se);
+int scene01_next_caca(graphical_env_t *ge, scene01_env_t *se);
#endif
diff --git a/src/scene02.c b/src/scene02.c
index 1989bf0..e8e7340 100644
--- a/src/scene02.c
+++ b/src/scene02.c
@@ -26,7 +26,15 @@ int scene02_init(graphical_env_t *ge, scene02_env_t *se) {
void scene02_free(graphical_env_t *ge, scene02_env_t *se) {
}
-int scene02_next(graphical_env_t *ge, scene02_env_t *se) {
+int scene02_next_gl(graphical_env_t *ge, scene02_env_t *se) {
+ return 0;
+}
+
+int scene02_next_sdl(graphical_env_t *ge, scene02_env_t *se) {
+ return 0;
+}
+
+int scene02_next_caca(graphical_env_t *ge, scene02_env_t *se) {
// Shorthands
caca_canvas_t *cv = ge->cv;
//int w = ge->w, h = ge->h;
diff --git a/src/scene02.h b/src/scene02.h
index 49abbfb..7032d50 100644
--- a/src/scene02.h
+++ b/src/scene02.h
@@ -8,5 +8,7 @@ typedef struct {
int scene02_init(graphical_env_t *ge, scene02_env_t *se);
void scene02_free(graphical_env_t *ge, scene02_env_t *se);
-int scene02_next(graphical_env_t *ge, scene02_env_t *se);
+int scene02_next_gl(graphical_env_t *ge, scene02_env_t *se);
+int scene02_next_sdl(graphical_env_t *ge, scene02_env_t *se);
+int scene02_next_caca(graphical_env_t *ge, scene02_env_t *se);
#endif