- removed the compressed texture cache.

This is a pointless relic from the past and makes zero sense with modern graphics hardware.
This commit is contained in:
Christoph Oelckers 2019-09-17 20:18:18 +02:00
parent b1763a8f4a
commit d63cf04e06
16 changed files with 216 additions and 1227 deletions

View file

@ -204,7 +204,6 @@
<ClCompile Include="..\..\source\build\src\compat.cpp" />
<ClCompile Include="..\..\source\build\src\crc32.cpp" />
<ClCompile Include="..\..\source\build\src\defs.cpp" />
<ClCompile Include="..\..\source\build\src\dxtfilter.cpp" />
<ClCompile Include="..\..\source\build\src\dynamicgtk.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@ -326,7 +325,6 @@
<ClInclude Include="..\..\source\build\include\crc32.h" />
<ClInclude Include="..\..\source\build\include\debugbreak.h" />
<ClInclude Include="..\..\source\build\include\dxdidf.h" />
<ClInclude Include="..\..\source\build\include\dxtfilter.h" />
<ClInclude Include="..\..\source\build\include\dynamicgtk.h" />
<ClInclude Include="..\..\source\build\include\editor.h" />
<ClInclude Include="..\..\source\build\include\fix16.h" />

View file

@ -47,9 +47,6 @@
<ClCompile Include="..\..\source\build\src\defs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\source\build\src\dxtfilter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\source\build\src\dynamicgtk.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -247,9 +244,6 @@
<ClInclude Include="..\..\source\build\include\dxdidf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\source\build\include\dxtfilter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\source\build\include\dynamicgtk.h">
<Filter>Header Files</Filter>
</ClInclude>

View file

@ -1329,7 +1329,6 @@ enum cutsceneflags {
#ifdef USE_OPENGL
extern int32_t glanisotropy;
extern int32_t glusetexcompr;
extern int32_t gltexfiltermode;
extern int32_t r_useindexedcolortextures;
@ -1338,7 +1337,7 @@ enum {
TEXFILTER_ON = 5, // GL_LINEAR_MIPMAP_LINEAR
};
extern int32_t glusetexcache, glusememcache;
extern int32_t glusememcache;
extern int32_t glmultisample, glnvmultisamplehint;
extern int32_t glprojectionhacks;
extern int32_t gltexmaxsize;

View file

@ -1,11 +0,0 @@
#ifndef DXTFILTER_H_
#define DXTFILTER_H_
void dxt_handle_io(int32_t fil, int32_t len, void *midbuf, char *packbuf);
int32_t dedxt_handle_io(int32_t fil, int32_t, void *midbuf, int32_t mbufsiz, char *packbuf, int32_t ispacked);
int32_t dxtfilter(int32_t fil, const texcachepicture *pict, const char *pic, void *midbuf, char *packbuf, uint32_t miplen);
int32_t dedxtfilter(int32_t fil, const texcachepicture *pict, char *pic, void *midbuf, char *packbuf, int32_t ispacked);
#endif

View file

@ -16,9 +16,6 @@
#else
# include <GL/glu.h>
#endif
#if defined EDUKE32_GLES
# include "jwzgles.h"
#endif
# ifdef _WIN32
# define PR_CALLBACK __stdcall

View file

@ -0,0 +1,209 @@
/*
** stats.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef __STATS_H__
#define __STATS_H__
#if !defined _WIN32 && !defined __APPLE__
#ifdef NO_CLOCK_GETTIME
class cycle_t
{
public:
cycle_t &operator= (const cycle_t &o) { return *this; }
void Reset() {}
void Clock() {}
void Unclock() {}
double Time() { return 0; }
double TimeMS() { return 0; }
};
#else
#include <time.h>
class cycle_t
{
public:
void Reset()
{
Sec = 0;
}
void Clock()
{
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
Sec -= ts.tv_sec + ts.tv_nsec * 1e-9;
}
void Unclock()
{
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
Sec += ts.tv_sec + ts.tv_nsec * 1e-9;
}
double Time()
{
return Sec;
}
double TimeMS()
{
return Sec * 1e3;
}
private:
double Sec;
};
#endif
#else
// Windows and macOS
extern double PerfToSec, PerfToMillisec;
#ifdef _MSC_VER
// Trying to include intrin.h here results in some bizarre errors, so I'm just
// going to duplicate the function prototype instead.
//#include <intrin.h>
extern "C" unsigned __int64 __rdtsc(void);
#pragma intrinsic(__rdtsc)
inline unsigned __int64 rdtsc()
{
return __rdtsc();
}
#elif defined __APPLE__ && (defined __i386__ || defined __x86_64__)
inline uint64_t rdtsc()
{
return __builtin_ia32_rdtsc();
}
#else
inline uint64_t rdtsc()
{
#ifdef __amd64__
uint64_t tsc;
asm volatile ("rdtsc; shlq $32, %%rdx; orq %%rdx, %%rax" : "=a" (tsc) :: "%rdx");
return tsc;
#elif defined __ppc__
unsigned int lower, upper, temp;
do
{
asm volatile ("mftbu %0 \n mftb %1 \n mftbu %2 \n"
: "=r"(upper), "=r"(lower), "=r"(temp));
}
while (upper != temp);
return (static_cast<unsigned long long>(upper) << 32) | lower;
#else // i386
if (CPU.bRDTSC)
{
uint64_t tsc;
asm volatile ("\trdtsc\n" : "=A" (tsc));
return tsc;
}
return 0;
#endif // __amd64__
}
#endif
class cycle_t
{
public:
void Reset()
{
Counter = 0;
}
void Clock()
{
int64_t time = rdtsc();
Counter -= time;
}
void Unclock(bool checkvar = true)
{
int64_t time = rdtsc();
Counter += time;
}
double Time()
{
return Counter * PerfToSec;
}
double TimeMS()
{
return Counter * PerfToMillisec;
}
int64_t GetRawCounter()
{
return Counter;
}
private:
int64_t Counter;
};
#endif
// Helper for code that uses a timer and has multiple exit points.
class Clocker
{
public:
Clocker(cycle_t& clck)
: clock(clck)
{
clock.Clock();
}
~Clocker()
{ // unlock
clock.Unclock();
}
Clocker(const Clocker&) = delete;
Clocker& operator=(const Clocker&) = delete;
private:
cycle_t & clock;
};
#endif //__STATS_H__

View file

@ -9,72 +9,16 @@ extern "C" {
#ifdef USE_OPENGL
#define TEXCACHEMAGIC "LZ41"
#define GLTEXCACHEADSIZ 8192
#define TEXCACHEHASHSIZE 1024
enum texcacherr_t
{
TEXCACHERR_NOERROR,
TEXCACHERR_OUTOFMEMORY, /* unused */
TEXCACHERR_BUFFERUNDERRUN,
TEXCACHERR_DEDXT,
TEXCACHERR_COMPTEX,
TEXCACHERR_GETTEXLEVEL,
TEXCACHEERRORS
};
typedef struct texcacheitem_
{
char *name;
int32_t offset;
int32_t len;
struct texcacheitem_ *next;
} texcacheindex;
typedef struct {
uint8_t *buf;
buildvfs_FILE index;
texcacheindex * first;
texcacheindex * current;
texcacheindex **entries;
pthtyp *list[GLTEXCACHEADSIZ];
hashtable_t hashes;
int32_t handle;
int32_t numentries;
int32_t entrybufsiz;
int32_t pos;
int32_t memsize;
} globaltexcache;
extern globaltexcache texcache;
extern char TEXCACHEFILE[BMAX_PATH];
extern int32_t texcache_enabled(void);
extern void texcache_freeptrs(void);
extern void texcache_syncmemcache(void);
extern void texcache_init(void);
int texcache_loadoffsets(void);
int texcache_readdata(void *outBuf, int32_t len);
extern pthtyp *texcache_fetch(int32_t dapicnum, int32_t dapalnum, int32_t dashade, int32_t dameth);
extern int32_t texcache_loadskin(const texcacheheader *head, int32_t *doalloc, GLuint *glpic, vec2_t *siz);
extern int32_t texcache_loadtile(const texcacheheader *head, int32_t *doalloc, pthtyp *pth);
extern char const * texcache_calcid(char *outbuf, const char *filename, int32_t len, int32_t dameth, char effect);
extern void texcache_prewritetex(texcacheheader *head);
void texcache_postwritetex(char const * cacheid, int32_t offset);
extern void texcache_writetex_fromdriver(char const * cacheid, texcacheheader *head);
extern int texcache_readtexheader(char const * cacheid, texcacheheader *head, int32_t modelp);
extern void texcache_openfiles(void);
extern void texcache_setupmemcache(void);
extern void texcache_checkgarbage(void);
extern void texcache_setupindex(void);
#endif

View file

@ -1,252 +0,0 @@
#ifdef USE_OPENGL
/*
Description of Ken's filter to improve LZW compression of DXT1 format by ~15%: (as tested with the HRP)
To increase LZW patterns, I store each field of the DXT block structure separately.
Here are the 3 DXT fields:
1. __int64 alpha_4x4; //DXT3 only (16 byte structure size when included)
2. short rgb0, rgb1;
3. int32_t index_4x4;
Each field is then stored with its own specialized algorithm.
1. I haven't done much testing with this field - I just copy it raw without any transform for now.
2. For rgb0 and rgb1, I use a "green" filter like this:
g = g;
r = r-g;
b = b-g;
For grayscale, this makes the stream: x,0,0,x,0,0,x,0,0,... instead of x,x,x,x,x,x,x,x,...
Q:what was the significance of choosing green? A:largest/most dominant component
Believe it or not, this gave 1% better compression :P
I tried subtracting each componenet with the previous pixel, but strangely it hurt compression.
Oh, the joy of trial & error. :)
3. For index_4x4, I transform the ordering of 2-bit indices in the DXT blocks from this:
0123 0123 0123 ---- ---- ----
4567 4567 4567 ---- ---- ----
89ab 89ab 89ab ---- ---- ----
cdef cdef cdef ---- ---- ----
To this: (I swap x & y axes)
048c 048c 048c |||| |||| ||||
159d 159d 159d |||| |||| ||||
26ae 26ae 26ae |||| |||| ||||
37bf 37bf 37bf |||| |||| ||||
The trick is: going from the bottom of the 4th line to the top of the 5th line
is the exact same jump (geometrically) as from 5th to 6th, etc.. This is not true in the top case.
These silly tricks will increase patterns and therefore make LZW compress better.
I think this improved compression by a few % :)
*/
#include "compat.h"
#include "build.h"
#include "texcache.h"
#include "lz4.h"
#include <fcntl.h>
#ifdef _WIN32
# include <io.h>
#else
# include <unistd.h>
#endif
#ifndef EDUKE32_GLES
static uint16_t dxt_hicosub(uint16_t c)
{
int32_t r, g, b;
g = ((c>> 5)&63);
r = ((c>>11)-(g>>1))&31;
b = ((c>> 0)-(g>>1))&31;
return ((r<<11)+(g<<5)+b);
}
static uint16_t dedxt_hicoadd(uint16_t c)
{
int32_t r, g, b;
g = ((c>> 5)&63);
r = ((c>>11)+(g>>1))&31;
b = ((c>> 0)+(g>>1))&31;
return ((r<<11)+(g<<5)+b);
}
#endif
void dxt_handle_io(int32_t fil, int32_t len, void *midbuf, char *packbuf)
{
void *writebuf;
int32_t j, cleng;
if (glusetexcache == 2)
{
cleng = LZ4_compress_default((const char*)midbuf, packbuf, len, len);
if (cleng <= 0 || cleng > len-1)
{
cleng = len;
writebuf = midbuf;
}
else writebuf = packbuf;
}
else
{
cleng = len;
writebuf = midbuf;
}
// native -> external (little endian)
j = B_LITTLE32(cleng);
Bwrite(fil, &j, sizeof(j));
Bwrite(fil, writebuf, cleng);
}
int32_t dedxt_handle_io(int32_t fil, int32_t j /* TODO: better name */,
void *midbuf, int32_t mbufsiz, char *packbuf, int32_t ispacked)
{
void *inbuf;
int32_t cleng;
if (texcache_readdata(&cleng, sizeof(int32_t)))
return -1;
// external (little endian) -> native
cleng = B_LITTLE32(cleng);
inbuf = (ispacked && cleng < j) ? packbuf : midbuf;
if (texcache.buf && texcache.memsize >= texcache.pos + cleng)
{
if (ispacked && cleng < j)
{
if (LZ4_decompress_safe((const char *)texcache.buf + texcache.pos, (char*)midbuf, cleng, mbufsiz) <= 0)
{
texcache.pos += cleng;
return -1;
}
}
else Bmemcpy(inbuf, texcache.buf + texcache.pos, cleng);
texcache.pos += cleng;
}
else
{
Blseek(fil, texcache.pos, BSEEK_SET);
texcache.pos += cleng;
if (Bread(fil, inbuf, cleng) < cleng)
return -1;
if (ispacked && cleng < j)
if (LZ4_decompress_safe(packbuf, (char*)midbuf, cleng, mbufsiz) <= 0)
return -1;
}
return 0;
}
#ifndef EDUKE32_GLES
// NOTE: <pict> members are in external (little) endianness.
int32_t dxtfilter(int32_t fil, const texcachepicture *pict, const char *pic, void *midbuf, char *packbuf, uint32_t miplen)
{
uint32_t j, k, offs, stride;
char *cptr;
if ((pict->format == (signed) B_LITTLE32(GL_COMPRESSED_RGB_S3TC_DXT1_EXT)) ||
(pict->format == (signed) B_LITTLE32(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT))) { offs = 0; stride = 8; }
else if ((pict->format == (signed) B_LITTLE32(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)) ||
(pict->format == (signed) B_LITTLE32(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT))) { offs = 8; stride = 16; }
else
{ offs = 0; stride = 8; }
if (stride == 16) //If DXT3...
{
//alpha_4x4
cptr = (char *)midbuf;
for (k=0; k<8; k++) *cptr++ = pic[k];
for (j=stride; (unsigned)j<miplen; j+=stride)
for (k=0; k<8; k++) *cptr++ = pic[j+k];
dxt_handle_io(fil, tabledivide32(miplen, stride)<<3, midbuf, packbuf);
}
//rgb0,rgb1
cptr = (char *)midbuf;
for (k=0; k<=2; k+=2)
for (j=0; (unsigned)j<miplen; j+=stride)
{ B_BUF16(cptr, dxt_hicosub(B_UNBUF16(&pic[offs+j+k]))); cptr += 2; }
dxt_handle_io(fil, tabledivide32(miplen, stride)<<2, midbuf, packbuf);
//index_4x4
cptr = (char *)midbuf;
for (j=0; (unsigned)j<miplen; j+=stride)
{
const char *c2 = &pic[j+offs+4];
cptr[0] = ((c2[0]>>0)&3) + (((c2[1]>>0)&3)<<2) + (((c2[2]>>0)&3)<<4) + (((c2[3]>>0)&3)<<6);
cptr[1] = ((c2[0]>>2)&3) + (((c2[1]>>2)&3)<<2) + (((c2[2]>>2)&3)<<4) + (((c2[3]>>2)&3)<<6);
cptr[2] = ((c2[0]>>4)&3) + (((c2[1]>>4)&3)<<2) + (((c2[2]>>4)&3)<<4) + (((c2[3]>>4)&3)<<6);
cptr[3] = ((c2[0]>>6)&3) + (((c2[1]>>6)&3)<<2) + (((c2[2]>>6)&3)<<4) + (((c2[3]>>6)&3)<<6);
cptr += 4;
}
dxt_handle_io(fil, tabledivide32(miplen, stride)<<2, midbuf, packbuf);
return 0;
}
// NOTE: <pict> members are in native endianness.
int32_t dedxtfilter(int32_t fil, const texcachepicture *pict, char *pic, void *midbuf, char *packbuf, int32_t ispacked)
{
int32_t j, k, offs, stride;
char *cptr;
if ((pict->format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ||
(pict->format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)) { offs = 0; stride = 8; }
else if ((pict->format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) ||
(pict->format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) { offs = 8; stride = 16; }
else
{ offs = 0; stride = 8; }
if (stride == 16) //If DXT3...
{
//alpha_4x4
if (dedxt_handle_io(fil, tabledivide32(pict->size, stride)*8, midbuf, pict->size, packbuf, ispacked))
return -1;
cptr = (char *)midbuf;
for (k=0; k<8; k++) pic[k] = *cptr++;
for (j=stride; j<pict->size; j+=stride)
for (k=0; k<8; k++) pic[j+k] = (*cptr++);
}
//rgb0,rgb1
if (dedxt_handle_io(fil, tabledivide32(pict->size, stride)*4, midbuf, pict->size, packbuf, ispacked))
return -1;
cptr = (char *)midbuf;
for (k=0; k<=2; k+=2)
{
for (j=0; j<pict->size; j+=stride)
{
B_BUF16(&pic[offs+j+k], dedxt_hicoadd(B_UNBUF16(cptr)));
cptr += 2;
}
}
//index_4x4:
if (dedxt_handle_io(fil, tabledivide32(pict->size, stride)*4, midbuf, pict->size, packbuf, ispacked))
return -1;
cptr = (char *)midbuf;
for (j=0; j<pict->size; j+=stride)
{
pic[j+offs+4] = ((cptr[0]>>0)&3) + (((cptr[1]>>0)&3)<<2) + (((cptr[2]>>0)&3)<<4) + (((cptr[3]>>0)&3)<<6);
pic[j+offs+5] = ((cptr[0]>>2)&3) + (((cptr[1]>>2)&3)<<2) + (((cptr[2]>>2)&3)<<4) + (((cptr[3]>>2)&3)<<6);
pic[j+offs+6] = ((cptr[0]>>4)&3) + (((cptr[1]>>4)&3)<<2) + (((cptr[2]>>4)&3)<<4) + (((cptr[3]>>4)&3)<<6);
pic[j+offs+7] = ((cptr[0]>>6)&3) + (((cptr[1]>>6)&3)<<2) + (((cptr[2]>>6)&3)<<4) + (((cptr[3]>>6)&3)<<6);
cptr += 4;
}
return 0;
}
#endif
#endif

View file

@ -676,22 +676,8 @@ int32_t mdloadskin(md2model_t *m, int32_t number, int32_t pal, int32_t surf)
int32_t startticks = timerGetTicks(), willprint = 0;
char hasalpha;
texcacheheader cachead;
char texcacheid[BMAX_PATH];
texcache_calcid(texcacheid, fn, picfillen, pal<<8, hicfxmask(pal));
int32_t gotcache = texcache_readtexheader(texcacheid, &cachead, 1);
vec2_t siz = { 0, 0 }, tsiz = { 0, 0 };
if (gotcache && !texcache_loadskin(&cachead, &doalloc, texidx, &siz))
{
tsiz.x = cachead.xdim;
tsiz.y = cachead.ydim;
hasalpha = !!(cachead.flags & CACHEAD_HASALPHA);
if (pal < (MAXPALOOKUPS - RESERVEDPALS))
m->usesalpha = hasalpha;
}
else
{
polytintflags_t const effect = hicfxmask(pal);
@ -699,8 +685,6 @@ int32_t mdloadskin(md2model_t *m, int32_t number, int32_t pal, int32_t surf)
int32_t isart = 0;
gotcache = 0; // the compressed version will be saved to disk
int32_t const length = kpzbufload(fn);
if (length == 0)
return mdloadskin_notfound(skinfile, fn);
@ -940,35 +924,6 @@ int32_t mdloadskin(md2model_t *m, int32_t number, int32_t pal, int32_t surf)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
#if defined USE_GLEXT && !defined EDUKE32_GLES
if (!gotcache && glinfo.texcompr && glusetexcache && !(sk->flags & HICR_NOTEXCOMPRESS) &&
(glusetexcompr == 2 || (glusetexcompr && !(sk->flags & HICR_ARTIMMUNITY))))
{
const int32_t nonpow2 = check_nonpow2(siz.x) || check_nonpow2(siz.y);
// save off the compressed version
cachead.quality = (sk->flags & (HICR_NODOWNSIZE|HICR_ARTIMMUNITY)) ? 0 : r_downsize;
cachead.xdim = tsiz.x>>cachead.quality;
cachead.ydim = tsiz.y>>cachead.quality;
cachead.flags = nonpow2*CACHEAD_NONPOW2 | (hasalpha ? CACHEAD_HASALPHA : 0) |
((sk->flags & (HICR_NODOWNSIZE|HICR_ARTIMMUNITY)) ? CACHEAD_NODOWNSIZE : 0);
/// OSD_Printf("Caching \"%s\"\n",fn);
texcache_writetex_fromdriver(texcacheid, &cachead);
if (willprint)
{
int32_t etime = timerGetTicks()-startticks;
if (etime>=MIN_CACHETIME_PRINT)
OSD_Printf("Load skin: p%d-e%d \"%s\"... cached... %d ms\n", pal, hicfxmask(pal), fn, etime);
willprint = 0;
}
else
OSD_Printf("Cached skin \"%s\"\n", fn);
}
#endif
if (willprint)
{
int32_t etime = timerGetTicks()-startticks;

View file

@ -95,15 +95,10 @@ struct glfiltermodes glfiltermodes[NUMGLFILTERMODES] =
int32_t glanisotropy = 0; // 0 = maximum supported by card
int32_t gltexfiltermode = TEXFILTER_OFF;
#ifdef EDUKE32_GLES
int32_t glusetexcompr = 2;
int32_t glusetexcache = 0, glusememcache = 0;
#else
int32_t glusetexcompr = 1;
int32_t glusetexcache = 2, glusememcache = 1;
int32_t glusememcache = 1;
int32_t r_polygonmode = 0; // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK
static int32_t lastglpolygonmode = 0; //FUK
#endif
#ifdef USE_GLEXT
int32_t glmultisample = 0, glnvmultisamplehint = 0;
int32_t r_detailmapping = 1;
@ -225,7 +220,7 @@ int32_t r_parallaxskypanning = 1;
void GetTextureHandle(GLuint *handle)
{
*handle = GLInstance.GetTextureID();
*handle = GLInterface.GetTextureID();
}
@ -322,6 +317,8 @@ void gltexapplyprops(void)
if (videoGetRenderMode() == REND_CLASSIC)
return;
GLInterface.mSamplers->SetTextureFilterMode(gltexfiltermode, glanisotropy);
if (glinfo.maxanisotropy > 1.f)
{
if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy)
@ -527,9 +524,6 @@ void polymost_glreset()
Bmemset(texcache.list,0,sizeof(texcache.list));
glox1 = -1;
texcache_freeptrs();
texcache_syncmemcache();
#ifdef DEBUGGINGAIDS
OSD_Printf("polymost_glreset()\n");
#endif
@ -1212,14 +1206,7 @@ void polymost_glinit()
}
polymost_resetVertexPointers();
texcache_init();
texcache_loadoffsets();
texcache_openfiles();
texcache_setupmemcache();
texcache_checkgarbage();
#if defined EDUKE32_GLES
Polymost_DetermineTextureFormatSupport();
#endif
@ -1823,25 +1810,6 @@ void gloadtile_art(int32_t dapic, int32_t dapal, int32_t tintpalnum, int32_t das
char hasalpha = 0, hasfullbright = 0;
char npoty = 0;
texcacheheader cachead;
char texcacheid[BMAX_PATH];
{
// Absolutely disgusting.
uint32_t firstint = 0;
if (waloff[dapic])
Bmemcpy(&firstint, (void *)waloff[dapic], min(4, picdim));
sprintf(texcacheid, "%08x", firstint);
}
texcache_calcid(texcacheid, texcacheid, picdim | ((unsigned)dapal<<24u), DAMETH_NARROW_MASKPROPS(dameth) | ((unsigned)dapic<<8u) | ((unsigned)dashade<<24u), tintpalnum);
int32_t gotcache = texcache_readtexheader(texcacheid, &cachead, 0);
if (gotcache && !texcache_loadtile(&cachead, &doalloc, pth))
{
hasalpha = !!(cachead.flags & CACHEAD_HASALPHA);
hasfullbright = !!(cachead.flags & CACHEAD_HASFULLBRIGHT);
npoty = !!(cachead.flags & CACHEAD_NPOTWALL);
}
else
{
if (!glinfo.texnpot)
{
@ -2014,21 +1982,6 @@ void gloadtile_art(int32_t dapic, int32_t dapal, int32_t tintpalnum, int32_t das
pth->flags = TO_PTH_CLAMPED(dameth) | TO_PTH_NOTRANSFIX(dameth) | (hasalpha*PTH_HASALPHA) | (npoty*PTH_NPOTWALL);
pth->hicr = NULL;
#if defined USE_GLEXT && !defined EDUKE32_GLES
if (!gotcache && glinfo.texcompr && glusetexcache && glusetexcompr == 2 && dapic < MAXUSERTILES)
{
cachead.quality = 0;
cachead.xdim = tsiz.x;
cachead.ydim = tsiz.y;
cachead.flags = (check_nonpow2(siz.x) || check_nonpow2(siz.y)) * CACHEAD_NONPOW2 |
npoty * CACHEAD_NPOTWALL |
hasalpha * CACHEAD_HASALPHA | hasfullbright * CACHEAD_HASFULLBRIGHT | CACHEAD_NODOWNSIZE;
texcache_writetex_fromdriver(texcacheid, &cachead);
}
#endif
if (hasfullbright && !fullbrightloadingpass)
{
// Load the ONLY texture that'll be assembled with the regular one to
@ -2081,26 +2034,13 @@ int32_t gloadtile_hi(int32_t dapic,int32_t dapalnum, int32_t facen, hicreplctyp
int32_t startticks = timerGetTicks(), willprint = 0;
char hasalpha;
texcacheheader cachead;
char texcacheid[BMAX_PATH];
texcache_calcid(texcacheid, fn, picfillen+(dapalnum<<8), DAMETH_NARROW_MASKPROPS(dameth), effect & HICTINT_IN_MEMORY);
int32_t gotcache = texcache_readtexheader(texcacheid, &cachead, 0);
vec2_t siz = { 0, 0 }, tsiz = { 0, 0 };
if (gotcache && !texcache_loadtile(&cachead, &doalloc, pth))
{
tsiz.x = cachead.xdim;
tsiz.y = cachead.ydim;
hasalpha = !!(cachead.flags & CACHEAD_HASALPHA);
}
else
{
// CODEDUP: mdloadskin
int32_t isart = 0;
gotcache = 0; // the compressed version will be saved to disk
int32_t const length = kpzbufload(fn);
if (length == 0)
return -1;
@ -2333,36 +2273,6 @@ int32_t gloadtile_hi(int32_t dapic,int32_t dapalnum, int32_t facen, hicreplctyp
pth->skyface = facen;
pth->hicr = hicr;
#if defined USE_GLEXT && !defined EDUKE32_GLES
if (!gotcache && glinfo.texcompr && glusetexcache && !(hicr->flags & HICR_NOTEXCOMPRESS) &&
(glusetexcompr == 2 || (glusetexcompr && !(hicr->flags & HICR_ARTIMMUNITY))))
{
const int32_t nonpow2 = check_nonpow2(siz.x) || check_nonpow2(siz.y);
// save off the compressed version
cachead.quality = (hicr->flags & (HICR_NODOWNSIZE|HICR_ARTIMMUNITY)) ? 0 : r_downsize;
cachead.xdim = tsiz.x >> cachead.quality;
cachead.ydim = tsiz.y >> cachead.quality;
// handle nodownsize:
cachead.flags = nonpow2 * CACHEAD_NONPOW2 | (hasalpha ? CACHEAD_HASALPHA : 0) |
((hicr->flags & (HICR_NODOWNSIZE|HICR_ARTIMMUNITY)) ? CACHEAD_NODOWNSIZE : 0);
/// OSD_Printf("Caching \"%s\"\n", fn);
texcache_writetex_fromdriver(texcacheid, &cachead);
if (willprint)
{
int32_t etime = timerGetTicks() - startticks;
if (etime >= MIN_CACHETIME_PRINT)
OSD_Printf("Load tile %4d: p%d-m%d-e%d %s... cached... %d ms\n", dapic, dapalnum, dameth, effect,
willprint == 2 ? fn : "", etime);
willprint = 0;
}
else
OSD_Printf("Cached \"%s\"\n", fn);
}
#endif
if (willprint)
{
@ -7499,7 +7409,6 @@ static int32_t gltexturemode(osdcmdptr_t parm)
gltexfiltermode = m;
gltexapplyprops();
GLInterface.mSamplers->SetTextureFilterMode(gltexfiltermode, glanisotropy);
OSD_Printf("Texture filtering mode changed to %s\n", glfiltermodes[gltexfiltermode].name);
@ -7534,7 +7443,6 @@ static int osdcmd_cvar_set_polymost(osdcmdptr_t parm)
if (in3dmode() && r_downsize != r_downsizevar)
{
texcache_invalidate();
videoResetMode();
if (videoSetGameMode(fullscreen,xres,yres,bpp,upscalefactor))
OSD_Printf("restartvid: Reset failed...\n");
@ -7544,7 +7452,6 @@ static int osdcmd_cvar_set_polymost(osdcmdptr_t parm)
}
else if (!Bstrcasecmp(parm->name, "r_anisotropy"))
{
GLInterface.mSamplers->SetTextureFilterMode(gltexfiltermode, glanisotropy);
gltexapplyprops();
}
else if (!Bstrcasecmp(parm->name, "r_texfilter"))
@ -7576,10 +7483,7 @@ void polymost_initosdfuncs(void)
#endif
#ifndef EDUKE32_GLES
{ "r_polygonmode","debugging feature",(void *) &r_polygonmode, CVAR_INT | CVAR_NOSAVE, 0, 3 },
{ "r_texcache","enable/disable OpenGL compressed texture cache",(void *) &glusetexcache, CVAR_INT, 0, 2 },
{ "r_memcache","enable/disable texture cache memory cache",(void *) &glusememcache, CVAR_BOOL, 0, 1 },
#endif
{ "r_texcompr","enable/disable OpenGL texture compression: 0: off 1: hightile only 2: ART and hightile",(void *) &glusetexcompr, CVAR_INT, 0, 2 },
{ "r_shadescale","multiplier for shading",(void *) &shadescale, CVAR_FLOAT, 0, 10 },
{ "r_shadescale_unbounded","enable/disable allowance of complete blackness",(void *) &shadescale_unbounded, CVAR_BOOL, 0, 1 },

View file

@ -6,37 +6,18 @@
#include "hightile.h"
#include "polymost.h"
#include "texcache.h"
#include "dxtfilter.h"
#include "scriptfile.h"
#include "xxhash.h"
#include "kplib.h"
#include "vfs.h"
#include <fcntl.h>
#ifdef _WIN32
# include <io.h>
#else
# include <unistd.h>
#endif
#include <sys/stat.h>
#define CLEAR_GL_ERRORS() while(glGetError() != GL_NO_ERROR) { }
#define TEXCACHE_FREEBUFS() { Bfree(pic), Bfree(packbuf), Bfree(midbuf); }
globaltexcache texcache;
char TEXCACHEFILE[BMAX_PATH] = "texturecache";
static const char *texcache_errors[TEXCACHEERRORS] = {
"no error",
"out of memory!",
"read too few bytes from cache file",
"dedxtfilter failed",
"glCompressedTexImage2DARB failed",
"glGetTexLevelParameteriv failed",
};
static pthtyp *texcache_tryart(int32_t const dapicnum, int32_t const dapalnum, int32_t const dashade, int32_t dameth)
{
const int32_t j = dapicnum&(GLTEXCACHEADSIZ-1);
@ -217,675 +198,7 @@ pthtyp *texcache_fetch(int32_t dapicnum, int32_t dapalnum, int32_t dashade, int3
return (drawingskybox || hicprecaching) ? NULL : texcache_tryart(dapicnum, dapalnum, dashade, dameth);
}
static void texcache_closefiles(void)
{
if (texcache.handle != -1)
{
Bclose(texcache.handle);
texcache.handle = -1;
}
MAYBE_FCLOSE_AND_NULL(texcache.index);
}
void texcache_freeptrs(void)
{
texcache.entrybufsiz = 0;
if (!texcache.entries)
return;
for (bssize_t i = 0; i < texcache.numentries; i++)
if (texcache.entries[i])
{
for (bssize_t ii = texcache.numentries - 1; ii >= 0; ii--)
if (i != ii && texcache.entries[ii] == texcache.entries[i])
{
/*OSD_Printf("removing duplicate cacheptr %d\n",ii);*/
texcache.entries[ii] = NULL;
}
DO_FREE_AND_NULL(texcache.entries[i]->name);
DO_FREE_AND_NULL(texcache.entries[i]);
}
DO_FREE_AND_NULL(texcache.entries);
}
static inline void texcache_clearmemcache(void)
{
DO_FREE_AND_NULL(texcache.buf);
texcache.memsize = -1;
}
void texcache_syncmemcache(void)
{
int32_t len = buildvfs_length(texcache.handle);
if (!texcache.buf || texcache.handle == -1 || len <= (int32_t)texcache.memsize)
return;
texcache.buf = (uint8_t *)Xrealloc(texcache.buf, len);
if (!texcache.buf)
{
texcache_clearmemcache();
initprintf("Failed syncing memcache!\n");
glusememcache = 0;
}
else
{
initprintf("Syncing memcache\n");
Blseek(texcache.handle, texcache.memsize, BSEEK_SET);
if (Bread(texcache.handle, texcache.buf + texcache.memsize, len - texcache.memsize) != (bssize_t)(len-texcache.memsize))
{
initprintf("Failed reading texcache into memcache!\n");
texcache_clearmemcache();
glusememcache = 0;
}
else
texcache.memsize = len;
}
}
void texcache_init(void)
{
if (!texcache.index)
texcache.handle = -1;
texcache_closefiles();
texcache_clearmemcache();
texcache_freeptrs();
texcache.current = texcache.first = (texcacheindex *)Xcalloc(1, sizeof(texcacheindex));
texcache.numentries = 0;
// Bmemset(&firstcacheindex, 0, sizeof(texcacheindex));
// Bmemset(&cacheptrs[0], 0, sizeof(cacheptrs));
texcache.hashes.size = TEXCACHEHASHSIZE;
hash_init(&texcache.hashes);
}
static void texcache_deletefiles(void)
{
unlink(TEXCACHEFILE);
Bstrcpy(ptempbuf, TEXCACHEFILE);
Bstrcat(ptempbuf, ".index");
unlink(ptempbuf);
}
int32_t texcache_enabled(void)
{
#if defined EDUKE32_GLES || !defined USE_GLEXT
return 0;
#else
if (!glinfo.texcompr || !glusetexcompr || !glusetexcache)
return 0;
if (!texcache.index || texcache.handle < 0)
{
OSD_Printf("Warning: no active cache!\n");
return 0;
}
return 1;
#endif
}
void texcache_openfiles(void)
{
Bstrcpy(ptempbuf, TEXCACHEFILE);
Bstrcat(ptempbuf, ".index");
bool const texcache_exists = buildvfs_exists(ptempbuf);
texcache.index = buildvfs_fopen_append(ptempbuf);
texcache.handle = Bopen(TEXCACHEFILE, BO_BINARY | BO_CREAT | BO_APPEND | BO_RDWR, BS_IREAD | BS_IWRITE);
if (!texcache.index || texcache.handle == -1)
{
initprintf("Unable to open cache file \"%s\" or \"%s\": %s\n", TEXCACHEFILE, ptempbuf, strerror(errno));
texcache_closefiles();
glusetexcache = 0;
return;
}
if (!texcache_exists)
{
buildvfs_fputstr(texcache.index, "// automatically generated by the engine, DO NOT MODIFY!\n");
}
initprintf("Opened \"%s\" as cache file\n", TEXCACHEFILE);
}
void texcache_checkgarbage(void)
{
if (!texcache_enabled())
return;
texcache.current = texcache.first;
int32_t bytes = 0;
while (texcache.current->next)
{
bytes += texcache.current->len;
texcache.current = texcache.current->next;
}
bytes = Blseek(texcache.handle, 0, BSEEK_END)-bytes;
if (bytes)
initprintf("Cache contains %d bytes of garbage data\n", bytes);
}
void texcache_invalidate(void)
{
#ifdef DEBUGGINGAIDS
OSD_Printf("texcache_invalidate()\n");
#endif
r_downsizevar = r_downsize; // update the cvar representation when the menu changes r_downsize
polymost_glreset();
texcache_init();
texcache_deletefiles();
texcache_openfiles();
}
int texcache_loadoffsets(void)
{
Bstrcpy(ptempbuf, TEXCACHEFILE);
Bstrcat(ptempbuf, ".index");
scriptfile *script = scriptfile_fromfile(ptempbuf);
if (!script) return -1;
int32_t foffset, fsize;
char *fname;
while (!scriptfile_eof(script))
{
if (scriptfile_getstring(script, &fname)) break; // hashed filename
if (scriptfile_getnumber(script, &foffset)) break; // offset in cache
if (scriptfile_getnumber(script, &fsize)) break; // size
int const i = hash_find(&texcache.hashes,fname);
if (i > -1)
{
// update an existing entry
texcacheindex *t = texcache.entries[i];
t->offset = foffset;
t->len = fsize;
/*initprintf("%s %d got a match for %s offset %d\n",__FILE__, __LINE__, fname,foffset);*/
}
else
{
texcacheindex * const index = texcache.current;
index->name = Xstrdup(fname);
index->offset = foffset;
index->len = fsize;
index->next = (texcacheindex *) Xcalloc(1, sizeof(texcacheindex));
hash_add(&texcache.hashes, fname, texcache.numentries, 1);
if (++texcache.numentries > texcache.entrybufsiz)
{
texcache.entrybufsiz += 512;
texcache.entries = (texcacheindex **) Xrealloc(texcache.entries, sizeof(intptr_t) * texcache.entrybufsiz);
}
texcache.entries[texcache.numentries-1] = texcache.current;
texcache.current = index->next;
}
}
scriptfile_close(script);
return 0;
}
// Read from on-disk texcache or its in-memory cache.
int texcache_readdata(void *outBuf, int32_t len)
{
const int32_t ofilepos = texcache.pos;
texcache.pos += len;
if (texcache.buf && texcache.memsize >= ofilepos + len)
{
// initprintf("using memcache!\n");
Bmemcpy(outBuf, texcache.buf + ofilepos, len);
return 0;
}
if (Blseek(texcache.handle, ofilepos, BSEEK_SET) != ofilepos ||
Bread(texcache.handle, outBuf, len) < len)
return 1;
return 0;
}
char const * texcache_calcid(char *outbuf, const char *filename, const int32_t len, const int32_t dameth, const char effect)
{
// Assert that BMAX_PATH is a multiple of 4 so that struct texcacheid_t
// gets no padding inserted by the compiler.
EDUKE32_STATIC_ASSERT((BMAX_PATH & 3) == 0);
struct texcacheid_t {
int32_t len, method;
char effect, name[BMAX_PATH+3]; // +3: pad to a multiple of 4
} id = { len, dameth, effect, "" };
Bstrcpy(id.name, filename);
size_t const fnlen = Bstrlen(filename);
size_t idlen = Bstrlen(id.name);
while (idlen < BMAX_PATH - fnlen)
{
Bstrcat(id.name, filename);
idlen += fnlen;
}
Bsprintf(outbuf, "%08x%08x%08x",
XXH32((uint8_t *)id.name, fnlen, TEXCACHEMAGIC[3]),
XXH32((uint8_t *)id.name, Bstrlen(id.name), TEXCACHEMAGIC[3]),
XXH32((uint8_t *)&id, sizeof(struct texcacheid_t), TEXCACHEMAGIC[3]));
return outbuf;
}
#define FAIL(x) { err = x; goto failure; }
// returns 1 on success
int texcache_readtexheader(char const * cacheid, texcacheheader *head, int32_t modelp)
{
if (!texcache_enabled())
return 0;
int32_t i = hash_find(&texcache.hashes, cacheid);
if (i < 0 || !texcache.entries[i])
return 0; // didn't find it
texcache.pos = texcache.entries[i]->offset;
// initprintf("%s %d got a match for %s offset %d\n",__FILE__, __LINE__, cachefn,offset);
int err = 0;
if (texcache_readdata(head, sizeof(texcacheheader)))
FAIL(0);
if (Bmemcmp(head->magic, TEXCACHEMAGIC, 4))
FAIL(1);
// native (little-endian) -> internal
head->xdim = B_LITTLE32(head->xdim);
head->ydim = B_LITTLE32(head->ydim);
head->flags = B_LITTLE32(head->flags);
head->quality = B_LITTLE32(head->quality);
if (modelp && head->quality != r_downsize)
FAIL(2);
if ((head->flags & CACHEAD_COMPRESSED) && glusetexcache != 2)
FAIL(3);
if (!(head->flags & CACHEAD_COMPRESSED) && glusetexcache == 2)
FAIL(4);
// handle nodownsize
if (!modelp && !(head->flags & CACHEAD_NODOWNSIZE) && head->quality != r_downsize)
return 0;
if (gltexmaxsize && (head->xdim > (1<<gltexmaxsize) || head->ydim > (1<<gltexmaxsize)))
FAIL(5);
if (!glinfo.texnpot && (head->flags & CACHEAD_NONPOW2))
FAIL(6);
return 1;
failure:
{
static const char *error_msgs[] = {
"failed reading texture cache header", // 0
"header magic string doesn't match", // 1
"r_downsize doesn't match", // 2 (skins only)
"compression doesn't match: cache contains compressed tex", // 3
"compression doesn't match: cache contains uncompressed tex", // 4
"texture in cache exceeds maximum supported size", // 5
"texture in cache has non-power-of-two size, unsupported", // 6
};
initprintf("%s cache miss: %s\n", modelp?"Skin":"Texture", error_msgs[err]);
}
return 0;
}
#undef READTEXHEADER_FAILURE
#if defined USE_GLEXT && !defined EDUKE32_GLES
void texcache_prewritetex(texcacheheader *head)
{
Bmemcpy(head->magic, TEXCACHEMAGIC, 4); // sizes are set by caller
if (glusetexcache == 2)
head->flags |= CACHEAD_COMPRESSED;
// native -> external (little-endian)
head->xdim = B_LITTLE32(head->xdim);
head->ydim = B_LITTLE32(head->ydim);
head->flags = B_LITTLE32(head->flags);
head->quality = B_LITTLE32(head->quality);
}
#define WRITEX_FAIL_ON_ERROR() if (glGetError() != GL_NO_ERROR) goto failure
void texcache_writetex_fromdriver(char const * const cacheid, texcacheheader *head)
{
if (!texcache_enabled()) return;
GLint gi = GL_FALSE;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &gi);
if (gi != GL_TRUE)
{
static GLint glGetTexLevelParameterivOK = GL_TRUE;
if (glGetTexLevelParameterivOK == GL_TRUE)
{
OSD_Printf("Error: glGetTexLevelParameteriv returned GL_FALSE!\n");
glGetTexLevelParameterivOK = GL_FALSE;
}
return;
}
texcache_prewritetex(head);
Blseek(texcache.handle, 0, BSEEK_END);
size_t const offset = Blseek(texcache.handle, 0, BSEEK_CUR);
texcachepicture pict;
char *pic = nullptr;
char *packbuf = nullptr;
void *midbuf = nullptr;
size_t alloclen = 0;
// OSD_Printf("Caching %s, offset 0x%x\n", cachefn, offset);
if (Bwrite(texcache.handle, head, sizeof(texcacheheader)) != sizeof(texcacheheader)) goto failure;
CLEAR_GL_ERRORS();
for (uint32_t level = 0, padx = 0, pady = 0; level == 0 || (padx > 1 || pady > 1); ++level)
{
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED, &gi);
WRITEX_FAIL_ON_ERROR();
if (gi != GL_TRUE)
goto failure; // an uncompressed mipmap
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, &gi);
WRITEX_FAIL_ON_ERROR();
#if defined __APPLE__ && defined POLYMER
if (pr_ati_textureformat_one && gi == 1) gi = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
#endif
// native -> external (little endian)
pict.format = B_LITTLE32(gi);
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &gi);
WRITEX_FAIL_ON_ERROR();
padx = gi;
pict.xdim = B_LITTLE32(gi);
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &gi);
WRITEX_FAIL_ON_ERROR();
pady = gi;
pict.ydim = B_LITTLE32(gi);
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_BORDER, &gi);
WRITEX_FAIL_ON_ERROR();
pict.border = B_LITTLE32(gi);
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_DEPTH, &gi);
WRITEX_FAIL_ON_ERROR();
pict.depth = B_LITTLE32(gi);
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &gi);
WRITEX_FAIL_ON_ERROR();
uint32_t miplen = gi;
pict.size = B_LITTLE32(gi);
if (alloclen < miplen)
{
alloclen = miplen;
pic = (char *)Xrealloc(pic, miplen);
packbuf = (char *)Xrealloc(packbuf, miplen);
midbuf = (void *)Xrealloc(midbuf, miplen);
}
glGetCompressedTexImage(GL_TEXTURE_2D, level, pic);
WRITEX_FAIL_ON_ERROR();
if (Bwrite(texcache.handle, &pict, sizeof(texcachepicture)) != sizeof(texcachepicture)) goto failure;
if (dxtfilter(texcache.handle, &pict, pic, midbuf, packbuf, miplen)) goto failure;
}
texcache_postwritetex(cacheid, offset);
TEXCACHE_FREEBUFS();
return;
failure:
initprintf("ERROR: cache failure!\n");
texcache.current->offset = 0;
Bfree(texcache.current->name);
TEXCACHE_FREEBUFS();
}
#undef WRITEX_FAIL_ON_ERROR
void texcache_postwritetex(char const * const cacheid, int32_t const offset)
{
int32_t const i = hash_find(&texcache.hashes, cacheid);
texcacheindex *t;
if (i > -1)
{
// update an existing entry
t = texcache.entries[i];
t->offset = offset;
t->len = Blseek(texcache.handle, 0, BSEEK_CUR) - t->offset;
/*initprintf("%s %d got a match for %s offset %d\n",__FILE__, __LINE__, cachefn,offset);*/
}
else
{
t = texcache.current;
Bfree(t->name);
t->name = Xstrdup(cacheid);
t->offset = offset;
t->len = Blseek(texcache.handle, 0, BSEEK_CUR) - t->offset;
t->next = (texcacheindex *)Xcalloc(1, sizeof(texcacheindex));
hash_add(&texcache.hashes, cacheid, texcache.numentries, 0);
if (++texcache.numentries > texcache.entrybufsiz)
{
texcache.entrybufsiz += 512;
texcache.entries = (texcacheindex **)Xrealloc(texcache.entries, sizeof(intptr_t) * texcache.entrybufsiz);
}
texcache.entries[texcache.numentries - 1] = t;
texcache.current = t->next;
}
if (texcache.index)
{
char buf[64];
buildvfs_fputstrptr(texcache.index, t->name);
snprintf(buf, sizeof(buf), " %d %d\n", t->offset, t->len);
buildvfs_fputstrptr(texcache.index, buf);
}
else
OSD_Printf("wtf?\n");
}
#endif
static void texcache_setuptexture(int32_t *doalloc, GLuint *glpic)
{
if (*doalloc&1)
{
glGenTextures(1, glpic); //# of textures (make OpenGL allocate structure)
*doalloc |= 2; // prevents glGenTextures being called again if we fail in here
}
glBindTexture(GL_TEXTURE_2D, *glpic);
}
static int32_t texcache_loadmips(const texcacheheader *head, GLenum *glerr)
{
texcachepicture pict;
char *pic = nullptr;
char *packbuf = nullptr;
void *midbuf = nullptr;
int32_t alloclen=0;
#if !defined USE_GLEXT && defined EDUKE32_GLES
UNREFERENCED_PARAMETER(glerr);
UNREFERENCED_PARAMETER(head);
#endif
for (bssize_t level = 0; level==0 || (pict.xdim > 1 || pict.ydim > 1); level++)
{
if (texcache_readdata(&pict, sizeof(texcachepicture)))
{
TEXCACHE_FREEBUFS();
return TEXCACHERR_BUFFERUNDERRUN;
}
// external (little endian) -> native
pict.size = B_LITTLE32(pict.size);
pict.format = B_LITTLE32(pict.format);
pict.xdim = B_LITTLE32(pict.xdim);
pict.ydim = B_LITTLE32(pict.ydim);
pict.border = B_LITTLE32(pict.border);
pict.depth = B_LITTLE32(pict.depth);
if (alloclen < pict.size)
{
alloclen = pict.size;
pic = (char *)Xrealloc(pic, pict.size);
packbuf = (char *)Xrealloc(packbuf, pict.size + 16);
midbuf = (void *)Xrealloc(midbuf, pict.size);
}
#if defined USE_GLEXT && !defined EDUKE32_GLES
if (dedxtfilter(texcache.handle, &pict, pic, midbuf, packbuf, (head->flags & CACHEAD_COMPRESSED) != 0))
{
TEXCACHE_FREEBUFS();
return TEXCACHERR_DEDXT;
}
glCompressedTexImage2D(GL_TEXTURE_2D, level, pict.format, pict.xdim, pict.ydim, pict.border, pict.size, pic);
if ((*glerr=glGetError()) != GL_NO_ERROR)
{
TEXCACHE_FREEBUFS();
return TEXCACHERR_COMPTEX;
}
GLint format;
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, &format);
if ((*glerr = glGetError()) != GL_NO_ERROR)
{
TEXCACHE_FREEBUFS();
return TEXCACHERR_GETTEXLEVEL;
}
if (pict.format != format)
{
OSD_Printf("gloadtile_cached: invalid texture cache file format %d %d\n", pict.format, format);
TEXCACHE_FREEBUFS();
return -1;
}
#endif
}
TEXCACHE_FREEBUFS();
return 0;
}
int32_t texcache_loadskin(const texcacheheader *head, int32_t *doalloc, GLuint *glpic, vec2_t *siz)
{
int32_t err=0;
GLenum glerr=GL_NO_ERROR;
texcache_setuptexture(doalloc, glpic);
siz->x = head->xdim;
siz->y = head->ydim;
CLEAR_GL_ERRORS();
if ((err = texcache_loadmips(head, &glerr)))
{
if (err > 0)
initprintf("texcache_loadskin: %s (glerr=%x)\n", texcache_errors[err], glerr);
return -1;
}
return 0;
}
int32_t texcache_loadtile(const texcacheheader *head, int32_t *doalloc, pthtyp *pth)
{
int32_t err = 0;
GLenum glerr = GL_NO_ERROR;
texcache_setuptexture(doalloc, &pth->glpic);
pth->siz.x = head->xdim;
pth->siz.y = head->ydim;
CLEAR_GL_ERRORS();
if ((err = texcache_loadmips(head, &glerr)))
{
if (err > 0)
initprintf("texcache_loadtile: %s (glerr=%x)\n", texcache_errors[err], glerr);
return -1;
}
return 0;
}
void texcache_setupmemcache(void)
{
if (!glusememcache || !texcache_enabled())
return;
texcache.memsize = buildvfs_length(texcache.handle);
if (texcache.memsize <= 0)
return;
texcache.buf = (uint8_t *)Xrealloc(texcache.buf, texcache.memsize);
if (!texcache.buf)
{
initprintf("Failed allocating %d bytes for memcache!\n", (int)texcache.memsize);
texcache_clearmemcache();
glusememcache = 0;
return;
}
if (Bread(texcache.handle, texcache.buf, texcache.memsize) != (bssize_t)texcache.memsize)
{
initprintf("Failed reading texcache into memcache!\n");
texcache_clearmemcache();
glusememcache = 0;
}
}
#endif

View file

@ -430,10 +430,6 @@ void G_LoadGroups(int32_t autoload)
}
}
#ifdef USE_OPENGL
Bsnprintf(path, sizeof(path), "%s/%s", g_modDir, TEXCACHEFILE);
Bstrcpy(TEXCACHEFILE, path);
#endif
}
if (g_addonNum)

View file

@ -1023,8 +1023,6 @@ static MenuEntry_t ME_RENDERERSETUP_PRECACHE = MAKE_MENUENTRY( "Pre-load map tex
# ifndef EDUKE32_GLES
static char const *MEOSN_RENDERERSETUP_TEXCACHE[] = { "Off", "On", "Compr.", };
static MenuOptionSet_t MEOS_RENDERERSETUP_TEXCACHE = MAKE_MENUOPTIONSET( MEOSN_RENDERERSETUP_TEXCACHE, NULL, 0x2 );
static MenuOption_t MEO_RENDERERSETUP_TEXCACHE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_RENDERERSETUP_TEXCACHE, &glusetexcache );
static MenuEntry_t ME_RENDERERSETUP_TEXCACHE = MAKE_MENUENTRY( "On-disk texture cache:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_TEXCACHE, Option );
# endif
# ifdef USE_GLEXT
static MenuOption_t MEO_RENDERERSETUP_DETAILTEX = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &r_detailmapping );
@ -1038,34 +1036,12 @@ static MenuOption_t MEO_RENDERERSETUP_PALETTEEMULATION = MAKE_MENUOPTION(&MF_Blu
static MenuEntry_t ME_RENDERERSETUP_PALETTEEMULATION = MAKE_MENUENTRY("Palette emulation:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_PALETTEEMULATION, Option);
#endif
#ifdef POLYMER
static char const *MEOSN_POLYMER_LIGHTS [] = { "Off", "Full", "Map only", };
static MenuOptionSet_t MEOS_POLYMER_LIGHTS = MAKE_MENUOPTIONSET(MEOSN_POLYMER_LIGHTS, NULL, 0x2);
static MenuOption_t MEO_POLYMER_LIGHTS = MAKE_MENUOPTION(&MF_Bluefont, &MEOS_POLYMER_LIGHTS, &pr_lighting);
static MenuEntry_t ME_POLYMER_LIGHTS = MAKE_MENUENTRY("Dynamic lights:", &MF_Bluefont, &MEF_SmallOptions, &MEO_POLYMER_LIGHTS, Option);
static MenuRangeInt32_t MEO_POLYMER_LIGHTPASSES = MAKE_MENURANGE(&r_pr_maxlightpasses, &MF_Bluefont, 1, 10, 1, 10, 1);
static MenuEntry_t ME_POLYMER_LIGHTPASSES = MAKE_MENUENTRY("Lights per surface:", &MF_Bluefont, &MEF_SmallOptions, &MEO_POLYMER_LIGHTPASSES, RangeInt32);
static MenuOption_t MEO_POLYMER_SHADOWS = MAKE_MENUOPTION(&MF_Bluefont, &MEOS_OffOn, &pr_shadows);
static MenuEntry_t ME_POLYMER_SHADOWS = MAKE_MENUENTRY("Dynamic shadows:", &MF_Bluefont, &MEF_SmallOptions, &MEO_POLYMER_SHADOWS, Option);
static MenuRangeInt32_t MEO_POLYMER_SHADOWCOUNT = MAKE_MENURANGE(&pr_shadowcount, &MF_Bluefont, 1, 10, 1, 10, 1);
static MenuEntry_t ME_POLYMER_SHADOWCOUNT = MAKE_MENUENTRY("Shadows per surface:", &MF_Bluefont, &MEF_SmallOptions, &MEO_POLYMER_SHADOWCOUNT, RangeInt32);
static MenuOption_t MEO_POLYMER_PALETTEEMULATION = MAKE_MENUOPTION(&MF_Bluefont, &MEOS_NoYes, &pr_artmapping);
static MenuEntry_t ME_POLYMER_PALETTEEMULATION = MAKE_MENUENTRY("Palette emulation:", &MF_Bluefont, &MEF_SmallOptions, &MEO_POLYMER_PALETTEEMULATION, Option);
#endif
#ifdef USE_OPENGL
static MenuEntry_t *MEL_RENDERERSETUP_POLYMOST[] = {
&ME_RENDERERSETUP_HIGHTILE,
&ME_RENDERERSETUP_TEXQUALITY,
&ME_RENDERERSETUP_PRECACHE,
# ifndef EDUKE32_GLES
&ME_RENDERERSETUP_TEXCACHE,
# endif
# ifdef USE_GLEXT
&ME_RENDERERSETUP_DETAILTEX,
&ME_RENDERERSETUP_GLOWTEX,
@ -1075,28 +1051,6 @@ static MenuEntry_t *MEL_RENDERERSETUP_POLYMOST[] = {
&ME_RENDERERSETUP_PALETTEEMULATION,
};
#ifdef POLYMER
static MenuEntry_t *MEL_RENDERERSETUP_POLYMER [] = {
&ME_RENDERERSETUP_HIGHTILE,
&ME_RENDERERSETUP_TEXQUALITY,
&ME_RENDERERSETUP_PRECACHE,
# ifndef EDUKE32_GLES
&ME_RENDERERSETUP_TEXCACHE,
# endif
# ifdef USE_GLEXT
&ME_RENDERERSETUP_DETAILTEX,
&ME_RENDERERSETUP_GLOWTEX,
&ME_POLYMER_PALETTEEMULATION,
# endif
&ME_Space4_Bluefont,
&ME_RENDERERSETUP_MODELS,
&ME_Space4_Bluefont,
&ME_POLYMER_LIGHTS,
&ME_POLYMER_LIGHTPASSES,
&ME_POLYMER_SHADOWS,
&ME_POLYMER_SHADOWCOUNT,
};
#endif
#endif
#ifdef EDUKE32_ANDROID_MENU
@ -1974,9 +1928,6 @@ static void Menu_Pre(MenuID_t cm)
case MENU_POLYMOST:
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_TEXQUALITY, !usehightile);
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_PRECACHE, !usehightile);
# ifndef EDUKE32_GLES
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_TEXCACHE, !(glusetexcompr && usehightile));
# endif
# ifdef USE_GLEXT
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_DETAILTEX, !usehightile);
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_GLOWTEX, !usehightile);
@ -3290,16 +3241,9 @@ static void Menu_EntryOptionDidModify(MenuEntry_t *entry)
#endif
else if (entry == &ME_RENDERERSETUP_TEXQUALITY)
{
texcache_invalidate();
r_downsizevar = r_downsize;
domodechange = 1;
}
#ifdef POLYMER
else if (entry == &ME_POLYMER_LIGHTS ||
entry == &ME_POLYMER_LIGHTPASSES ||
entry == &ME_POLYMER_SHADOWCOUNT)
domodechange = 1;
#endif
if (domodechange)
{

View file

@ -44,7 +44,6 @@ TexFilter_s TexFilter[]={
FSamplerManager::FSamplerManager()
{
glGenSamplers(NumSamplers, mSamplers);
SetTextureFilterMode(0);
glSamplerParameteri(mSamplers[5], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(mSamplers[5], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameterf(mSamplers[5], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);