Add support for image-loading plugins.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6103 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-11-03 20:31:21 +00:00
parent 57746acd5a
commit ab2dc14f49
4 changed files with 148 additions and 1 deletions

View file

@ -230,6 +230,44 @@ static float HalfToFloat(unsigned short val);
static unsigned short FloatToHalf(float val);
static struct
{
void *module;
plugimageloaderfuncs_t *funcs;
} *imageloader;
static size_t imageloader_count;
qboolean Image_RegisterLoader(void *module, plugimageloaderfuncs_t *driver)
{
int i;
if (!driver)
{
for (i = 0; i < imageloader_count; )
{
if (imageloader[i].module == module)
{
memmove(&imageloader[i], &imageloader[i+1], imageloader_count-(i+1));
imageloader_count--;
}
else
i++;
}
return true;
}
else
{
void *n = BZ_Malloc(sizeof(*imageloader)*(imageloader_count+1));
memcpy(n, imageloader, sizeof(*imageloader)*imageloader_count);
Z_Free(imageloader);
imageloader = n;
imageloader[imageloader_count].module = module;
imageloader[imageloader_count].funcs = driver;
imageloader_count++;
return true;
}
}
#if defined(AVAIL_JPEGLIB) || defined(AVAIL_PNGLIB)
static void GenerateXMPData(char *blob, size_t blobsize, int width, int height, unsigned int metainfo)
{ //XMP is a general thing that applies to multiple formats - or at least png+jpeg.
@ -7251,6 +7289,7 @@ void Image_PrintInputFormatVersions(void)
//if force_rgba8 then it guarentees rgba8 or rgbx8, otherwise can return l8, etc
qbyte *ReadRawImageFile(qbyte *buf, int len, int *width, int *height, uploadfmt_t *format, qboolean force_rgba8, const char *fname)
{
size_t l, i;
qbyte *data;
*format = PTI_RGBX8;
#ifdef IMAGEFMT_TGA
@ -7344,6 +7383,58 @@ qbyte *ReadRawImageFile(qbyte *buf, int len, int *width, int *height, uploadfmt_
}
#endif
for (l = 0; l < imageloader_count; l++)
{
struct pendingtextureinfo *mips = imageloader[l].funcs->ReadImageFile(0, fname, buf, len);
if (mips)
{
if (mips->extrafree != buf)
Sys_Error("Image loader did weird extrafree things.");
mips->extrafree = NULL;
//free any excess mips
while (mips->mipcount > 1)
if (mips->mip[--mips->mipcount].needfree)
BZ_Free(mips->mip[mips->mipcount].data);
if (mips->mipcount > 0 && mips->type == PTI_2D)
{
if (force_rgba8)
{
qboolean rgbx8only[PTI_MAX] = {0};
rgbx8only[PTI_RGBX8] = true;
rgbx8only[PTI_RGBA8] = true;
Image_ChangeFormat(mips, rgbx8only, mips->encoding, fname);
}
if (mips->mip[0].needfree)
{
data = mips->mip[0].data;
mips->mip[0].data = NULL;
mips->mip[0].needfree = false;
}
else
{
data = BZ_Malloc(mips->mip[0].datasize);
memcpy(data, mips->mip[0].data, mips->mip[0].datasize);
}
*width = mips->mip[0].width;
*height = mips->mip[0].height;
*format = mips->encoding;
}
for (i = 0; i < mips->mipcount; i++)
if (mips->mip[i].needfree)
BZ_Free(mips->mip[i].data);
if (mips->extrafree && mips->extrafree)
BZ_Free(mips->extrafree);
BZ_Free(mips);
if (data)
return data;
}
}
#ifdef IMAGEFMT_LMP
if (len >= 8) //.lmp has no magic id. guess at it.
{
@ -13154,6 +13245,7 @@ struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char *iname
qbyte *rgbadata;
int imgwidth, imgheight;
size_t l;
struct pendingtextureinfo *mips = NULL;
@ -13174,6 +13266,8 @@ struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char *iname
if (!mips && filedata[0] == 'B' && filedata[1] == 'L' && filedata[2] == 'P' && filedata[3] == '2')
mips = Image_ReadBLPFile(flags, fname, filedata, filesize);
#endif
for (l = 0; !mips && l < imageloader_count; l++)
mips = imageloader[l].funcs->ReadImageFile(flags, fname, filedata, filesize);
#ifdef IMAGEFMT_ASTC
if (!mips && filesize>= 16 && filedata[0] == 0x13 && filedata[1] == 0xab && filedata[2] == 0xa1 && filedata[3] == 0x5c)
mips = Image_ReadASTCFile(flags, fname, filedata, filesize);
@ -13692,6 +13786,8 @@ qboolean Image_LocateHighResTexture(image_t *tex, flocation_t *bestloc, char *be
continue;
s = COM_SkipPath(nicename);
if (!*s)
continue;
n = basename;
while (*s && (*s != '.'||exactext) && n < basename+sizeof(basename)-5)
*n++ = *s++;
@ -13837,7 +13933,7 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
unsigned int locflags = 0;
vfsfile_t *f;
size_t fsize;
size_t fsize, l;
char *buf;
int i, j;
@ -13919,6 +14015,12 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
if (!mips)
mips = Image_ReadDDSFile(tex->flags, altname, buf, fsize);
#endif
for (l = 0; !mips && l < imageloader_count; l++)
{
if (!imageloader[l].funcs->canloadcubemaps)
continue;
mips = imageloader[l].funcs->ReadImageFile(tex->flags, altname, buf, fsize);
}
if (!mips)
BZ_Free(buf);
}

View file

@ -500,6 +500,16 @@ void Image_ChangeFormat(struct pendingtextureinfo *mips, qboolean *allowedformat
void Image_Premultiply(struct pendingtextureinfo *mips);
void *Image_FlipImage(const void *inbuffer, void *outbuffer, int *inoutwidth, int *inoutheight, int pixelbytes, qboolean flipx, qboolean flipy, qboolean flipd);
typedef struct
{
const char *loadername;
size_t pendingtextureinfosize;
qboolean canloadcubemaps;
struct pendingtextureinfo *(*ReadImageFile)(unsigned int imgflags, const char *fname, qbyte *filedata, size_t filesize);
#define plugimageloaderfuncs_name "ImageLoader"
} plugimageloaderfuncs_t;
qboolean Image_RegisterLoader(void *module, plugimageloaderfuncs_t *loader);
#ifdef D3D8QUAKE
void D3D8_Set2D (void);
void D3D8_UpdateFiltering (image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);

View file

@ -406,6 +406,8 @@ static qboolean QDECL PlugBI_ExportInterface(const char *name, void *interfacept
#ifdef HAVE_CLIENT
if (!strcmp(name, plugvrfuncs_name))
return R_RegisterVRDriver(currentplug, interfaceptr);
if (!strcmp(name, plugimageloaderfuncs_name))
return Image_RegisterLoader(currentplug, interfaceptr);
#endif
#ifdef PACKAGEMANAGER
if (!strcmp(name, plugupdatesourcefuncs_name))
@ -1533,6 +1535,7 @@ void Plug_Close(plugin_t *plug)
#endif
#ifdef HAVE_CLIENT
S_UnregisterSoundInputModule(plug);
Image_RegisterLoader(plug, NULL);
#endif
NET_RegisterCrypto(plug, NULL);
#ifdef PACKAGEMANAGER
@ -1783,6 +1786,12 @@ plugcorefuncs_t plugcorefuncs =
Sys_LoadLibrary,
Sys_GetAddressForName,
Sys_CloseLibrary,
Z_Malloc,
BZ_Realloc,
Z_Free,
ZG_Malloc,
ZG_FreeGroup,
};
static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t structsize)
@ -1989,6 +1998,16 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
if (structsize == sizeof(funcs))
return &funcs;
}
if (!strcmp(interfacename, plugimagefuncs_name))
{
static plugimagefuncs_t funcs =
{
Image_BlockSizeForEncoding,
Image_FormatName,
};
if (structsize == sizeof(funcs))
return &funcs;
}
#endif
#ifdef SUPPORT_ICE

View file

@ -197,6 +197,15 @@ typedef struct //core stuff
F(dllhandle_t*,LoadDLL, (const char *modulename, struct dllfunction_s *funcs));
F(void*, GetDLLSymbol, (dllhandle_t *handle, const char *symbolname));
F(void, CloseDLL, (dllhandle_t *handle)); //not guarenteed to actually do anything, of course.
//general memory (mallocs and frees over dll boundaries is not usable on windows)
F(void*, Malloc, (size_t size));
F(void*, Realloc, (void *memptr, size_t size)); //doesn't zero-fill, so faster (when memptr is NULL).
F(void, Free, (void *memptr));
//for lazy mallocs
F(void*, GMalloc, (struct zonegroup_s *ctx, size_t size));
F(void, GFreeAll, (struct zonegroup_s *ctx));
#define plugcorefuncs_name "Core"
} plugcorefuncs_t;
@ -254,6 +263,13 @@ typedef struct
#define plugaudiofuncs_name "Audio"
} plugaudiofuncs_t;
typedef struct
{
F(void, BlockSizeForEncoding,(uploadfmt_t encoding, unsigned int *blockbytes, unsigned int *blockwidth, unsigned int *blockheight, unsigned int *blockdepth));
F(const char *,FormatName, (uploadfmt_t encoding));
#define plugimagefuncs_name "Image"
} plugimagefuncs_t;
typedef struct //q1 client/network info
{
F(int, GetStats, (int seat, unsigned int *stats, int maxstats));