Allow plugins to provide material interpreters.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6105 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
022e42c6c7
commit
a9a4e3c358
7 changed files with 176 additions and 60 deletions
|
@ -364,7 +364,7 @@ extern cvar_t worker_flush;
|
|||
qboolean COM_DoWork(int thread, qboolean leavelocked);
|
||||
#define COM_MainThreadWork() while (COM_DoWork(0, false) && worker_flush.ival) /*called each frame to do any gl uploads or whatever*/
|
||||
#define COM_MainThreadFlush() while (COM_DoWork(0, false)) /*make sure the main thread has done ALL work pending*/
|
||||
typedef enum
|
||||
typedef enum wgroup_e
|
||||
{
|
||||
WG_MAIN = 0,
|
||||
WG_LOADER = 1,
|
||||
|
|
|
@ -408,6 +408,8 @@ static qboolean QDECL PlugBI_ExportInterface(const char *name, void *interfacept
|
|||
return R_RegisterVRDriver(currentplug, interfaceptr);
|
||||
if (!strcmp(name, plugimageloaderfuncs_name))
|
||||
return Image_RegisterLoader(currentplug, interfaceptr);
|
||||
if (!strcmp(name, plugmaterialloaderfuncs_name))
|
||||
return Material_RegisterLoader(currentplug, interfaceptr);
|
||||
#endif
|
||||
#ifdef PACKAGEMANAGER
|
||||
if (!strcmp(name, plugupdatesourcefuncs_name))
|
||||
|
@ -1536,6 +1538,7 @@ void Plug_Close(plugin_t *plug)
|
|||
#ifdef HAVE_CLIENT
|
||||
S_UnregisterSoundInputModule(plug);
|
||||
Image_RegisterLoader(plug, NULL);
|
||||
Material_RegisterLoader(plug, NULL);
|
||||
#endif
|
||||
NET_RegisterCrypto(plug, NULL);
|
||||
#ifdef PACKAGEMANAGER
|
||||
|
@ -1869,6 +1872,8 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
|
|||
COM_EnumerateFiles,
|
||||
|
||||
wildcmp,
|
||||
COM_GetFileExtension,
|
||||
COM_FileBase,
|
||||
COM_CleanUpPath,
|
||||
Com_BlockChecksum,
|
||||
FS_LoadMallocFile,
|
||||
|
@ -2044,7 +2049,10 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
|
|||
Sys_CreateMutex,
|
||||
Sys_LockMutex,
|
||||
Sys_UnlockMutex,
|
||||
Sys_DestroyMutex
|
||||
Sys_DestroyMutex,
|
||||
|
||||
COM_AddWork,
|
||||
COM_WorkerPartialSync,
|
||||
};
|
||||
|
||||
if (structsize == sizeof(funcs))
|
||||
|
|
|
@ -149,12 +149,16 @@ qboolean Sys_ConditionSignal(void *condv); //lock first
|
|||
qboolean Sys_ConditionBroadcast(void *condv); //lock first
|
||||
void Sys_DestroyConditional(void *condv);
|
||||
|
||||
enum wgroup_e;
|
||||
typedef struct
|
||||
{
|
||||
void *(QDECL *CreateMutex)(void);
|
||||
qboolean (QDECL *LockMutex)(void *mutex);
|
||||
qboolean (QDECL *UnlockMutex)(void *mutex);
|
||||
void (QDECL *DestroyMutex)(void *mutex);
|
||||
|
||||
void (*AddWork)(enum wgroup_e thread, void(*func)(void *ctx, void *data, size_t a, size_t b), void *ctx, void *data, size_t a, size_t b); //low priority
|
||||
void (*WaitForCompletion)(void *priorityctx, int *address, int sleepwhilevalue);
|
||||
#define plugthreadfuncs_name "Threading"
|
||||
} plugthreadfuncs_t;
|
||||
|
||||
|
|
|
@ -297,6 +297,43 @@ static qboolean Shader_LocateSource(const char *name, const char **buf, size_t *
|
|||
static void Shader_ReadShader(parsestate_t *ps, const char *shadersource, shadercachefile_t *sourcefile);
|
||||
static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename);
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
void *module;
|
||||
plugmaterialloaderfuncs_t *funcs;
|
||||
} *materialloader;
|
||||
static size_t materialloader_count;
|
||||
qboolean Material_RegisterLoader(void *module, plugmaterialloaderfuncs_t *driver)
|
||||
{
|
||||
int i;
|
||||
if (!driver)
|
||||
{
|
||||
for (i = 0; i < materialloader_count; )
|
||||
{
|
||||
if (materialloader[i].module == module)
|
||||
{
|
||||
memmove(&materialloader[i], &materialloader[i+1], materialloader_count-(i+1));
|
||||
materialloader_count--;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
void *n = BZ_Malloc(sizeof(*materialloader)*(materialloader_count+1));
|
||||
memcpy(n, materialloader, sizeof(*materialloader)*materialloader_count);
|
||||
Z_Free(materialloader);
|
||||
materialloader = n;
|
||||
materialloader[materialloader_count].module = module;
|
||||
materialloader[materialloader_count].funcs = driver;
|
||||
materialloader_count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
static qboolean Shader_EvaluateCondition(shader_t *shader, const char **ptr)
|
||||
|
@ -2048,13 +2085,7 @@ typedef struct sgeneric_s
|
|||
qboolean failed;
|
||||
} sgeneric_t;
|
||||
static sgeneric_t *sgenerics;
|
||||
struct sbuiltin_s
|
||||
{
|
||||
int qrtype;
|
||||
int apiver;
|
||||
char name[MAX_QPATH];
|
||||
char *body;
|
||||
} sbuiltins[] =
|
||||
static struct sbuiltin_s sbuiltins[] =
|
||||
{
|
||||
#include "r_bishaders.h"
|
||||
{QR_NONE}
|
||||
|
@ -2155,23 +2186,35 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
|
|||
else
|
||||
{
|
||||
int ver;
|
||||
for (i = 0; *sbuiltins[i].name; i++)
|
||||
const struct sbuiltin_s *progs;
|
||||
unsigned int l;
|
||||
for (l = 0; l <= materialloader_count; l++)
|
||||
{
|
||||
if (sbuiltins[i].qrtype == qrtype && !strcmp(sbuiltins[i].name, basicname))
|
||||
{
|
||||
ver = sbuiltins[i].apiver;
|
||||
if (l == materialloader_count)
|
||||
progs = sbuiltins;
|
||||
else if (materialloader[l].funcs && materialloader[l].funcs->builtinshaders)
|
||||
progs = materialloader[l].funcs->builtinshaders;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (ver < sh_config.minver || ver > sh_config.maxver)
|
||||
if (!(qrenderer==QR_OPENGL&&ver==110))
|
||||
for (i = 0; *progs[i].name; i++)
|
||||
{
|
||||
if (progs[i].qrtype == qrtype && !strcmp(progs[i].name, basicname))
|
||||
{
|
||||
ver = progs[i].apiver;
|
||||
|
||||
if (ver < sh_config.minver || ver > sh_config.maxver)
|
||||
if (!(qrenderer==QR_OPENGL&&ver==110))
|
||||
continue;
|
||||
|
||||
TRACE(("Loading Embedded %s\n", g->name));
|
||||
g->failed = !Shader_LoadPermutations(g->name, &g->prog, progs[i].body, qrtype, ver, blobname);
|
||||
|
||||
if (g->failed)
|
||||
continue;
|
||||
|
||||
TRACE(("Loading Embedded %s\n", g->name));
|
||||
g->failed = !Shader_LoadPermutations(g->name, &g->prog, sbuiltins[i].body, qrtype, ver, blobname);
|
||||
|
||||
if (g->failed)
|
||||
continue;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
TRACE(("Program unloadable %s\n", g->name));
|
||||
|
@ -2489,6 +2532,17 @@ static void Shader_HLSL11ProgramName (parsestate_t *ps, const char **ptr)
|
|||
Shader_SLProgramName(shader,pass,ptr,QR_DIRECT3D11);
|
||||
}
|
||||
|
||||
static void Shaderpass_BlendFunc (parsestate_t *ps, const char **ptr);
|
||||
static void Shader_ProgBlendFunc (parsestate_t *ps, const char **ptr)
|
||||
{
|
||||
if (ps->s->prog)
|
||||
{
|
||||
ps->pass = ps->s->passes;
|
||||
Shaderpass_BlendFunc(ps, ptr);
|
||||
ps->pass = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void Shader_ReflectCube(parsestate_t *ps, const char **ptr)
|
||||
{
|
||||
char *token = Shader_ParseSensString(ptr);
|
||||
|
@ -2847,7 +2901,7 @@ static shaderkey_t shaderkeys[] =
|
|||
{"glslprogram", Shader_GLSLProgramName, "fte"}, //for renderers that accept embedded glsl
|
||||
{"hlslprogram", Shader_HLSL9ProgramName, "fte"}, //for d3d with embedded hlsl
|
||||
{"hlsl11program", Shader_HLSL11ProgramName, "fte"}, //for d3d with embedded hlsl
|
||||
// {"progblendfunc", Shader_ProgBlendFunc, "fte"}, //specifies the blend mode (actually just overrides the first subpasses' blendmode.
|
||||
{"progblendfunc", Shader_ProgBlendFunc, "fte"}, //specifies the blend mode (actually just overrides the first subpasses' blendmode.
|
||||
// {"progmap", Shader_ProgMap, "fte"}, //avoids needing extra subpasses (actually just inserts an extra pass).
|
||||
|
||||
//dp compat
|
||||
|
@ -4353,8 +4407,9 @@ static const char *Shader_Skip(const char *file, const char *shadername, const c
|
|||
return ptr;
|
||||
}
|
||||
|
||||
static void Shader_Reset(shader_t *s)
|
||||
static void Shader_Reset(parsestate_t *ps)
|
||||
{
|
||||
shader_t *s = ps->s;
|
||||
extern cvar_t r_refractreflect_scale;
|
||||
char name[MAX_QPATH];
|
||||
int id = s->id;
|
||||
|
@ -4393,7 +4448,7 @@ static void Shader_Reset(shader_t *s)
|
|||
|
||||
static void Shader_Regenerate(parsestate_t *ps, const char *shortname)
|
||||
{
|
||||
Shader_Reset(ps->s);
|
||||
Shader_Reset(ps);
|
||||
|
||||
if (!strcmp(shortname, "textures/common/clip") || !strcmp(shortname, "textures/common/nodraw") || !strcmp(shortname, "common/nodraw"))
|
||||
Shader_DefaultScript(ps, shortname,
|
||||
|
@ -7279,6 +7334,12 @@ static void Shader_ReadShader(parsestate_t *ps, const char *shadersource, shader
|
|||
}
|
||||
}
|
||||
|
||||
static void Shader_LoadMaterialString(parsestate_t *ps, const char *shadertext)
|
||||
{ //callback for our external material loaders.
|
||||
Shader_Reset(ps);
|
||||
Shader_ReadShader(ps, shadertext, NULL);
|
||||
}
|
||||
|
||||
static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
|
||||
{
|
||||
size_t offset = 0, length;
|
||||
|
@ -7294,8 +7355,15 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
|
|||
if (!strcmp(token, ".mat") || !*token)
|
||||
{
|
||||
char shaderfile[MAX_QPATH];
|
||||
size_t i;
|
||||
if (!*token)
|
||||
{
|
||||
for (i = 0; i < materialloader_count; i++)
|
||||
{
|
||||
if (materialloader[i].funcs->ReadMaterial(ps, parsename, Shader_LoadMaterialString))
|
||||
return true;
|
||||
}
|
||||
|
||||
Q_snprintfz(shaderfile, sizeof(shaderfile), "%s.mat", parsename);
|
||||
file = COM_LoadTempMoreFile(shaderfile, &length);
|
||||
}
|
||||
|
@ -7303,7 +7371,7 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
|
|||
file = COM_LoadTempMoreFile(parsename, &length);
|
||||
if (file)
|
||||
{
|
||||
Shader_Reset(ps->s);
|
||||
Shader_Reset(ps);
|
||||
token = COM_ParseExt (&file, true, false); //we need to skip over the leading {.
|
||||
if (*token != '{')
|
||||
token = COM_ParseExt (&file, true, false); //try again, in case we found some legacy name.
|
||||
|
@ -7331,7 +7399,7 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
|
|||
return false;
|
||||
}
|
||||
|
||||
Shader_Reset(ps->s);
|
||||
Shader_Reset(ps);
|
||||
|
||||
Shader_ReadShader(ps, file, sourcefile);
|
||||
|
||||
|
|
|
@ -710,6 +710,24 @@ struct shader_s
|
|||
*/
|
||||
};
|
||||
|
||||
struct shaderparsestate_s;
|
||||
struct sbuiltin_s
|
||||
{
|
||||
int qrtype;
|
||||
int apiver;
|
||||
char name[MAX_QPATH];
|
||||
char *body;
|
||||
};
|
||||
typedef struct
|
||||
{
|
||||
const char *loadername;
|
||||
qboolean (*ReadMaterial)(struct shaderparsestate_s *ps, const char *filename, void (*LoadMaterialString)(struct shaderparsestate_s *ps, const char *script));
|
||||
|
||||
struct sbuiltin_s *builtinshaders;
|
||||
#define plugmaterialloaderfuncs_name "MaterialLoader"
|
||||
} plugmaterialloaderfuncs_t;
|
||||
qboolean Material_RegisterLoader(void *module, plugmaterialloaderfuncs_t *loader);
|
||||
|
||||
extern unsigned int r_numshaders;
|
||||
extern unsigned int r_maxshaders;
|
||||
extern shader_t **r_shaders;
|
||||
|
|
|
@ -109,7 +109,7 @@ void dumpprogblob(FILE *out, FILE *src)
|
|||
fprintf(out, "\"");
|
||||
}
|
||||
|
||||
struct shadertype_s
|
||||
static struct shadertype_s
|
||||
{
|
||||
char *abrv;
|
||||
char *filepattern;
|
||||
|
@ -126,12 +126,48 @@ struct shadertype_s
|
|||
};
|
||||
//tbh we should precompile the d3d shaders.
|
||||
|
||||
int main(void)
|
||||
static void dumpprogram(FILE *c, const char *progname)
|
||||
{
|
||||
FILE *s;
|
||||
char line[1024];
|
||||
int a;
|
||||
printf("%25s: ", progname);
|
||||
for (a = 0; a < sizeof(shadertype)/sizeof(shadertype[0]); a++)
|
||||
{
|
||||
sprintf(line, shadertype[a].filepattern, progname);
|
||||
if (shadertype[a].apiversion == -1)
|
||||
s = fopen(line, "rb");
|
||||
else
|
||||
s = fopen(line, "rt");
|
||||
if (!s)
|
||||
{
|
||||
printf("%4s", "");
|
||||
continue;
|
||||
}
|
||||
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
|
||||
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, progname);
|
||||
if (shadertype[a].apiversion == -1)
|
||||
dumpprogblob(c,s);
|
||||
else
|
||||
dumpprogstring(c, s);
|
||||
fputs("},\n", c);
|
||||
fprintf(c, "#endif\n");
|
||||
fclose(s);
|
||||
fflush(c);
|
||||
|
||||
printf("%4s", shadertype[a].abrv);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
FILE *c, *s;
|
||||
char line[1024];
|
||||
int i, j, a;
|
||||
c = fopen("../gl/r_bishaders.h", "wt");
|
||||
|
||||
const char *outname = ((argc>1)?argv[1]:"../gl/r_bishaders.h");
|
||||
|
||||
c = fopen(outname, "wt");
|
||||
|
||||
if (!c)
|
||||
{
|
||||
|
@ -141,35 +177,15 @@ int main(void)
|
|||
|
||||
fprintf(c, "/*\nWARNING: THIS FILE IS GENERATED BY '"__FILE__"'.\nYOU SHOULD NOT EDIT THIS FILE BY HAND\n*/\n\n");
|
||||
|
||||
for (i = 0; *shaders[i]; i++)
|
||||
{
|
||||
printf("%25s: ", shaders[i]);
|
||||
for (a = 0; a < sizeof(shadertype)/sizeof(shadertype[0]); a++)
|
||||
{
|
||||
sprintf(line, shadertype[a].filepattern, shaders[i]);
|
||||
if (shadertype[a].apiversion == -1)
|
||||
s = fopen(line, "rb");
|
||||
else
|
||||
s = fopen(line, "rt");
|
||||
if (!s)
|
||||
{
|
||||
printf("%4s", "");
|
||||
continue;
|
||||
}
|
||||
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
|
||||
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]);
|
||||
if (shadertype[a].apiversion == -1)
|
||||
dumpprogblob(c,s);
|
||||
else
|
||||
dumpprogstring(c, s);
|
||||
fputs("},\n", c);
|
||||
fprintf(c, "#endif\n");
|
||||
fclose(s);
|
||||
fflush(c);
|
||||
|
||||
printf("%4s", shadertype[a].abrv);
|
||||
}
|
||||
printf("\n");
|
||||
if (argc>2)
|
||||
{ //if we're passed a file list on the commandline then just use that (generally for plugins).
|
||||
for (i = 2; i < argc; i++)
|
||||
dumpprogram(c, argv[i]);
|
||||
}
|
||||
else
|
||||
{ //use our built in list.
|
||||
for (i = 0; *shaders[i]; i++)
|
||||
dumpprogram(c, shaders[i]);
|
||||
}
|
||||
|
||||
fclose(c);
|
||||
|
|
|
@ -349,6 +349,8 @@ typedef struct //for plugins that need to read/write files...
|
|||
|
||||
//helpers
|
||||
F(int, WildCmp, (const char *wild, const char *string));
|
||||
F(const char *,GetExtension,(const char *filename, const char *ignoreext));
|
||||
F(void, FileBase, (const char *in, char *out, int outlen));
|
||||
F(void, CleanUpPath, (char *str));
|
||||
F(unsigned int,BlockChecksum,(const void *buffer, int length)); //mostly for pack hashes.
|
||||
F(qbyte*, LoadFile, (const char *fname, size_t *fsize)); //plugfuncs->Free
|
||||
|
|
Loading…
Reference in a new issue