Playing around trying to make the emscriptem port more usable/nicer.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4371 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
594a297ffa
commit
d97a163011
8 changed files with 165 additions and 20 deletions
|
@ -1105,8 +1105,8 @@ ifeq ($(FTE_TARGET),web)
|
|||
WEB_MEMORY?=402653184
|
||||
RELEASE_CFLAGS=-DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB
|
||||
DEBUG_CFLAGS=-g --jcache -DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB
|
||||
RELEASE_LDFLAGS=-O1 $(WEB_PREJS) -s TOTAL_MEMORY=$(WEB_MEMORY)
|
||||
DEBUG_LDLAGS=-O0 $(WEB_PREJS) -s TOTAL_MEMORY=$(WEB_MEMORY)
|
||||
RELEASE_LDFLAGS=-O1 $(WEB_PREJS) -s TOTAL_MEMORY=$(WEB_MEMORY) --js-library web/ftejslib.js --shell-file web/fteshell.html
|
||||
DEBUG_LDLAGS=-O0 $(WEB_PREJS) -s TOTAL_MEMORY=$(WEB_MEMORY) --js-library web/ftejslib.js
|
||||
CC=emcc
|
||||
#-s ASM_JS=1
|
||||
#BASELDFLAGS=
|
||||
|
|
|
@ -28,6 +28,7 @@ void (APIENTRY *qglGetFloatv) (GLenum pname, GLfloat *params);
|
|||
void (APIENTRY *qglGetIntegerv) (GLenum pname, GLint *params);
|
||||
const GLubyte * (APIENTRY *qglGetString) (GLenum name);
|
||||
void (APIENTRY *qglHint) (GLenum target, GLenum mode);
|
||||
GLboolean (APIENTRY *qglIsEnabled) (GLenum cap);
|
||||
void (APIENTRY *qglPolygonOffset) (GLfloat factor, GLfloat units);
|
||||
void (APIENTRY *qglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
|
||||
void (APIENTRY *qglTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
|
@ -110,7 +111,6 @@ void (APIENTRY *qglEnd) (void);
|
|||
void (APIENTRY *qglEndList) (void);
|
||||
void (APIENTRY *qglFrustum) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
|
||||
GLuint (APIENTRY *qglGenLists) (GLsizei range);
|
||||
GLboolean (APIENTRY *qglIsEnabled) (GLenum cap);
|
||||
void (APIENTRY *qglLoadIdentity) (void);
|
||||
void (APIENTRY *qglLoadMatrixf) (const GLfloat *m);
|
||||
void (APIENTRY *qglNormal3f) (GLfloat nx, GLfloat ny, GLfloat nz);
|
||||
|
@ -1507,6 +1507,7 @@ void GL_Init(void *(*getglfunction) (char *name))
|
|||
qglGetIntegerv = (void *)getglcore("glGetIntegerv");
|
||||
qglGetString = (void *)getglcore("glGetString");
|
||||
qglHint = (void *)getglcore("glHint");
|
||||
qglIsEnabled = (void *)getglext("glIsEnabled");
|
||||
qglReadPixels = (void *)getglcore("glReadPixels");
|
||||
qglTexImage2D = (void *)getglcore("glTexImage2D");
|
||||
qglTexSubImage2D = (void *)getglcore("glTexSubImage2D");
|
||||
|
@ -1596,7 +1597,6 @@ void GL_Init(void *(*getglfunction) (char *name))
|
|||
|
||||
qglGetTexEnviv = (void *)getglext("glGetTexEnviv");
|
||||
qglGetPointerv = (void *)getglext("glGetPointerv");
|
||||
qglIsEnabled = (void *)getglext("glIsEnabled");
|
||||
|
||||
qglGetStringi = (void *)getglext("glGetStringi");
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
|
|||
{
|
||||
int flags;
|
||||
|
||||
Con_Printf("SDL GLVID_Init\n");
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
|
||||
#ifndef FTE_TARGET_WEB
|
||||
SDL_SetVideoMode( 0, 0, 0, 0 ); //to get around some SDL bugs
|
||||
|
@ -89,7 +87,6 @@ void GLVID_DeInit (void)
|
|||
ActiveApp = false;
|
||||
|
||||
IN_DeactivateMouse();
|
||||
Con_Printf("Restoring gamma\n");
|
||||
SDL_SetGammaRamp (intitialgammaramps[0], intitialgammaramps[1], intitialgammaramps[2]);
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
@ -149,7 +146,7 @@ qboolean GLVID_ApplyGammaRamps (unsigned short *ramps)
|
|||
if (gammaworks)
|
||||
{ //we have hardware gamma applied - if we're doing a BF, we don't want to reset to the default gamma (yuck)
|
||||
SDL_SetGammaRamp (&ramps[0], &ramps[256], &ramps[512]);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
gammaworks = !SDL_SetGammaRamp (&ramps[0], &ramps[256], &ramps[512]);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,14 @@
|
|||
#if defined(WEBCLIENT)
|
||||
|
||||
#if defined(FTE_TARGET_WEB)
|
||||
|
||||
|
||||
#define MYJS 1
|
||||
#if MYJS
|
||||
#include "web/ftejslib.h"
|
||||
#else
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -56,11 +63,11 @@ static void VFSMEM_Flush(struct vfsfile_s *file)
|
|||
}
|
||||
static vfsfile_t *VFSMEM_File(void *data, unsigned int datasize)
|
||||
{
|
||||
/*create a file which is already unlinked*/
|
||||
mfile_t *f;
|
||||
f = malloc(sizeof(*f) + datasize);
|
||||
if (!f)
|
||||
return NULL;
|
||||
/*create a file which is already unlinked*/
|
||||
mfile_t *f;
|
||||
f = malloc(sizeof(*f) + datasize);
|
||||
if (!f)
|
||||
return NULL;
|
||||
f->funcs.ReadBytes = VFSMEM_ReadBytes;
|
||||
f->funcs.WriteBytes = VFSMEM_WriteBytes;
|
||||
f->funcs.Seek = VFSMEM_Seek;
|
||||
|
@ -82,43 +89,55 @@ static void DL_Abort(struct dl_download *dl)
|
|||
static void DL_OnLoad(void *c, void *data, int datasize)
|
||||
{
|
||||
struct dl_download *dl = c;
|
||||
Con_Printf("download %p: success\n", dl);
|
||||
|
||||
//make sure the file is 'open'.
|
||||
if (!dl->file)
|
||||
{
|
||||
if (*dl->localname)
|
||||
{
|
||||
Con_Printf("create file\n");
|
||||
FS_CreatePath(dl->localname, FS_GAME);
|
||||
dl->file = FS_OpenVFS(dl->localname, "w+b", FS_GAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
//emscripten does not close the file. plus we seem to end up with infinite loops.
|
||||
Con_Printf("temp file\n");
|
||||
dl->file = VFSMEM_File(data, datasize);
|
||||
}
|
||||
}
|
||||
|
||||
if (dl->file)
|
||||
{
|
||||
Con_Printf("writing to file\n");
|
||||
VFS_WRITE(dl->file, data, datasize);
|
||||
}
|
||||
|
||||
dl->replycode = 200;
|
||||
#if !MYJS
|
||||
dl->completed += datasize;
|
||||
#endif
|
||||
dl->status = DL_FINISHED;
|
||||
}
|
||||
#if MYJS
|
||||
static void DL_OnError(void *c, int ecode)
|
||||
#else
|
||||
static void DL_OnError(void *c)
|
||||
#endif
|
||||
{
|
||||
struct dl_download *dl = c;
|
||||
Con_Printf("download %p: error\n", dl);
|
||||
|
||||
#if MYJS
|
||||
dl->replycode = ecode;
|
||||
#else
|
||||
dl->replycode = 404; //we don't actually know. should we not do this?
|
||||
#endif
|
||||
dl->status = DL_FAILED;
|
||||
}
|
||||
static void DL_OnProgress(void *c, int position, int totalsize)
|
||||
{
|
||||
struct dl_download *dl = c;
|
||||
dl->completed = position;
|
||||
dl->totalsize = totalsize;
|
||||
}
|
||||
|
||||
//this becomes a poll function. the main thread will call this once a frame or so.
|
||||
qboolean HTTPDL_Decide(struct dl_download *dl)
|
||||
|
@ -141,8 +160,13 @@ qboolean HTTPDL_Decide(struct dl_download *dl)
|
|||
dl->abort = DL_Abort;
|
||||
dl->ctx = dl;
|
||||
|
||||
Con_Printf("Sending %p request for %s\n", dl, url);
|
||||
#if MYJS
|
||||
emscriptenfte_async_wget_data2(url, dl, DL_OnLoad, DL_OnError, DL_OnProgress);
|
||||
#else
|
||||
//annoyingly, emscripten doesn't provide an onprogress callback, unlike firefox etc, so we can't actually tell how far its got.
|
||||
//we'd need to provide our own js library to fix this. it can be done, I'm just lazy.
|
||||
emscripten_async_wget_data(url, dl, DL_OnLoad, DL_OnError);
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
2
engine/web/ftejslib.h
Normal file
2
engine/web/ftejslib.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
void emscriptenfte_async_wget_data2(const char *url, void *ctx, void (*onload)(void*ctx,void*buf,int sz), void (*onerror)(void*ctx,int code), void (*onprogress)(void*ctx,int prog,int total));
|
||||
|
43
engine/web/ftejslib.js
Normal file
43
engine/web/ftejslib.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
mergeInto(LibraryManager.library,
|
||||
{
|
||||
emscriptenfte_async_wget_data2 : function(url, ctx, onload, onerror, onprogress)
|
||||
{
|
||||
var _url = Pointer_stringify(url);
|
||||
|
||||
var http = new XMLHttpRequest();
|
||||
http.open('GET', _url, true);
|
||||
http.responseType = 'arraybuffer';
|
||||
|
||||
http.onload = function(e)
|
||||
{
|
||||
if (http.status == 200)
|
||||
{
|
||||
var bar = new Uint8Array(http.response);
|
||||
var buf = _malloc(bar.length);
|
||||
HEAPU8.set(bar, buf);
|
||||
if (onload)
|
||||
Runtime.dynCall('viii', onload, [ctx, buf, bar.length]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (onerror)
|
||||
Runtime.dynCall('vii', onerror, [ctx, http.status]);
|
||||
}
|
||||
};
|
||||
|
||||
http.onerror = function(e)
|
||||
{
|
||||
if (onerror)
|
||||
Runtime.dynCall('vii', onerror, [ctx, http.status]);
|
||||
};
|
||||
|
||||
http.onprogress = function(e)
|
||||
{
|
||||
if (onprogress)
|
||||
Runtime.dynCall('viii', onprogress, [ctx, e.loaded, e.total]);
|
||||
};
|
||||
|
||||
http.send(null);
|
||||
}
|
||||
});
|
79
engine/web/fteshell.html
Normal file
79
engine/web/fteshell.html
Normal file
|
@ -0,0 +1,79 @@
|
|||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>FTE QuakeWorld</title>
|
||||
<style>
|
||||
body { background-color:#000000; color:#808080; }
|
||||
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
||||
div.emscripten { text-align: center; }
|
||||
div.emscripten_border { border: 1px solid black; }
|
||||
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
|
||||
canvas.emscripten { border: 0px none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="emscripten" id="status">Is javascript enabled?</div>
|
||||
<div class="emscripten">
|
||||
<progress value="0" max="100" id="progress" hidden=1></progress>
|
||||
</div>
|
||||
<div class="emscripten_border">
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
</div>
|
||||
<div class="emscripten">
|
||||
<input type="checkbox" id="resize">Resize canvas
|
||||
<input type="checkbox" id="pointerLock" checked>Lock/hide mouse pointer
|
||||
|
||||
<input type="button" value="Fullscreen" onclick="Module.requestFullScreen(document.getElementById('pointerLock').checked,
|
||||
document.getElementById('resize').checked)">
|
||||
</div>
|
||||
|
||||
<script type='text/javascript'>
|
||||
// connect to canvas
|
||||
var Module = {
|
||||
preRun: [],
|
||||
postRun: [],
|
||||
print: (function() {
|
||||
})(),
|
||||
printErr: function(text) {
|
||||
text = Array.prototype.slice.call(arguments).join(' ');
|
||||
if (0) { // XXX disabled for safety typeof dump == 'function') {
|
||||
dump(text + '\n'); // fast, straight to the real console
|
||||
} else {
|
||||
console.log(text);
|
||||
}
|
||||
},
|
||||
canvas: document.getElementById('canvas'),
|
||||
setStatus: function(text) {
|
||||
if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
|
||||
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
|
||||
var statusElement = document.getElementById('status');
|
||||
var progressElement = document.getElementById('progress');
|
||||
if (m) {
|
||||
text = m[1];
|
||||
progressElement.value = parseInt(m[2])*100;
|
||||
progressElement.max = parseInt(m[4])*100;
|
||||
progressElement.hidden = false;
|
||||
} else {
|
||||
progressElement.value = null;
|
||||
progressElement.max = null;
|
||||
progressElement.hidden = true;
|
||||
}
|
||||
statusElement.innerHTML = text;
|
||||
},
|
||||
totalDependencies: 0,
|
||||
monitorRunDependencies: function(left) {
|
||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
||||
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
|
||||
}
|
||||
};
|
||||
Module.setStatus('Downloading...');
|
||||
</script>
|
||||
<script type='text/javascript'>
|
||||
|
||||
{{{ SCRIPT_CODE }}}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -12,9 +12,9 @@ Module['preRun'] = function()
|
|||
//FS.createPreloadedFile('/id1/', 'pak3.pak', '/pak3.pak', true, false);
|
||||
};
|
||||
|
||||
Module['arguments'] = ['-nohome'];//, '+connect', 'tcp://127.0.0.1:80'];//, '-manifest', document.location + '.fmf'];
|
||||
Module['arguments'] = ['-nohome', '-manifest', document.location + '.fmf'];
|
||||
// use query string in URL as command line
|
||||
if (!document.referrer) {
|
||||
qstring = decodeURIComponent(window.location.search.substring(1)).split(" ");
|
||||
Module['arguments'] = Module['arguments'].concat(qstring);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue