What happened to the Emscripten branch?

Emscripten, WASM, and asm.js related questions
Post Reply
VANYA
Posts: 1839
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: What happened to the Emscripten branch?

Post by VANYA »

angros47, Good job!

@CoderJeff
I have no right to advise you. However, angros47 is still the only one who implements patches for the emscripten port. Is there some way to give him access to the page for editing? This will allow him to quickly make changes to this port without distracting you once more.
angros47
Posts: 2331
Joined: Jun 21, 2005 19:04

Re: What happened to the Emscripten branch?

Post by angros47 »

Ok, this is something interesting.

New version of file gfx_driver.c in the directory src/gfxlib2/js:

Code: Select all

/* asmjs fbgfx driver */

#include "../fb_gfx.h"
#include "fb_gfx_js.h"
#include "../fb_gfx_gl.h"

JS_GFXDRIVER_CTX __fb_js_ctx =
{
    .inited = FALSE,
    .changingScreen = FALSE,
    .updated = FALSE,
    .blitting = FALSE,
    .canvas = NULL,
    .doNotCaptureKeyboard = 0,
};

static void driver_exit(void);

static void driver_blit()
{

    if(SDL_LockSurface(__fb_js_ctx.canvas) == 0)
    {
        __fb_js_ctx.blit(__fb_js_ctx.canvas->pixels, __fb_js_ctx.canvas->pitch);

        SDL_UnlockSurface(__fb_js_ctx.canvas);
    }

	SDL_Flip(__fb_js_ctx.canvas);

}

static void driver_update(void *unused)
{
	if( !__fb_js_ctx.inited || __fb_gfx == NULL || __fb_gfx->framebuffer == NULL )
		return;

    int ini_time = SDL_GetTicks();

	if( !__fb_js_ctx.changingScreen && !__fb_js_ctx.blitting )
    {
        __fb_js_ctx.blitting = TRUE;
        driver_blit();
        __fb_js_ctx.blitting = FALSE;

        __fb_js_ctx.updated = TRUE;

        fb_js_events_check( );
	}

	int delay = (1000/GFX_JS_FPS) - (SDL_GetTicks() - ini_time);

	emscripten_async_call(driver_update, NULL, MAX( delay, 1 ) );
}


static int driver_init(char *title, int w, int h, int depth_arg, int refresh_rate, int flags)
{
	if( w == 0 || h == 0 || depth_arg == 0 )
		return 0;

	if (flags & DRIVER_OPENGL)
		return -1;

	__fb_js_ctx.changingScreen = TRUE;

	if( !__fb_js_ctx.inited )
    {
        fb_js_events_init();
        SDL_Init(SDL_INIT_VIDEO);
    }

	if( __fb_js_ctx.canvas != NULL )
		SDL_FreeSurface(__fb_js_ctx.canvas);

	__fb_js_ctx.canvas = SDL_SetVideoMode(w, h, 32, SDL_HWSURFACE);

	__fb_js_ctx.blit = fb_hGetBlitter(__fb_js_ctx.canvas->format->BitsPerPixel, TRUE);

	__fb_js_ctx.changingScreen = FALSE;
	__fb_js_ctx.blitting = FALSE;

	int was_inited = __fb_js_ctx.inited;
	__fb_js_ctx.inited = TRUE;

	if( !was_inited )
	{
		__fb_js_ctx.updated = 0;
		emscripten_async_call(driver_update, NULL, 1000/GFX_JS_FPS);
	}

	return 0;
}

static int WGL_init(char *title, int w, int h, int depth_arg, int refresh_rate, int flags)
{
	if( w == 0 || h == 0 || depth_arg == 0 )
		return 0;

	if (!(flags & DRIVER_OPENGL))
		return -1;

	__fb_js_ctx.changingScreen = TRUE;

	if( !__fb_js_ctx.inited )
    {
        fb_js_events_init();
        SDL_Init(SDL_INIT_VIDEO);
    }

	if( __fb_js_ctx.canvas != NULL )
		SDL_FreeSurface(__fb_js_ctx.canvas);

	fb_hGL_NormalizeParameters(flags);

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, __fb_gl_params.color_red_bits); 
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, __fb_gl_params.color_green_bits);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, __fb_gl_params.color_blue_bits);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, __fb_gl_params.color_alpha_bits);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, __fb_gl_params.depth_bits);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
	__fb_js_ctx.canvas = SDL_SetVideoMode(w, h, 32, SDL_DOUBLEBUF | SDL_DOUBLEBUF | SDL_OPENGL);

	__fb_js_ctx.changingScreen = FALSE;
	__fb_js_ctx.blitting = FALSE;

	int was_inited = __fb_js_ctx.inited;
	__fb_js_ctx.inited = TRUE;

	if( !was_inited )
	{
		__fb_js_ctx.updated = 0;
		//emscripten_async_call(driver_update, NULL, 1000/GFX_JS_FPS);
	}

	return 0;
}


static void driver_exit(void)
{
	if( __fb_js_ctx.inited )
	{
		__fb_js_ctx.inited = FALSE;

		if( !__fb_js_ctx.updated )
			driver_blit();

		if( __fb_js_ctx.canvas != NULL )
		{
			SDL_FreeSurface(__fb_js_ctx.canvas);
			__fb_js_ctx.canvas = NULL;
		}

		fb_js_events_exit();

		SDL_Quit();
	}
}

static void WGL_exit(void)
{
	if( __fb_js_ctx.inited )
	{
		__fb_js_ctx.inited = FALSE;

		if( __fb_js_ctx.canvas != NULL )
		{
			SDL_FreeSurface(__fb_js_ctx.canvas);
			__fb_js_ctx.canvas = NULL;
		}

		fb_js_events_exit();

		SDL_Quit();
	}
}

static void driver_lock(void)
{
	/* !!!WRITEME!!! */
}

static void driver_unlock(void)
{
	/* !!!WRITEME!!! */
}

static void driver_wait_vsync(void)
{
	/* !!!WRITEME!!! */
	emscripten_sleep(1000/GFX_JS_FPS);
}

static void WGL_Flip(void)
{
	SDL_GL_SwapBuffers();
}

int fb_js_sdl_buttons_to_fb_buttons(int sdl_buttons)
{
	int fb_buttons = 0;

	if( sdl_buttons & SDL_BUTTON_LMASK)
        fb_buttons |= BUTTON_LEFT;
	if( sdl_buttons & SDL_BUTTON_MMASK)
        fb_buttons |= BUTTON_MIDDLE;
	if( sdl_buttons & SDL_BUTTON_RMASK)
        fb_buttons |= BUTTON_RIGHT;
	if( sdl_buttons & SDL_BUTTON_X1MASK)
        fb_buttons |= BUTTON_X1;
	if( sdl_buttons & SDL_BUTTON_X2MASK)
        fb_buttons |= BUTTON_X2;

    return fb_buttons;
}

static int driver_get_mouse(int *x, int *y, int *z, int *buttons, int *clip)
{
	SDL_PumpEvents();

	*buttons = fb_js_sdl_buttons_to_fb_buttons(SDL_GetMouseState(x, y));

	*z = 0;
	*clip = 0;

	return 0;
}

static void driver_set_mouse(int x, int y, int cursor, int clip)
{
	//SDL_WarpMouseInWindow(NULL, x, y);
}

static int modes[] = {
    SCREENLIST(640, 480),
    SCREENLIST(512, 512),
    SCREENLIST(320, 240),
    SCREENLIST(320, 200),
    SCREENLIST(320, 100),
    SCREENLIST(256, 256),
    SCREENLIST(160, 120),
    SCREENLIST(80, 80)
};

static int *driver_fetch_modes(int depth, int *size)
{
	*size = sizeof(modes) / sizeof(int);
	return memcpy((void*)malloc(sizeof(modes)), modes, sizeof(modes));
}

static void driver_poll_events(void)
{
	fb_js_events_check( );
}

static void driver_set_window_title(char *title)
{
    SDL_WM_SetCaption(title, NULL);
}

static const GFXDRIVER fb_gfxDriverJS =
{
	"asmjs",                 /* char *name; */
	driver_init,             /* int (*init)(char *title, int w, int h, int depth, int refresh_rate, int flags); */
	driver_exit,             /* void (*exit)(void); */
	driver_lock,             /* void (*lock)(void); */
	driver_unlock,           /* void (*unlock)(void); */
	NULL,                    /* void (*set_palette)(int index, int r, int g, int b); */
	driver_wait_vsync,       /* void (*wait_vsync)(void); */
	driver_get_mouse,        /* int (*get_mouse)(int *x, int *y, int *z, int *buttons, int *clip); */
	driver_set_mouse,        /* void (*set_mouse)(int x, int y, int cursor, int clip); */
	driver_set_window_title, /* void (*set_window_title)(char *title); */
	NULL,                    /* int (*set_window_pos)(int x, int y); */
	driver_fetch_modes,      /* int *(*fetch_modes)(int depth, int *size); */
	NULL,                    /* void (*flip)(void); */
	driver_poll_events       /* void (*poll_events)(void); */
};

static const GFXDRIVER fb_gfxWebGL =
{
	"WebGL",                 /* char *name; */
	WGL_init,             /* int (*init)(char *title, int w, int h, int depth, int refresh_rate, int flags); */
	WGL_exit,             /* void (*exit)(void); */
	driver_lock,             /* void (*lock)(void); */
	driver_unlock,           /* void (*unlock)(void); */
	NULL,                    /* void (*set_palette)(int index, int r, int g, int b); */
	driver_wait_vsync,       /* void (*wait_vsync)(void); */
	driver_get_mouse,        /* int (*get_mouse)(int *x, int *y, int *z, int *buttons, int *clip); */
	driver_set_mouse,        /* void (*set_mouse)(int x, int y, int cursor, int clip); */
	driver_set_window_title, /* void (*set_window_title)(char *title); */
	NULL,                    /* int (*set_window_pos)(int x, int y); */
	driver_fetch_modes,      /* int *(*fetch_modes)(int depth, int *size); */
	WGL_Flip,                    /* void (*flip)(void); */
	driver_poll_events       /* void (*poll_events)(void); */
};

const GFXDRIVER *__fb_gfx_drivers_list[] = {
	&fb_gfxDriverJS,
	&fb_gfxWebGL,
	NULL
};

void fb_hScreenInfo(ssize_t *width, ssize_t *height, ssize_t *depth, ssize_t *refresh)
{
	*width = 512;
	*height = 512;
	*depth = 32;
	*refresh = GFX_JS_FPS;
}

FBCALL int fb_GfxGetJoystick(int id, ssize_t *buttons, float *a1, float *a2, float *a3, float *a4, float *a5, float *a6, float *a7, float *a8)
{
	FB_GRAPHICS_LOCK( );

	*buttons = -1;
	*a1 = *a2 = *a3 = *a4 = *a5 = *a6 = *a7 = *a8 = -1000.0f;

	if ((id < 0) || (id >= 4)) {
		FB_GRAPHICS_UNLOCK( );
		return fb_ErrorSetNum(FB_RTERROR_ILLEGALFUNCTIONCALL);
	}

	FB_GRAPHICS_UNLOCK( );
	return fb_ErrorSetNum( FB_RTERROR_OK );
}
With these changes, it is possible to set OpenGL mode. Both drivers (SDL and OpenGL) are implemented in the same .c file, since most methods are the same.

So far, the ability to mix FreeBasic graphic and OpenGL (that I implemented in version 1.06) is still not available. Also, a different header for OpenGL functions is needed, since no external library needs to be included (Emscripten already provides all the OpenGL function)

Unless some compiling flags are set, only a subset of OpenGL is implemented in Emscripten, as explained here: https://emscripten.org/docs/porting/mul ... pport.html

Anyway, with this version of the driver it is already possible to use OpenB3D (a special version compiled for Emscripten) with FreeBasic (although there are still several bugs)
Last edited by angros47 on Nov 29, 2020 16:24, edited 1 time in total.
VANYA
Posts: 1839
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: What happened to the Emscripten branch?

Post by VANYA »

1) I have tried SDL (example examples / graphics / SDL / pixel.bas). With the ASYNCIFY option and if you add "sleep (1)" to the loop, the example works, but firstly, the speed (FPS) is several times lower. This factor makes the use of SDL impractical. Secondly, the example does not work for long, after a while "error javascript".
2) I tried OpenGL (previously removed #inclib "GL" and #include once "GL / mesa / glext.bi" in the headers). However, I could not compile because the linker does not find many necessary classical functions: glColor3f, glEnd, glFrustum, glRotatef. Perhaps these functions are not available in WEBGL.

In general, while fbgfx is an unrivaled option :) fbgfx programs work in the browser the same way as in executable files, at least I did not notice a drop in speed.
angros47
Posts: 2331
Joined: Jun 21, 2005 19:04

Re: What happened to the Emscripten branch?

Post by angros47 »

VANYA wrote:1) I have tried SDL (example examples / graphics / SDL / pixel.bas). With the ASYNCIFY option and if you add "sleep (1)" to the loop, the example works, but firstly, the speed (FPS) is several times lower. This factor makes the use of SDL impractical. Secondly, the example does not work for long, after a while "error javascript".
I guess that's why the use of ASYNCIFY is not recommended, and it is not enabled by default in Emscripten: it causes a significant drop in speed because it needs to compile in a different, less efficient code (I have read that sometimes it needs to create an interpreter in WebAssembly to run the intermediate code, to be able to use ASYNCIFY). I guess this will also answer the question you asked me before, if I was going to make ASYNCIFY the default for FreeBasic. Better not.
The fact that the example doesn't work for long makes me think of some memory leak somewhere.

I have also noticed that the Emscripten environment is much, much less forgiving than other platforms. For example, if you have a SUB in a module, and by mistake you declare it as a FUNCTION in another module, and call it with no return value, under Linux and Windows it works anyway, under Emscripten it returns an exception and crashes
2) I tried OpenGL (previously removed #inclib "GL" and #include once "GL / mesa / glext.bi" in the headers). However, I could not compile because the linker does not find many necessary classical functions: glColor3f, glEnd, glFrustum, glRotatef. Perhaps these functions are not available in WEBGL.
You are right: all these commands are not available in WebGL. glEnd (and glBegin, of course) are part of the immediate mode, that is deprecated in OpenGL 2.0, and not supported in WebGL. glColor3f is not available, you need to use glVertexAttribPointer to pass the colors from an array. glFrustom, glRotatef and so on are not supported, you need to manually calculate a transform matrix, WebGL won't do it for you anymore. And after you did that, you need to write the shader (that has to be written in GLSL, you can't use FreeBasic for that, because every different video cart has a different compiler, provided by the driver, and often based on proprietary code). I already discussed that here: viewtopic.php?p=215377#p215377

By the way, this is not a problem limited to Emscripten, even Android or iOs require you to code in that way for 3d (and I have heard Vulkan is even worse)

Emscripten offers a backward compatibility layer, to emulate the missing functions, but it is not active by default (just like ASYNCIFY) and they recommend not to use it. If you want to try, you should use "-s LEGACY_GL_EMULATION=1", but I don't guarantee anything.

And actually, that's why I want to enable the use of OpenB3D with FreeBasic on Emscripten (my hope is to have OpenB3D to become the official 3d engine for FreeBasic)
In general, while fbgfx is an unrivaled option :) fbgfx programs work in the browser the same way as in executable files, at least I did not notice a drop in speed.
That's actually why I (and I guess many others here) kept using FreeBasic even after learning C++: it provides most features out of the box, and a program written in FreeBasic works with no changes on a lot of different platforms. A C/C++ code, to do all FreeBasic can do, would require two or three external libraries, that often are different on different platforms, making the code non portable.
srvaldez
Posts: 3401
Joined: Sep 25, 2005 21:54

Re: What happened to the Emscripten branch?

Post by srvaldez »

VANYA wrote: Here is a program that compiles fine under Linux and Windows, but hangs at compile time for WEB. Don't look at the confusion of the code, this program was written for the ZX Spectrum and I don't even know the author of the program. In those days, it was written in BASIC. I just ported the program code to FB. The only important thing is that the compilation fails (hangs), and this indicates problems inside the compiler:

Code: Select all

#Lang "qb"
Randomize timer
...
...
8950 PRINT "KPУИ3      ";:RETURN
9910 GOSUB 210:LET X=INT ((2+5*Y)*20*5^I_I):LET Z_Z=INT (.7*X*(Y+.3)):RETURN
tried to compile this with my latest FB-1.08.0 build's using various 32-bit gcc versions
with gcc-5.4 and 6.4 using the command fbc -w all -Wc -O2 -gen gcc -v "%f" I get "Aborting due to runtime error 12 ("segmentation violation" signal)"
using gcc-7.4 with the same command it also gives the same error but what is strange is that if I use fbc -w pedantic -Wc -O2 -gen gcc -v "%f" then it compiles just fine
with the official FB release it compiles just fine however running the the program compiled with FB x64 it crashes after pressing the return key at what looks like input request
the only reason I am posting this is that I found it strange that it would fail to compile with -w all but succeed with -w pedantic
coderJeff
Site Admin
Posts: 4358
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: What happened to the Emscripten branch?

Post by coderJeff »

angros47 wrote:I wonder if CoderJeff will want to add some more of my patches to github
Do you have the source published anywhere? It would be super convenient for me if you did.
Even if not, as long as I know what version (SHA1) you are working from, you could email me the patches or even a ZIP of all the changes at coder@execulink.com
It looks like the emscripten branch is generally usable and could merged in with version fbc 1.08.0. Then, it could be possible that members using St_W's daily build could try this out as well.
angros47
Posts: 2331
Joined: Jun 21, 2005 19:04

Re: What happened to the Emscripten branch?

Post by angros47 »

I sent you the file, let me know if it has arrived.

I haven't published it anywhere else, since I didn't want to leave around unofficial incomplete distributions
coderJeff
Site Admin
Posts: 4358
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: What happened to the Emscripten branch?

Post by coderJeff »

angros47 wrote:I sent you the file, let me know if it has arrived.
I got the the file, thank-you. Just working on this now. I made a couple of tests and I feel OK to merge this in to current fbc/master.

Obviously anyone wanting to try this out is going to need to take some extra steps until we figure out how to bundle with an official release, write the needed docs, etc. However, this addition produces a usable product so I'm OK to merge it in. I'm not sure if St_W's daily builds will have all the needed files since this target uses a few extra files and directories not normally seen in the fbc builds so far. I will post again once this is merged in.
St_W
Posts: 1628
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: What happened to the Emscripten branch?

Post by St_W »

coderJeff wrote:I'm not sure if St_W's daily builds will have all the needed files since this target uses a few extra files and directories not normally seen in the fbc builds so far. I will post again once this is merged in.
I tried to reduce the size of the builds and just include the bare necessities (mostly), so the chance is high that it won't work out of the box. In case you'd end up not considering it ready for master yet I could also provide builds just for a specific branch, maybe even specifically targeted for emscripten backend use (e.g. include some extra required files there). If it gets merged to master and there are issues with the nightly builds I'll try to fix them ofc. Thanks for your efforts, angros47 and coderJeff, to make this feature more easily accessible, already looking forward to see it in the official git repo, rebased on a recent version. :-)
angros47
Posts: 2331
Joined: Jun 21, 2005 19:04

Re: What happened to the Emscripten branch?

Post by angros47 »

You are welcome!
coderJeff
Site Admin
Posts: 4358
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: What happened to the Emscripten branch?

Post by coderJeff »

The updates (by angros47) are now merged in with fbc/master what will be the 1.08.0 release.

The changes do not include the hack I made for running on windows. Even though this what I would call a work in progress, it can make a usable product with some effort.

St_W, I have not tested how portable the binaries are. For example, using only a binary build of fbc+libraries w/ emscripten installed.
angros47
Posts: 2331
Joined: Jun 21, 2005 19:04

Re: What happened to the Emscripten branch?

Post by angros47 »

That's a great news! I am glad
angros47
Posts: 2331
Joined: Jun 21, 2005 19:04

Re: What happened to the Emscripten branch?

Post by angros47 »

VANYA wrote:angros47, I unfortunately see that threads are not working (threadcreate).
.....
I tried linking with the standard libfbmt.a, libfbgfxmt.a, but this produced an error:
I made a couple of tests. Building the files libfbmt.a and libfbgfxmt.a is actually possible: all you have to do is to open the makefile, locate the lines:

Code: Select all

ifeq ($(TARGET_OS),js)
	DISABLE_MT := YesPlease
endif
and either delete or commend them. Then you can build the rtlib and the gfxlib2 with TARGET=asmjs-unknown-emscripten , and the multithread version will be created. It seems to compile flawlessly.

Unfortunately, I tested it, and it doesn't work (the FreeBasic program containing threads is compiled, and runs, but only the main thread is executed). I tried by passing the -pthread flag to the linker, and to the C compiler, and it compiled, but returned exceptions and didn't work at all. Same with the flag -s USE_PTHREADS=1 passed to the linker.

By the way, I also tried compiling a C example using threads, and I failed to run it. I am not sure if I am missing something, or if support for threads in Emscripten is still not fully supported. For now, I guess that threads won't be a feature of the Emscripten version. The fact that the library can be compiled suggests that no changes might be needed in the source code, only different flags. I shared these information if anyone wants to do further experiments.
VANYA
Posts: 1839
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: What happened to the Emscripten branch?

Post by VANYA »

angros47 wrote:Unfortunately, I tested it, and it doesn't work (the FreeBasic program containing threads is compiled, and runs, but only the main thread is executed). I tried by passing the -pthread flag to the linker, and to the C compiler, and it compiled, but returned exceptions and didn't work at all. Same with the flag -s USE_PTHREADS=1 passed to the linker.

By the way, I also tried compiling a C example using threads, and I failed to run it. I am not sure if I am missing something, or if support for threads in Emscripten is still not fully supported. For now, I guess that threads won't be a feature of the Emscripten version. The fact that the library can be compiled suggests that no changes might be needed in the source code, only different flags. I shared these information if anyone wants to do further experiments.
I believe you, so there is no point in trying compiling libfbmt.a and libfbgfxmt.a
Mysoft
Posts: 840
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

Re: What happened to the Emscripten branch?

Post by Mysoft »

does anyone know a place where to get latest emscripten binaries to use with this? (that work on windows... 32bit)?
Post Reply