Subversion Repositories eduke32

Rev

Rev 884 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 884 Rev 885
1
/**************************************************************************************************
1
/**************************************************************************************************
2
"POLYMOST" code written by Ken Silverman
2
"POLYMOST" code written by Ken Silverman
3
Ken Silverman's official web site: http://www.advsys.net/ken
3
Ken Silverman's official web site: http://www.advsys.net/ken
4

4

5
Motivation:
5
Motivation:
6
When 3D Realms released the Duke Nukem 3D source code, I thought somebody would do a OpenGL or
6
When 3D Realms released the Duke Nukem 3D source code, I thought somebody would do a OpenGL or
7
Direct3D port. Well, after a few months passed, I saw no sign of somebody working on a true
7
Direct3D port. Well, after a few months passed, I saw no sign of somebody working on a true
8
hardware-accelerated port of Build, just people saying it wasn't possible. Eventually, I realized
8
hardware-accelerated port of Build, just people saying it wasn't possible. Eventually, I realized
9
the only way this was going to happen was for me to do it myself. First, I needed to port Build to
9
the only way this was going to happen was for me to do it myself. First, I needed to port Build to
10
Windows. I could have done it myself, but instead I thought I'd ask my Australian buddy, Jonathon
10
Windows. I could have done it myself, but instead I thought I'd ask my Australian buddy, Jonathon
11
Fowler, if he would upgrade his Windows port to my favorite compiler (MSVC) - which he did. Once
11
Fowler, if he would upgrade his Windows port to my favorite compiler (MSVC) - which he did. Once
12
that was done, I was ready to start the "POLYMOST" project.
12
that was done, I was ready to start the "POLYMOST" project.
13

13

14
About:
14
About:
15
This source file is basically a complete rewrite of the entire rendering part of the Build engine.
15
This source file is basically a complete rewrite of the entire rendering part of the Build engine.
16
There are small pieces in ENGINE.C to activate this code, and other minor hacks in other source
16
There are small pieces in ENGINE.C to activate this code, and other minor hacks in other source
17
files, but most of it is in here. If you're looking for polymost-related code in the other source
17
files, but most of it is in here. If you're looking for polymost-related code in the other source
18
files, you should find most of them by searching for either "polymost" or "rendmode". Speaking of
18
files, you should find most of them by searching for either "polymost" or "rendmode". Speaking of
19
rendmode, there are now 4 rendering modes in Build:
19
rendmode, there are now 4 rendering modes in Build:
20

20

21
        rendmode 0: The original code I wrote from 1993-1997
21
        rendmode 0: The original code I wrote from 1993-1997
22
        rendmode 1: Solid-color rendering: my debug code before I did texture mapping
22
        rendmode 1: Solid-color rendering: my debug code before I did texture mapping
23
        rendmode 2: Software rendering before I started the OpenGL code (Note: this is just a quick
23
        rendmode 2: Software rendering before I started the OpenGL code (Note: this is just a quick
24
                                                hack to make testing easier - it's not optimized to my usual standards!)
24
                                                hack to make testing easier - it's not optimized to my usual standards!)
25
        rendmode 3: The OpenGL code
25
        rendmode 3: The OpenGL code
26

26

27
The original Build engine did hidden surface removal by using a vertical span buffer on the tops
27
The original Build engine did hidden surface removal by using a vertical span buffer on the tops
28
and bottoms of walls. This worked nice back in the day, but it it's not suitable for a polygon
28
and bottoms of walls. This worked nice back in the day, but it it's not suitable for a polygon
29
engine. So I decided to write a brand new hidden surface removal algorithm - using the same idea
29
engine. So I decided to write a brand new hidden surface removal algorithm - using the same idea
30
as the original Build - but one that worked with vectors instead of already rasterized data.
30
as the original Build - but one that worked with vectors instead of already rasterized data.
31

31

32
Brief history:
32
Brief history:
33
06/20/2000: I release Build Source code
33
06/20/2000: I release Build Source code
34
04/01/2003: 3D Realms releases Duke Nukem 3D source code
34
04/01/2003: 3D Realms releases Duke Nukem 3D source code
35
10/04/2003: Jonathon Fowler gets his Windows port working in Visual C
35
10/04/2003: Jonathon Fowler gets his Windows port working in Visual C
36
10/04/2003: I start writing POLYMOST.BAS, a new hidden surface removal algorithm for Build that
36
10/04/2003: I start writing POLYMOST.BAS, a new hidden surface removal algorithm for Build that
37
                                        works on a polygon level instead of spans.
37
                                        works on a polygon level instead of spans.
38
10/16/2003: Ported POLYMOST.BAS to C inside JonoF KenBuild's ENGINE.C; later this code was split
38
10/16/2003: Ported POLYMOST.BAS to C inside JonoF KenBuild's ENGINE.C; later this code was split
39
                                        out of ENGINE.C and put in this file, POLYMOST.C.
39
                                        out of ENGINE.C and put in this file, POLYMOST.C.
40
12/10/2003: Started OpenGL code for POLYMOST (rendmode 3)
40
12/10/2003: Started OpenGL code for POLYMOST (rendmode 3)
41
12/23/2003: 1st public release
41
12/23/2003: 1st public release
42
01/01/2004: 2nd public release: fixed stray lines, status bar, mirrors, sky, and lots of other bugs.
42
01/01/2004: 2nd public release: fixed stray lines, status bar, mirrors, sky, and lots of other bugs.
43

43

44
----------------------------------------------------------------------------------------------------
44
----------------------------------------------------------------------------------------------------
45

45

46
Todo list (in approximate chronological order):
46
Todo list (in approximate chronological order):
47

47

48
High priority:
48
High priority:
49
        *   BOTH: Do accurate software sorting/chopping for sprites: drawing in wrong order is bad :/
49
        *   BOTH: Do accurate software sorting/chopping for sprites: drawing in wrong order is bad :/
50
        *   BOTH: Fix hall of mirrors near "zenith". Call polymost_drawrooms twice?
50
        *   BOTH: Fix hall of mirrors near "zenith". Call polymost_drawrooms twice?
51
        * OPENGL: drawmapview()
51
        * OPENGL: drawmapview()
52

52

53
Low priority:
53
Low priority:
54
        * SOFT6D: Do back-face culling of sprites during up/down/tilt transformation (top of drawpoly)
54
        * SOFT6D: Do back-face culling of sprites during up/down/tilt transformation (top of drawpoly)
55
        * SOFT6D: Fix depth shading: use saturation&LUT
55
        * SOFT6D: Fix depth shading: use saturation&LUT
56
        * SOFT6D: Optimize using hyperbolic mapping (similar to KUBE algo)
56
        * SOFT6D: Optimize using hyperbolic mapping (similar to KUBE algo)
57
        * SOFT6D: Slab6-style voxel sprites. How to accelerate? :/
57
        * SOFT6D: Slab6-style voxel sprites. How to accelerate? :/
58
        * OPENGL: KENBUILD: Write flipping code for floor mirrors
58
        * OPENGL: KENBUILD: Write flipping code for floor mirrors
59
        *   BOTH: KENBUILD: Parallaxing sky modes 1&2
59
        *   BOTH: KENBUILD: Parallaxing sky modes 1&2
60
        *   BOTH: Masked/1-way walls don't clip correctly to sectors of intersecting ceiling/floor slopes
60
        *   BOTH: Masked/1-way walls don't clip correctly to sectors of intersecting ceiling/floor slopes
61
        *   BOTH: Editart x-center is not working correctly with Duke's camera/turret sprites
61
        *   BOTH: Editart x-center is not working correctly with Duke's camera/turret sprites
62
        *   BOTH: Get rid of horizontal line above Duke full-screen status bar
62
        *   BOTH: Get rid of horizontal line above Duke full-screen status bar
63
        *   BOTH: Combine ceilings/floors into a single triangle strip (should lower poly count by 2x)
63
        *   BOTH: Combine ceilings/floors into a single triangle strip (should lower poly count by 2x)
64
        *   BOTH: Optimize/clean up texture-map setup equations
64
        *   BOTH: Optimize/clean up texture-map setup equations
65

65

66
**************************************************************************************************/
66
**************************************************************************************************/
67
67
68
int animateoffs(short tilenum, short fakevar);
68
int animateoffs(short tilenum, short fakevar);
69
int rendmode=0;
69
int rendmode=0;
70
int usemodels=1, usehightile=1;
70
int usemodels=1, usehightile=1;
71
71
72
#include <math.h> //<-important!
72
#include <math.h> //<-important!
73
typedef struct { float x, cy[2], fy[2]; int n, p, tag, ctag, ftag; } vsptyp;
73
typedef struct { float x, cy[2], fy[2]; int n, p, tag, ctag, ftag; } vsptyp;
74
#define VSPMAX 4096 //<- careful!
74
#define VSPMAX 4096 //<- careful!
75
static vsptyp vsp[VSPMAX];
75
static vsptyp vsp[VSPMAX];
76
static int vcnt, gtag;
76
static int vcnt, gtag;
77
77
78
static double dxb1[MAXWALLSB], dxb2[MAXWALLSB];
78
static double dxb1[MAXWALLSB], dxb2[MAXWALLSB];
79
79
80
#define SCISDIST 1.0 //1.0: Close plane clipping distance
80
#define SCISDIST 1.0 //1.0: Close plane clipping distance
81
#define USEZBUFFER 1 //1:use zbuffer (slow, nice sprite rendering), 0:no zbuffer (fast, bad sprite rendering)
81
#define USEZBUFFER 1 //1:use zbuffer (slow, nice sprite rendering), 0:no zbuffer (fast, bad sprite rendering)
82
#define LINTERPSIZ 4 //log2 of interpolation size. 4:pretty fast&acceptable quality, 0:best quality/slow!
82
#define LINTERPSIZ 4 //log2 of interpolation size. 4:pretty fast&acceptable quality, 0:best quality/slow!
83
#define DEPTHDEBUG 0 //1:render distance instead of texture, for debugging only!, 0:default
83
#define DEPTHDEBUG 0 //1:render distance instead of texture, for debugging only!, 0:default
84
#define FOGSCALE 0.0000640
84
#define FOGSCALE 0.0000640
85
#define PI 3.14159265358979323
85
#define PI 3.14159265358979323
86
86
87
float shadescale = 1.050;
87
float shadescale = 1.050;
88
88
89
static double gyxscale, gxyaspect, gviewxrange, ghalfx, grhalfxdown10, grhalfxdown10x, ghoriz;
89
static double gyxscale, gxyaspect, gviewxrange, ghalfx, grhalfxdown10, grhalfxdown10x, ghoriz;
90
static double gcosang, gsinang, gcosang2, gsinang2;
90
static double gcosang, gsinang, gcosang2, gsinang2;
91
static double gchang, gshang, gctang, gstang, gvisibility;
91
static double gchang, gshang, gctang, gstang, gvisibility;
92
float gtang = 0.0;
92
float gtang = 0.0;
93
double guo, gux, guy; //Screen-based texture mapping parameters
93
double guo, gux, guy; //Screen-based texture mapping parameters
94
double gvo, gvx, gvy;
94
double gvo, gvx, gvy;
95
double gdo, gdx, gdy;
95
double gdo, gdx, gdy;
96
96
97
#if (USEZBUFFER != 0)
97
#if (USEZBUFFER != 0)
98
int  zbufysiz = 0, zbufbpl = 0, *zbufoff = 0;
98
int  zbufysiz = 0, zbufbpl = 0, *zbufoff = 0;
99
intptr_t zbufmem = 0;
99
intptr_t zbufmem = 0;
100
#endif
100
#endif
101
101
102
#ifdef USE_OPENGL
102
#ifdef USE_OPENGL
103
static int srepeat = 0, trepeat = 0;
103
static int srepeat = 0, trepeat = 0;
104
104
105
int glredbluemode = 0;
105
int glredbluemode = 0;
106
static int lastglredbluemode = 0, redblueclearcnt = 0;
106
static int lastglredbluemode = 0, redblueclearcnt = 0;
107
107
108
static struct glfiltermodes
108
static struct glfiltermodes
109
{
109
{
110
    char *name;
110
    char *name;
111
    int min,mag;
111
    int min,mag;
112
} glfiltermodes[] =
112
} glfiltermodes[] =
113
{
113
{
114
    {"GL_NEAREST",GL_NEAREST,GL_NEAREST},
114
    {"GL_NEAREST",GL_NEAREST,GL_NEAREST},
115
    {"GL_LINEAR",GL_LINEAR,GL_LINEAR},
115
    {"GL_LINEAR",GL_LINEAR,GL_LINEAR},
116
    {"GL_NEAREST_MIPMAP_NEAREST",GL_NEAREST_MIPMAP_NEAREST,GL_NEAREST},
116
    {"GL_NEAREST_MIPMAP_NEAREST",GL_NEAREST_MIPMAP_NEAREST,GL_NEAREST},
117
    {"GL_LINEAR_MIPMAP_NEAREST",GL_LINEAR_MIPMAP_NEAREST,GL_LINEAR},
117
    {"GL_LINEAR_MIPMAP_NEAREST",GL_LINEAR_MIPMAP_NEAREST,GL_LINEAR},
118
    {"GL_NEAREST_MIPMAP_LINEAR",GL_NEAREST_MIPMAP_LINEAR,GL_NEAREST},
118
    {"GL_NEAREST_MIPMAP_LINEAR",GL_NEAREST_MIPMAP_LINEAR,GL_NEAREST},
119
    {"GL_LINEAR_MIPMAP_LINEAR",GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR}
119
    {"GL_LINEAR_MIPMAP_LINEAR",GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR}
120
};
120
};
121
#define numglfiltermodes (sizeof(glfiltermodes)/sizeof(glfiltermodes[0]))
121
#define numglfiltermodes (sizeof(glfiltermodes)/sizeof(glfiltermodes[0]))
122
122
123
int glanisotropy = 1;            // 0 = maximum supported by card
123
int glanisotropy = 1;            // 0 = maximum supported by card
124
int glusetexcompr = 1;
124
int glusetexcompr = 1;
125
int gltexfiltermode = 2; // GL_NEAREST_MIPMAP_NEAREST
125
int gltexfiltermode = 2; // GL_NEAREST_MIPMAP_NEAREST
126
int glusetexcache = 0;
126
int glusetexcache = 0;
127
int glusetexcachecompression = 1;
127
int glusetexcachecompression = 1;
128
int glmultisample = 0, glnvmultisamplehint = 0;
128
int glmultisample = 0, glnvmultisamplehint = 0;
129
int gltexmaxsize = 0;      // 0 means autodetection on first run
129
int gltexmaxsize = 0;      // 0 means autodetection on first run
130
int gltexmiplevel = 0;          // discards this many mipmap levels
130
int gltexmiplevel = 0;          // discards this many mipmap levels
131
static int lastglpolygonmode = 0; //FUK
131
static int lastglpolygonmode = 0; //FUK
132
int glpolygonmode = 0;     // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK
132
int glpolygonmode = 0;     // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK
133
int glwidescreen = 0;
133
int glwidescreen = 0;
134
int glprojectionhacks = 1;
134
int glprojectionhacks = 1;
135
static GLuint polymosttext = 0;
135
static GLuint polymosttext = 0;
136
extern char nofog;
136
extern char nofog;
137
137
138
// Those THREE globals control the drawing of fullbright tiles
138
// Those THREE globals control the drawing of fullbright tiles
139
static int fullbrightloadingpass = 0;
139
static int fullbrightloadingpass = 0;
140
static int fullbrightdrawingpass = 0;
140
static int fullbrightdrawingpass = 0;
141
static int shadeforfullbrightpass;
141
static int shadeforfullbrightpass;
142
142
143
// Depth peeling control
143
// Depth peeling control
144
int r_depthpeeling = 0;    // cvar toggling general depth peeling usage
144
int r_depthpeeling = 0;    // cvar toggling general depth peeling usage
145
int r_peelscount = 5;      // cvar controlling the number of peeling layers
145
int r_peelscount = 5;      // cvar controlling the number of peeling layers
146
int r_curpeel = -1;        // cvar controlling the display of independant peeling layers
146
int r_curpeel = -1;        // cvar controlling the display of independant peeling layers
147
static float curpolygonoffset;     // internal polygon offset stack for drawing flat sprites to avoid depth fighting
147
static float curpolygonoffset;     // internal polygon offset stack for drawing flat sprites to avoid depth fighting
148
static int peelcompiling = 0;     // internal control var to disable blending when compiling the peeling display list
148
static int peelcompiling = 0;     // internal control var to disable blending when compiling the peeling display list
149
static int newpeelscount = 0;     // temporary var for peels count changing during the game
149
static int newpeelscount = 0;     // temporary var for peels count changing during the game
150
150
151
// Depth peeling data
151
// Depth peeling data
152
static GLuint ztexture[3];         // secondary Z-buffers identifier
152
static GLuint ztexture[3];         // secondary Z-buffers identifier
153
static GLuint *peels;              // peels identifiers
153
static GLuint *peels;              // peels identifiers
154
static GLuint *peelfbos;           // peels FBOs identifiers
154
static GLuint *peelfbos;           // peels FBOs identifiers
155
static GLuint peelprogram[2];      // ARBfp peeling fragment program
155
static GLuint peelprogram[2];      // ARBfp peeling fragment program
156
156
157
// Detail mapping cvar
157
// Detail mapping cvar
158
int r_detailmapping = 1;
158
int r_detailmapping = 1;
159
159
160
// Glow mapping cvar
160
// Glow mapping cvar
161
int r_glowmapping = 1;
161
int r_glowmapping = 1;
162
162
163
// Vertex Array model drawing cvar
163
// Vertex Array model drawing cvar
164
int r_vertexarrays = 1;
164
int r_vertexarrays = 1;
165
165
166
// Vertex Buffer Objects model drawing cvars
166
// Vertex Buffer Objects model drawing cvars
167
int r_vbos = 0;
167
int r_vbos = 0;
168
int r_vbocount = 64;
168
int r_vbocount = 64;
169
169
170
// model animation smoothing cvar
170
// model animation smoothing cvar
171
int r_animsmoothing = 1;
171
int r_animsmoothing = 1;
172
172
173
// polymost ART sky control
173
// polymost ART sky control
174
int r_parallaxskyclamping = 1;
174
int r_parallaxskyclamping = 1;
175
int r_parallaxskypanning = 0;
175
int r_parallaxskypanning = 0;
176
176
177
// line of sight checks before mddraw()
177
// line of sight checks before mddraw()
178
int r_cullobstructedmodels = 0;
178
int r_cullobstructedmodels = 0;
179
#define CULL_DELAY 5
179
#define CULL_DELAY 5
180
180
181
// fullbright cvar
181
// fullbright cvar
182
int r_fullbright = 1;
182
int r_fullbright = 1;
183
183
184
static float fogresult, fogcol[4];
184
static float fogresult, fogcol[4];
185
185
186
// making this a macro should speed things up at the expense of code size
186
// making this a macro should speed things up at the expense of code size
187
#define fogcalc(shade, vis, pal) \
187
#define fogcalc(shade, vis, pal) \
188
{ \
188
{ \
189
    fogresult = (float)gvisibility*(vis+16+(shade<0?(-shade*shade)*0.125f:(shade*shade)*0.125f)); \
189
    fogresult = (float)gvisibility*(vis+16+(shade<0?(-shade*shade)*0.125f:(shade*shade)*0.125f)); \
190
    if (vis > 239) fogresult = (float)gvisibility*((vis-240+(shade<0?(-shade*shade)*0.125f:(shade*shade)*0.125f))/(klabs(vis-256))); \
190
    if (vis > 239) fogresult = (float)gvisibility*((vis-240+(shade<0?(-shade*shade)*0.125f:(shade*shade)*0.125f))/(klabs(vis-256))); \
191
    fogresult = min(max(fogresult, 0.01f),10.f); \
191
    fogresult = min(max(fogresult, 0.01f),10.f); \
192
    fogcol[0] = (float)palookupfog[pal].r / 63.f; \
192
    fogcol[0] = (float)palookupfog[pal].r / 63.f; \
193
    fogcol[1] = (float)palookupfog[pal].g / 63.f; \
193
    fogcol[1] = (float)palookupfog[pal].g / 63.f; \
194
    fogcol[2] = (float)palookupfog[pal].b / 63.f; \
194
    fogcol[2] = (float)palookupfog[pal].b / 63.f; \
195
    fogcol[3] = 0; \
195
    fogcol[3] = 0; \
196
}
196
}
197
#endif
197
#endif
198
198
199
#if defined(USE_MSC_PRAGMAS)
199
#if defined(USE_MSC_PRAGMAS)
200
static inline void ftol(float f, int *a)
200
static inline void ftol(float f, int *a)
201
{
201
{
202
    _asm
202
    _asm
203
    {
203
    {
204
        mov eax, a
204
        mov eax, a
205
        fld f
205
        fld f
206
        fistp dword ptr [eax]
206
        fistp dword ptr [eax]
207
    }
207
    }
208
}
208
}
209
209
210
static inline void dtol(double d, int *a)
210
static inline void dtol(double d, int *a)
211
{
211
{
212
    _asm
212
    _asm
213
    {
213
    {
214
        mov eax, a
214
        mov eax, a
215
        fld d
215
        fld d
216
        fistp dword ptr [eax]
216
        fistp dword ptr [eax]
217
    }
217
    }
218
}
218
}
219
#elif defined(USE_WATCOM_PRAGMAS)
219
#elif defined(USE_WATCOM_PRAGMAS)
220
220
221
#pragma aux ftol =\
221
#pragma aux ftol =\
222
        "fistp dword ptr [eax]",\
222
        "fistp dword ptr [eax]",\
223
        parm [eax 8087]
223
        parm [eax 8087]
224
#pragma aux dtol =\
224
#pragma aux dtol =\
225
        "fistp dword ptr [eax]",\
225
        "fistp dword ptr [eax]",\
226
        parm [eax 8087]
226
        parm [eax 8087]
227
227
228
#elif defined(USE_GCC_PRAGMAS)
228
#elif defined(USE_GCC_PRAGMAS)
229
229
230
static inline void ftol(float f, int *a)
230
static inline void ftol(float f, int *a)
231
{
231
{
232
    __asm__ __volatile__(
232
    __asm__ __volatile__(
233
#if 0 //(__GNUC__ >= 3)
233
#if 0 //(__GNUC__ >= 3)
234
        "flds %1; fistpl %0;"
234
        "flds %1; fistpl %0;"
235
#else
235
#else
236
        "flds %1; fistpl (%0);"
236
        "flds %1; fistpl (%0);"
237
#endif
237
#endif
238
    : "=r"(a) : "m"(f) : "memory","cc");
238
    : "=r"(a) : "m"(f) : "memory","cc");
239
}
239
}
240
240
241
static inline void dtol(double d, int *a)
241
static inline void dtol(double d, int *a)
242
{
242
{
243
    __asm__ __volatile__(
243
    __asm__ __volatile__(
244
#if 0 //(__GNUC__ >= 3)
244
#if 0 //(__GNUC__ >= 3)
245
        "fldl %1; fistpl %0;"
245
        "fldl %1; fistpl %0;"
246
#else
246
#else
247
        "fldl %1; fistpl (%0);"
247
        "fldl %1; fistpl (%0);"
248
#endif
248
#endif
249
    : "=r"(a) : "m"(d) : "memory","cc");
249
    : "=r"(a) : "m"(d) : "memory","cc");
250
}
250
}
251
251
252
#else
252
#else
253
static inline void ftol(float f, int *a)
253
static inline void ftol(float f, int *a)
254
{
254
{
255
    *a = (int)f;
255
    *a = (int)f;
256
}
256
}
257
257
258
static inline void dtol(double d, int *a)
258
static inline void dtol(double d, int *a)
259
{
259
{
260
    *a = (int)d;
260
    *a = (int)d;
261
}
261
}
262
#endif
262
#endif
263
263
264
static inline int imod(int a, int b)
264
static inline int imod(int a, int b)
265
{
265
{
266
    if (a >= 0) return(a%b);
266
    if (a >= 0) return(a%b);
267
    return(((a+1)%b)+b-1);
267
    return(((a+1)%b)+b-1);
268
}
268
}
269
269
270
void drawline2d(float x0, float y0, float x1, float y1, char col)
270
void drawline2d(float x0, float y0, float x1, float y1, char col)
271
{
271
{
272
    float f, dx, dy, fxres, fyres;
272
    float f, dx, dy, fxres, fyres;
273
    int e, inc, x, y;
273
    int e, inc, x, y;
274
    unsigned int up16;
274
    unsigned int up16;
275
275
276
    dx = x1-x0; dy = y1-y0; if ((dx == 0) && (dy == 0)) return;
276
    dx = x1-x0; dy = y1-y0; if ((dx == 0) && (dy == 0)) return;
277
    fxres = (float)xdimen; fyres = (float)ydimen;
277
    fxres = (float)xdimen; fyres = (float)ydimen;
278
    if (x0 >= fxres) { if (x1 >= fxres) return; y0 += (fxres-x0)*dy/dx; x0 = fxres; }
278
    if (x0 >= fxres) { if (x1 >= fxres) return; y0 += (fxres-x0)*dy/dx; x0 = fxres; }
279
    else if (x0 <      0) { if (x1 <      0) return; y0 += (0-x0)*dy/dx; x0 =     0; }
279
    else if (x0 <      0) { if (x1 <      0) return; y0 += (0-x0)*dy/dx; x0 =     0; }
280
    if (x1 >= fxres) {                          y1 += (fxres-x1)*dy/dx; x1 = fxres; }
280
    if (x1 >= fxres) {                          y1 += (fxres-x1)*dy/dx; x1 = fxres; }
281
    else if (x1 <      0) {                          y1 += (0-x1)*dy/dx; x1 =     0; }
281
    else if (x1 <      0) {                          y1 += (0-x1)*dy/dx; x1 =     0; }
282
    if (y0 >= fyres) { if (y1 >= fyres) return; x0 += (fyres-y0)*dx/dy; y0 = fyres; }
282
    if (y0 >= fyres) { if (y1 >= fyres) return; x0 += (fyres-y0)*dx/dy; y0 = fyres; }
283
    else if (y0 <      0) { if (y1 <      0) return; x0 += (0-y0)*dx/dy; y0 =     0; }
283
    else if (y0 <      0) { if (y1 <      0) return; x0 += (0-y0)*dx/dy; y0 =     0; }
284
    if (y1 >= fyres) {                          x1 += (fyres-y1)*dx/dy; y1 = fyres; }
284
    if (y1 >= fyres) {                          x1 += (fyres-y1)*dx/dy; y1 = fyres; }
285
    else if (y1 <      0) {                          x1 += (0-y1)*dx/dy; y1 =     0; }
285
    else if (y1 <      0) {                          x1 += (0-y1)*dx/dy; y1 =     0; }
286
286
287
    if (fabs(dx) > fabs(dy))
287
    if (fabs(dx) > fabs(dy))
288
    {
288
    {
289
        if (x0 > x1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; }
289
        if (x0 > x1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; }
290
        y = (int)(y0*65536.f)+32768;
290
        y = (int)(y0*65536.f)+32768;
291
        inc = (int)(dy/dx*65536.f+.5f);
291
        inc = (int)(dy/dx*65536.f+.5f);
292
        x = (int)(x0+.5); if (x < 0) { y -= inc*x; x = 0; } //if for safety
292
        x = (int)(x0+.5); if (x < 0) { y -= inc*x; x = 0; } //if for safety
293
        e = (int)(x1+.5); if (e > xdimen) e = xdimen;       //if for safety
293
        e = (int)(x1+.5); if (e > xdimen) e = xdimen;       //if for safety
294
        up16 = (ydimen<<16);
294
        up16 = (ydimen<<16);
295
        for (;x<e;x++,y+=inc) if ((unsigned int)y < up16) *(char *)(ylookup[y>>16]+x+frameoffset) = col;
295
        for (;x<e;x++,y+=inc) if ((unsigned int)y < up16) *(char *)(ylookup[y>>16]+x+frameoffset) = col;
296
    }
296
    }
297
    else
297
    else
298
    {
298
    {
299
        if (y0 > y1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; }
299
        if (y0 > y1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; }
300
        x = (int)(x0*65536.f)+32768;
300
        x = (int)(x0*65536.f)+32768;
301
        inc = (int)(dx/dy*65536.f+.5f);
301
        inc = (int)(dx/dy*65536.f+.5f);
302
        y = (int)(y0+.5); if (y < 0) { x -= inc*y; y = 0; } //if for safety
302
        y = (int)(y0+.5); if (y < 0) { x -= inc*y; y = 0; } //if for safety
303
        e = (int)(y1+.5); if (e > ydimen) e = ydimen;       //if for safety
303
        e = (int)(y1+.5); if (e > ydimen) e = ydimen;       //if for safety
304
        up16 = (xdimen<<16);
304
        up16 = (xdimen<<16);
305
        for (;y<e;y++,x+=inc) if ((unsigned int)x < up16) *(char *)(ylookup[y]+(x>>16)+frameoffset) = col;
305
        for (;y<e;y++,x+=inc) if ((unsigned int)x < up16) *(char *)(ylookup[y]+(x>>16)+frameoffset) = col;
306
    }
306
    }
307
}
307
}
308
308
309
#ifdef USE_OPENGL
309
#ifdef USE_OPENGL
310
typedef struct { unsigned char r, g, b, a; } coltype;
310
typedef struct { unsigned char r, g, b, a; } coltype;
311
311
312
static void uploadtexture(int doalloc, int xsiz, int ysiz, int intexfmt, int texfmt, coltype *pic, int tsizx, int tsizy, int dameth);
312
static void uploadtexture(int doalloc, int xsiz, int ysiz, int intexfmt, int texfmt, coltype *pic, int tsizx, int tsizy, int dameth);
313
313
314
#include "md4.h"
314
#include "md4.h"
315
315
316
#define USELZF
316
#define USELZF
317
#define USEKENFILTER 1
317
#define USEKENFILTER 1
318
318
319
#ifdef USELZF
319
#ifdef USELZF
320
#       include "lzf.h"
320
#       include "lzf.h"
321
#else
321
#else
322
#       include "lzwnew.h"
322
#       include "lzwnew.h"
323
#endif
323
#endif
324
324
325
static char TEXCACHEDIR[] = "texcache";
325
static char TEXCACHEDIR[] = "texcache";
326
typedef struct
326
typedef struct
327
{
327
{
328
    char magic[8];      // 'Polymost'
328
    char magic[8];      // 'Polymost'
329
    int xdim, ydim;     // of image, unpadded
329
    int xdim, ydim;     // of image, unpadded
330
    int flags;          // 1 = !2^x, 2 = has alpha, 4 = lzw compressed
330
    int flags;          // 1 = !2^x, 2 = has alpha, 4 = lzw compressed
331
} texcacheheader;
331
} texcacheheader;
332
typedef struct
332
typedef struct
333
{
333
{
334
    int size;
334
    int size;
335
    int format;
335
    int format;
336
    int xdim, ydim;     // of mipmap (possibly padded)
336
    int xdim, ydim;     // of mipmap (possibly padded)
337
    int border, depth;
337
    int border, depth;
338
} texcachepicture;
338
} texcachepicture;
339
339
340
int dxtfilter(int fil, texcachepicture *pict, char *pic, void *midbuf, char *packbuf, unsigned int miplen);
340
int dxtfilter(int fil, texcachepicture *pict, char *pic, void *midbuf, char *packbuf, unsigned int miplen);
341
int dedxtfilter(int fil, texcachepicture *pict, char *pic, void *midbuf, char *packbuf, int ispacked);
341
int dedxtfilter(int fil, texcachepicture *pict, char *pic, void *midbuf, char *packbuf, int ispacked);
342
342
343
static inline void phex(unsigned char v, char *s);
343
static inline void phex(unsigned char v, char *s);
344
void writexcache(char *fn, int len, int dameth, char effect, texcacheheader *head);
344
void writexcache(char *fn, int len, int dameth, char effect, texcacheheader *head);
345
345
346
int mdtims, omdtims;
346
int mdtims, omdtims;
347
float alphahackarray[MAXTILES];
347
float alphahackarray[MAXTILES];
348
#include "mdsprite.c"
348
#include "mdsprite.c"
349
349
350
//--------------------------------------------------------------------------------------------------
350
//--------------------------------------------------------------------------------------------------
351
//TEXTURE MANAGEMENT: treats same texture with different .PAL as a separate texture. This makes the
351
//TEXTURE MANAGEMENT: treats same texture with different .PAL as a separate texture. This makes the
352
//   max number of virtual textures very large (MAXTILES*256). Instead of allocating a handle for
352
//   max number of virtual textures very large (MAXTILES*256). Instead of allocating a handle for
353
//   every virtual texture, I use a cache where indexing is managed through a hash table.
353
//   every virtual texture, I use a cache where indexing is managed through a hash table.
354
//
354
//
355
355
356
// moved into polymost.h
356
// moved into polymost.h
357
/*typedef struct pthtyp_t
357
/*typedef struct pthtyp_t
358
{
358
{
359
    struct pthtyp_t *next;
359
    struct pthtyp_t *next;
360
    GLuint glpic;
360
    GLuint glpic;
361
    short picnum;
361
    short picnum;
362
    char palnum;
362
    char palnum;
363
    char effects;
363
    char effects;
364
    char flags;      // 1 = clamped (dameth&4), 2 = hightile, 4 = skybox face, 8 = hasalpha, 16 = hasfullbright, 128 = invalidated
364
    char flags;      // 1 = clamped (dameth&4), 2 = hightile, 4 = skybox face, 8 = hasalpha, 16 = hasfullbright, 128 = invalidated
365
    char skyface;
365
    char skyface;
366
    hicreplctyp *hicr;
366
    hicreplctyp *hicr;
367

367

368
    unsigned short sizx, sizy;
368
    unsigned short sizx, sizy;
369
    float scalex, scaley;
369
    float scalex, scaley;
370
    struct pthtyp_t *wofb; // without fullbright
370
    struct pthtyp_t *wofb; // without fullbright
371
    struct pthtyp_t *ofb; // only fullbright
371
    struct pthtyp_t *ofb; // only fullbright
372
} pthtyp;*/
372
} pthtyp;*/
373
373
374
#define GLTEXCACHEADSIZ 8192
374
#define GLTEXCACHEADSIZ 8192
375
static pthtyp *gltexcachead[GLTEXCACHEADSIZ];
375
static pthtyp *gltexcachead[GLTEXCACHEADSIZ];
376
376
377
int drawingskybox = 0;
377
int drawingskybox = 0;
378
378
379
pthtyp *pichead;
379
pthtyp *pichead;
380
380
381
int gloadtile_art(int,int,int,pthtyp*,int);
381
int gloadtile_art(int,int,int,pthtyp*,int);
382
int gloadtile_hi(int,int,int,hicreplctyp*,int,pthtyp*,int,char);
382
int gloadtile_hi(int,int,int,hicreplctyp*,int,pthtyp*,int,char);
383
static int hicprecaching = 0;
383
static int hicprecaching = 0;
384
pthtyp * gltexcache(int dapicnum, int dapalnum, int dameth)
384
pthtyp * gltexcache(int dapicnum, int dapalnum, int dameth)
385
{
385
{
386
    int i, j;
386
    int i, j;
387
    hicreplctyp *si;
387
    hicreplctyp *si;
388
    pthtyp *pth, *pth2;
388
    pthtyp *pth, *pth2;
389
389
390
    j = (dapicnum&(GLTEXCACHEADSIZ-1));
390
    j = (dapicnum&(GLTEXCACHEADSIZ-1));
391
391
392
    if (usehightile) si = hicfindsubst(dapicnum,dapalnum,drawingskybox);
392
    if (usehightile) si = hicfindsubst(dapicnum,dapalnum,drawingskybox);
393
    else si = NULL;
393
    else si = NULL;
394
    if (!si)
394
    if (!si)
395
    {
395
    {
396
        if (drawingskybox) return NULL;
396
        if (drawingskybox) return NULL;
397
        goto tryart;
397
        goto tryart;
398
    }
398
    }
399
399
400
    /* if palette > 0 && replacement found
400
    /* if palette > 0 && replacement found
401
     *    no effects are applied to the texture
401
     *    no effects are applied to the texture
402
     * else if palette > 0 && no replacement found
402
     * else if palette > 0 && no replacement found
403
     *    effects are applied to the palette 0 texture if it exists
403
     *    effects are applied to the palette 0 texture if it exists
404
     */
404
     */
405
405
406
    pichead=gltexcachead[j]; // for palmaps
406
    pichead=gltexcachead[j]; // for palmaps
407
    // load a replacement
407
    // load a replacement
408
    for (pth=pichead; pth; pth=pth->next)
408
    for (pth=pichead; pth; pth=pth->next)
409
    {
409
    {
410
        if (pth->picnum == dapicnum &&
410
        if (pth->picnum == dapicnum &&
411
                pth->palnum == si->palnum &&
411
                pth->palnum == si->palnum &&
412
                (si->palnum>0 ? 1 : (pth->effects == hictinting[dapalnum].f)) &&
412
                (si->palnum>0 ? 1 : (pth->effects == hictinting[dapalnum].f)) &&
413
                (pth->flags & (1+2+4)) == (((dameth&4)>>2)+2+((drawingskybox>0)<<2)) &&
413
                (pth->flags & (1+2+4)) == (((dameth&4)>>2)+2+((drawingskybox>0)<<2)) &&
414
                (drawingskybox>0 ? (pth->skyface == drawingskybox) : 1)
414
                (drawingskybox>0 ? (pth->skyface == drawingskybox) : 1)
415
           )
415
           )
416
        {
416
        {
417
            if (pth->flags & 128)
417
            if (pth->flags & 128)
418
            {
418
            {
419
                pth->flags &= ~128;
419
                pth->flags &= ~128;
420
                if (gloadtile_hi(dapicnum,dapalnum,drawingskybox,si,dameth,pth,0,
420
                if (gloadtile_hi(dapicnum,dapalnum,drawingskybox,si,dameth,pth,0,
421
                                 (si->palnum>0) ? 0 : hictinting[dapalnum].f))    // reload tile
421
                                 (si->palnum>0) ? 0 : hictinting[dapalnum].f))    // reload tile
422
                {
422
                {
423
                    if (drawingskybox) return NULL;
423
                    if (drawingskybox) return NULL;
424
                    goto tryart;   // failed, so try for ART
424
                    goto tryart;   // failed, so try for ART
425
                }
425
                }
426
            }
426
            }
427
            return(pth);
427
            return(pth);
428
        }
428
        }
429
    }
429
    }
430
430
431
431
432
    pth = (pthtyp *)calloc(1,sizeof(pthtyp));
432
    pth = (pthtyp *)calloc(1,sizeof(pthtyp));
433
    if (!pth) return NULL;
433
    if (!pth) return NULL;
434
434
435
    // possibly fetch an already loaded multitexture :_)
435
    // possibly fetch an already loaded multitexture :_)
436
    if (dapalnum >= (MAXPALOOKUPS - RESERVEDPALS))
436
    if (dapalnum >= (MAXPALOOKUPS - RESERVEDPALS))
437
        for (i = (GLTEXCACHEADSIZ - 1); i >= 0; i--)
437
        for (i = (GLTEXCACHEADSIZ - 1); i >= 0; i--)
438
            for (pth2=gltexcachead[i]; pth2; pth2=pth2->next)
438
            for (pth2=gltexcachead[i]; pth2; pth2=pth2->next)
439
            {
439
            {
440
                if ((pth2->hicr) && (pth2->hicr->filename) && (Bstrcasecmp(pth2->hicr->filename, si->filename) == 0))
440
                if ((pth2->hicr) && (pth2->hicr->filename) && (Bstrcasecmp(pth2->hicr->filename, si->filename) == 0))
441
                {
441
                {
442
                    memcpy(pth, pth2, sizeof(pthtyp));
442
                    memcpy(pth, pth2, sizeof(pthtyp));
443
                    pth->picnum = dapicnum;
443
                    pth->picnum = dapicnum;
444
                    pth->flags = ((dameth&4)>>2) + 2 + ((drawingskybox>0)<<2);
444
                    pth->flags = ((dameth&4)>>2) + 2 + ((drawingskybox>0)<<2);
445
                    if (pth2->flags & 8) pth->flags |= 8; //hasalpha
445
                    if (pth2->flags & 8) pth->flags |= 8; //hasalpha
446
                    pth->hicr = si;
446
                    pth->hicr = si;
447
                    pth->next = gltexcachead[j];
447
                    pth->next = gltexcachead[j];
448
448
449
                    gltexcachead[j] = pth;
449
                    gltexcachead[j] = pth;
450
                    return(pth);
450
                    return(pth);
451
                }
451
                }
452
            }
452
            }
453
453
454
    if (gloadtile_hi(dapicnum,dapalnum,drawingskybox,si,dameth,pth,1, (si->palnum>0) ? 0 : hictinting[dapalnum].f))
454
    if (gloadtile_hi(dapicnum,dapalnum,drawingskybox,si,dameth,pth,1, (si->palnum>0) ? 0 : hictinting[dapalnum].f))
455
    {
455
    {
456
        free(pth);
456
        free(pth);
457
        if (drawingskybox) return NULL;
457
        if (drawingskybox) return NULL;
458
        goto tryart;   // failed, so try for ART
458
        goto tryart;   // failed, so try for ART
459
    }
459
    }
460
    pth->palnum = si->palnum;
460
    pth->palnum = si->palnum;
461
    pth->next = gltexcachead[j];
461
    pth->next = gltexcachead[j];
462
    gltexcachead[j] = pth;
462
    gltexcachead[j] = pth;
463
    return(pth);
463
    return(pth);
464
464
465
tryart:
465
tryart:
466
    if (hicprecaching) return NULL;
466
    if (hicprecaching) return NULL;
467
467
468
    // load from art
468
    // load from art
469
    for (pth=gltexcachead[j]; pth; pth=pth->next)
469
    for (pth=gltexcachead[j]; pth; pth=pth->next)
470
        if (pth->picnum == dapicnum &&
470
        if (pth->picnum == dapicnum &&
471
                pth->palnum == dapalnum &&
471
                pth->palnum == dapalnum &&
472
                (pth->flags & (1+2)) == ((dameth&4)>>2)
472
                (pth->flags & (1+2)) == ((dameth&4)>>2)
473
           )
473
           )
474
        {
474
        {
475
            if (pth->flags & 128)
475
            if (pth->flags & 128)
476
            {
476
            {
477
                pth->flags &= ~128;
477
                pth->flags &= ~128;
478
                if (gloadtile_art(dapicnum,dapalnum,dameth,pth,0)) return NULL; //reload tile (for animations)
478
                if (gloadtile_art(dapicnum,dapalnum,dameth,pth,0)) return NULL; //reload tile (for animations)
479
            }
479
            }
480
            return(pth);
480
            return(pth);
481
        }
481
        }
482
482
483
    pth = (pthtyp *)calloc(1,sizeof(pthtyp));
483
    pth = (pthtyp *)calloc(1,sizeof(pthtyp));
484
    if (!pth) return NULL;
484
    if (!pth) return NULL;
485
485
486
    if (gloadtile_art(dapicnum,dapalnum,dameth,pth,1))
486
    if (gloadtile_art(dapicnum,dapalnum,dameth,pth,1))
487
    {
487
    {
488
        free(pth);
488
        free(pth);
489
        return NULL;
489
        return NULL;
490
    }
490
    }
491
    pth->next = gltexcachead[j];
491
    pth->next = gltexcachead[j];
492
    gltexcachead[j] = pth;
492
    gltexcachead[j] = pth;
493
493
494
    return(pth);
494
    return(pth);
495
}
495
}
496
496
497
int gltexmayhavealpha(int dapicnum, int dapalnum)
497
int gltexmayhavealpha(int dapicnum, int dapalnum)
498
{
498
{
499
    int j = (dapicnum&(GLTEXCACHEADSIZ-1));
499
    int j = (dapicnum&(GLTEXCACHEADSIZ-1));
500
    pthtyp *pth;
500
    pthtyp *pth;
501
501
502
    for (pth=gltexcachead[j]; pth; pth=pth->next)
502
    for (pth=gltexcachead[j]; pth; pth=pth->next)
503
        if ((pth->picnum == dapicnum) && (pth->palnum == dapalnum))
503
        if ((pth->picnum == dapicnum) && (pth->palnum == dapalnum))
504
            return((pth->flags&8) != 0);
504
            return((pth->flags&8) != 0);
505
    return(1);
505
    return(1);
506
}
506
}
507
507
508
void gltexinvalidate(int dapicnum, int dapalnum, int dameth)
508
void gltexinvalidate(int dapicnum, int dapalnum, int dameth)
509
{
509
{
510
    int j;
510
    int j;
511
    pthtyp *pth;
511
    pthtyp *pth;
512
512
513
    j = (dapicnum&(GLTEXCACHEADSIZ-1));
513
    j = (dapicnum&(GLTEXCACHEADSIZ-1));
514
    for (pth=gltexcachead[j]; pth; pth=pth->next)
514
    for (pth=gltexcachead[j]; pth; pth=pth->next)
515
        if (pth->picnum == dapicnum && pth->palnum == dapalnum && (pth->flags & 1) == ((dameth&4)>>2))
515
        if (pth->picnum == dapicnum && pth->palnum == dapalnum && (pth->flags & 1) == ((dameth&4)>>2))
516
        {
516
        {
517
            pth->flags |= 128;
517
            pth->flags |= 128;
518
            if (pth->flags & 16)
518
            if (pth->flags & 16)
519
                pth->ofb->flags |= 128;
519
                pth->ofb->flags |= 128;
520
        }
520
        }
521
}
521
}
522
522
523
//Make all textures "dirty" so they reload, but not re-allocate
523
//Make all textures "dirty" so they reload, but not re-allocate
524
//This should be much faster than polymost_glreset()
524
//This should be much faster than polymost_glreset()
525
//Use this for palette effects ... but not ones that change every frame!
525
//Use this for palette effects ... but not ones that change every frame!
526
void gltexinvalidateall()
526
void gltexinvalidateall()
527
{
527
{
528
    int j;
528
    int j;
529
    pthtyp *pth;
529
    pthtyp *pth;
530
530
531
    for (j=GLTEXCACHEADSIZ-1;j>=0;j--)
531
    for (j=GLTEXCACHEADSIZ-1;j>=0;j--)
532
        for (pth=gltexcachead[j];pth;pth=pth->next)
532
        for (pth=gltexcachead[j];pth;pth=pth->next)
533
        {
533
        {
534
            pth->flags |= 128;
534
            pth->flags |= 128;
535
            if (pth->flags & 16)
535
            if (pth->flags & 16)
536
                pth->ofb->flags |= 128;
536
                pth->ofb->flags |= 128;
537
        }
537
        }
538
    clearskins();
538
    clearskins();
539
#ifdef DEBUGGINGAIDS
539
#ifdef DEBUGGINGAIDS
540
    OSD_Printf("gltexinvalidateall()\n");
540
    OSD_Printf("gltexinvalidateall()\n");
541
#endif
541
#endif
542
}
542
}
543
543
544
void gltexinvalidate8()
544
void gltexinvalidate8()
545
{
545
{
546
    int j;
546
    int j;
547
    pthtyp *pth;
547
    pthtyp *pth;
548
548
549
    for (j=GLTEXCACHEADSIZ-1;j>=0;j--)
549
    for (j=GLTEXCACHEADSIZ-1;j>=0;j--)
550
        for (pth=gltexcachead[j];pth;pth=pth->next)
550
        for (pth=gltexcachead[j];pth;pth=pth->next)
551
        {
551
        {
552
            if (pth->hicr == NULL)
552
            if (pth->hicr == NULL)
553
            {
553
            {
554
                pth->flags |= 128;
554
                pth->flags |= 128;
555
                if (pth->flags & 16)
555
                if (pth->flags & 16)
556
                    pth->ofb->flags |= 128;
556
                    pth->ofb->flags |= 128;
557
            }
557
            }
558
        }
558
        }
559
#ifdef DEBUGGINGAIDS
559
#ifdef DEBUGGINGAIDS
560
    OSD_Printf("gltexinvalidate8()\n");
560
    OSD_Printf("gltexinvalidate8()\n");
561
#endif
561
#endif
562
}
562
}
563
563
564
void gltexapplyprops(void)
564
void gltexapplyprops(void)
565
{
565
{
566
    int i;
566
    int i;
567
    pthtyp *pth;
567
    pthtyp *pth;
568
568
569
    if (glinfo.maxanisotropy > 1.0)
569
    if (glinfo.maxanisotropy > 1.0)
570
    {
570
    {
571
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy;
571
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy;
572
    }
572
    }
573
573
574
    if (gltexfiltermode < 0) gltexfiltermode = 0;
574
    if (gltexfiltermode < 0) gltexfiltermode = 0;
575
    else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1;
575
    else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1;
576
    for (i=GLTEXCACHEADSIZ-1;i>=0;i--)
576
    for (i=GLTEXCACHEADSIZ-1;i>=0;i--)
577
    {
577
    {
578
        for (pth=gltexcachead[i];pth;pth=pth->next)
578
        for (pth=gltexcachead[i];pth;pth=pth->next)
579
        {
579
        {
580
            bglBindTexture(GL_TEXTURE_2D,pth->glpic);
580
            bglBindTexture(GL_TEXTURE_2D,pth->glpic);
581
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
581
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
582
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
582
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
583
            if (glinfo.maxanisotropy > 1.0)
583
            if (glinfo.maxanisotropy > 1.0)
584
                bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
584
                bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
585
            if (r_fullbright && pth->flags & 16)
585
            if (r_fullbright && pth->flags & 16)
586
            {
586
            {
587
                bglBindTexture(GL_TEXTURE_2D,pth->ofb->glpic);
587
                bglBindTexture(GL_TEXTURE_2D,pth->ofb->glpic);
588
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
588
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
589
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
589
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
590
                if (glinfo.maxanisotropy > 1.0)
590
                if (glinfo.maxanisotropy > 1.0)
591
                    bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
591
                    bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
592
            }
592
            }
593
        }
593
        }
594
    }
594
    }
595
595
596
    {
596
    {
597
        int j;
597
        int j;
598
        mdskinmap_t *sk;
598
        mdskinmap_t *sk;
599
        md2model *m;
599
        md2model *m;
600
600
601
        for (i=0;i<nextmodelid;i++)
601
        for (i=0;i<nextmodelid;i++)
602
        {
602
        {
603
            m = (md2model *)models[i];
603
            m = (md2model *)models[i];
604
            if (m->mdnum < 2) continue;
604
            if (m->mdnum < 2) continue;
605
            for (j=0;j<m->numskins*(HICEFFECTMASK+1);j++)
605
            for (j=0;j<m->numskins*(HICEFFECTMASK+1);j++)
606
            {
606
            {
607
                if (!m->texid[j]) continue;
607
                if (!m->texid[j]) continue;
608
                bglBindTexture(GL_TEXTURE_2D,m->texid[j]);
608
                bglBindTexture(GL_TEXTURE_2D,m->texid[j]);
609
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
609
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
610
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
610
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
611
                if (glinfo.maxanisotropy > 1.0)
611
                if (glinfo.maxanisotropy > 1.0)
612
                    bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
612
                    bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
613
            }
613
            }
614
614
615
            for (sk=m->skinmap;sk;sk=sk->next)
615
            for (sk=m->skinmap;sk;sk=sk->next)
616
                for (j=0;j<(HICEFFECTMASK+1);j++)
616
                for (j=0;j<(HICEFFECTMASK+1);j++)
617
                {
617
                {
618
                    if (!sk->texid[j]) continue;
618
                    if (!sk->texid[j]) continue;
619
                    bglBindTexture(GL_TEXTURE_2D,sk->texid[j]);
619
                    bglBindTexture(GL_TEXTURE_2D,sk->texid[j]);
620
                    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
620
                    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
621
                    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
621
                    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
622
                    if (glinfo.maxanisotropy > 1.0)
622
                    if (glinfo.maxanisotropy > 1.0)
623
                        bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
623
                        bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
624
                }
624
                }
625
        }
625
        }
626
    }
626
    }
627
}
627
}
628
628
629
//--------------------------------------------------------------------------------------------------
629
//--------------------------------------------------------------------------------------------------
630
630
631
static float glox1, gloy1, glox2, gloy2;
631
static float glox1, gloy1, glox2, gloy2;
632
632
633
//Use this for both initialization and uninitialization of OpenGL.
633
//Use this for both initialization and uninitialization of OpenGL.
634
static int gltexcacnum = -1;
634
static int gltexcacnum = -1;
635
void polymost_glreset()
635
void polymost_glreset()
636
{
636
{
637
    int i;
637
    int i;
638
    pthtyp *pth, *next;
638
    pthtyp *pth, *next;
639
    //Reset if this is -1 (meaning 1st texture call ever), or > 0 (textures in memory)
639
    //Reset if this is -1 (meaning 1st texture call ever), or > 0 (textures in memory)
640
    if (gltexcacnum < 0)
640
    if (gltexcacnum < 0)
641
    {
641
    {
642
        gltexcacnum = 0;
642
        gltexcacnum = 0;
643
643
644
        //Hack for polymost_dorotatesprite calls before 1st polymost_drawrooms()
644
        //Hack for polymost_dorotatesprite calls before 1st polymost_drawrooms()
645
        gcosang = gcosang2 = ((double)16384)/262144.0;
645
        gcosang = gcosang2 = ((double)16384)/262144.0;
646
        gsinang = gsinang2 = ((double)    0)/262144.0;
646
        gsinang = gsinang2 = ((double)    0)/262144.0;
647
    }
647
    }
648
    else
648
    else
649
    {
649
    {
650
        for (i=GLTEXCACHEADSIZ-1; i>=0; i--)
650
        for (i=GLTEXCACHEADSIZ-1; i>=0; i--)
651
        {
651
        {
652
            for (pth=gltexcachead[i]; pth;)
652
            for (pth=gltexcachead[i]; pth;)
653
            {
653
            {
654
                next = pth->next;
654
                next = pth->next;
655
                if (pth->flags & 16) // fullbright textures
655
                if (pth->flags & 16) // fullbright textures
656
                {
656
                {
657
                    bglDeleteTextures(1,&pth->ofb->glpic);
657
                    bglDeleteTextures(1,&pth->ofb->glpic);
658
                    free(pth->ofb);
658
                    free(pth->ofb);
659
                }
659
                }
660
                bglDeleteTextures(1,&pth->glpic);
660
                bglDeleteTextures(1,&pth->glpic);
661
                if (pth->palmap)
661
                if (pth->palmap)
662
                {
662
                {
663
                    //_initprintf("Kill #%d\n",pth->palmap);
663
                    //_initprintf("Kill #%d\n",pth->palmap);
664
                    free(pth->palmap);pth->palmap=0;
664
                    free(pth->palmap);pth->palmap=0;
665
                }
665
                }
666
                free(pth);
666
                free(pth);
667
                pth = next;
667
                pth = next;
668
            }
668
            }
669
            gltexcachead[i] = NULL;
669
            gltexcachead[i] = NULL;
670
        }
670
        }
671
        clearskins();
671
        clearskins();
672
    }
672
    }
673
673
674
    if (polymosttext) bglDeleteTextures(1,&polymosttext);
674
    if (polymosttext) bglDeleteTextures(1,&polymosttext);
675
    polymosttext=0;
675
    polymosttext=0;
676
676
677
    memset(gltexcachead,0,sizeof(gltexcachead));
677
    memset(gltexcachead,0,sizeof(gltexcachead));
678
    glox1 = -1;
678
    glox1 = -1;
679
679
680
    // Depth peeling cleanup
680
    // Depth peeling cleanup
681
    if (peels)
681
    if (peels)
682
    {
682
    {
683
        bglDeleteProgramsARB(2, peelprogram);
683
        bglDeleteProgramsARB(2, peelprogram);
684
        bglDeleteFramebuffersEXT(r_peelscount + 1, peelfbos);
684
        bglDeleteFramebuffersEXT(r_peelscount + 1, peelfbos);
685
        bglDeleteTextures(r_peelscount + 1, peels);
685
        bglDeleteTextures(r_peelscount + 1, peels);
686
        bglDeleteTextures(3, ztexture);
686
        bglDeleteTextures(3, ztexture);
687
        free(peels);
687
        free(peels);
688
        free(peelfbos);
688
        free(peelfbos);
689
689
690
        peels = NULL;
690
        peels = NULL;
691
    }
691
    }
692
}
692
}
693
693
694
// one-time initialization of OpenGL for polymost
694
// one-time initialization of OpenGL for polymost
695
void polymost_glinit()
695
void polymost_glinit()
696
{
696
{
697
    GLfloat col[4];
697
    GLfloat col[4];
698
    int     i;
698
    int     i;
699
    char    notpeeledprogramstring[] =
699
    char    notpeeledprogramstring[] =
700
        "!!ARBfp1.0\n"
700
        "!!ARBfp1.0\n"
701
        "OPTION ARB_fog_exp2;\n"
701
        "OPTION ARB_fog_exp2;\n"
702
        "OPTION ARB_fragment_program_shadow;\n"
702
        "OPTION ARB_fragment_program_shadow;\n"
703
        "TEMP texsample;\n"
703
        "TEMP texsample;\n"
704
        "TEMP depthresult;\n"
704
        "TEMP depthresult;\n"
705
        "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n"
705
        "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n"
706
        "ADD depthresult.a, depthresult.a, -0.5;\n"
706
        "ADD depthresult.a, depthresult.a, -0.5;\n"
707
        "KIL depthresult.a;\n"
707
        "KIL depthresult.a;\n"
708
        "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n"
708
        "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n"
709
        "MUL result.color, fragment.color, texsample;\n"
709
        "MUL result.color, fragment.color, texsample;\n"
710
        "END\n";
710
        "END\n";
711
    char    peeledprogramstring[] =
711
    char    peeledprogramstring[] =
712
        "!!ARBfp1.0\n"
712
        "!!ARBfp1.0\n"
713
        "OPTION ARB_fog_exp2;\n"
713
        "OPTION ARB_fog_exp2;\n"
714
        "OPTION ARB_fragment_program_shadow;\n"
714
        "OPTION ARB_fragment_program_shadow;\n"
715
        "TEMP texsample;\n"
715
        "TEMP texsample;\n"
716
        "TEMP depthresult;\n"
716
        "TEMP depthresult;\n"
717
        "TEX depthresult, fragment.position, texture[2], SHADOWRECT;\n"
717
        "TEX depthresult, fragment.position, texture[2], SHADOWRECT;\n"
718
        "ADD depthresult.a, depthresult.a, -0.5;\n"
718
        "ADD depthresult.a, depthresult.a, -0.5;\n"
719
        "KIL depthresult.a;\n"
719
        "KIL depthresult.a;\n"
720
        "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n"
720
        "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n"
721
        "ADD depthresult.a, depthresult.a, -0.5;\n"
721
        "ADD depthresult.a, depthresult.a, -0.5;\n"
722
        "KIL depthresult.a;\n"
722
        "KIL depthresult.a;\n"
723
        "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n"
723
        "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n"
724
        "MUL result.color, fragment.color, texsample;\n"
724
        "MUL result.color, fragment.color, texsample;\n"
725
        "END\n";
725
        "END\n";
726
726
727
#if 1
727
#if 1
728
    if (!Bstrcmp(glinfo.vendor, "ATI Technologies Inc."))
728
    if (!Bstrcmp(glinfo.vendor, "ATI Technologies Inc."))
729
    {
729
    {
730
        initprintf("polymost_glinit(): ATI detected, GL_FOG_HINT = GL_DONT_CARE\n");
730
        initprintf("polymost_glinit(): ATI detected, GL_FOG_HINT = GL_DONT_CARE\n");
731
        bglHint(GL_FOG_HINT,GL_DONT_CARE);
731
        bglHint(GL_FOG_HINT,GL_DONT_CARE);
732
    }
732
    }
733
    else
733
    else
734
    {
734
    {
735
        bglHint(GL_FOG_HINT,GL_NICEST);
735
        bglHint(GL_FOG_HINT,GL_NICEST);
736
    }
736
    }
737
#else
737
#else
738
    bglHint(GL_FOG_HINT,GL_DONT_CARE);
738
    bglHint(GL_FOG_HINT,GL_DONT_CARE);
739
#endif
739
#endif
740
740
741
    bglFogi(GL_FOG_MODE,GL_EXP2);
741
    bglFogi(GL_FOG_MODE,GL_EXP2);
742
    bglFogf(GL_FOG_DENSITY,1.0); //must be > 0, default is 1
742
    bglFogf(GL_FOG_DENSITY,1.0); //must be > 0, default is 1
743
    /*    bglFogf(GL_FOG_START,0.0); //default is 0
743
    /*    bglFogf(GL_FOG_START,0.0); //default is 0
744
        bglFogf(GL_FOG_END,1.0); //default is 1 */
744
        bglFogf(GL_FOG_END,1.0); //default is 1 */
745
    col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0; //range:0 to 1
745
    col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0; //range:0 to 1
746
    bglFogfv(GL_FOG_COLOR,col); //default is 0,0,0,0
746
    bglFogfv(GL_FOG_COLOR,col); //default is 0,0,0,0
747
747
748
    bglBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
748
    bglBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
749
749
750
    //bglHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
750
    //bglHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
751
    //bglEnable(GL_LINE_SMOOTH);
751
    //bglEnable(GL_LINE_SMOOTH);
752
752
753
    if (glmultisample > 0 && glinfo.multisample)
753
    if (glmultisample > 0 && glinfo.multisample)
754
    {
754
    {
755
        if (glinfo.nvmultisamplehint)
755
        if (glinfo.nvmultisamplehint)
756
            bglHint(GL_MULTISAMPLE_FILTER_HINT_NV, glnvmultisamplehint ? GL_NICEST:GL_FASTEST);
756
            bglHint(GL_MULTISAMPLE_FILTER_HINT_NV, glnvmultisamplehint ? GL_NICEST:GL_FASTEST);
757
        bglEnable(GL_MULTISAMPLE_ARB);
757
        bglEnable(GL_MULTISAMPLE_ARB);
758
    }
758
    }
759
759
760
    if (r_depthpeeling && (!glinfo.arbfp || !glinfo.depthtex || !glinfo.shadow || !glinfo.fbos || !glinfo.rect || !glinfo.multitex))
760
    if (r_depthpeeling && (!glinfo.arbfp || !glinfo.depthtex || !glinfo.shadow || !glinfo.fbos || !glinfo.rect || !glinfo.multitex))
761
    {
761
    {
762
        OSD_Printf("Your OpenGL implementation doesn't support depth peeling. Disabling...\n");
762
        OSD_Printf("Your OpenGL implementation doesn't support depth peeling. Disabling...\n");
763
        r_depthpeeling = 0;
763
        r_depthpeeling = 0;
764
    }
764
    }
765
765
766
    if (r_detailmapping && (!glinfo.multitex || !glinfo.envcombine))
766
    if (r_detailmapping && (!glinfo.multitex || !glinfo.envcombine))
767
    {
767
    {
768
        OSD_Printf("Your OpenGL implementation doesn't support detail mapping. Disabling...\n");
768
        OSD_Printf("Your OpenGL implementation doesn't support detail mapping. Disabling...\n");
769
        r_detailmapping = 0;
769
        r_detailmapping = 0;
770
    }
770
    }
771
771
772
    if (r_glowmapping && (!glinfo.multitex || !glinfo.envcombine))
772
    if (r_glowmapping && (!glinfo.multitex || !glinfo.envcombine))
773
    {
773
    {
774
        OSD_Printf("Your OpenGL implementation doesn't support glow mapping. Disabling...\n");
774
        OSD_Printf("Your OpenGL implementation doesn't support glow mapping. Disabling...\n");
775
        r_glowmapping = 0;
775
        r_glowmapping = 0;
776
    }
776
    }
777
777
778
    if (r_vbos && (!glinfo.vbos))
778
    if (r_vbos && (!glinfo.vbos))
779
    {
779
    {
780
        OSD_Printf("Your OpenGL implementation doesn't support Vertex Buffer Objects. Disabling...\n");
780
        OSD_Printf("Your OpenGL implementation doesn't support Vertex Buffer Objects. Disabling...\n");
781
        r_vbos = 0;
781
        r_vbos = 0;
782
    }
782
    }
783
783
784
    //depth peeling initialization
784
    //depth peeling initialization
785
    if (r_depthpeeling)
785
    if (r_depthpeeling)
786
    {
786
    {
787
        if (newpeelscount)
787
        if (newpeelscount)
788
        {
788
        {
789
            r_peelscount = newpeelscount;
789
            r_peelscount = newpeelscount;
790
            newpeelscount = 0;
790
            newpeelscount = 0;
791
        }
791
        }
792
        // create the secondary Z-buffers and the Z-backbuffer
792
        // create the secondary Z-buffers and the Z-backbuffer
793
        bglGenTextures(3, ztexture);
793
        bglGenTextures(3, ztexture);
794
794
795
        i = 0;
795
        i = 0;
796
        while (i < 3)
796
        while (i < 3)
797
        {
797
        {
798
            bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[i]);
798
            bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[i]);
799
            bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT, 0, 0, xdim, ydim, 0);
799
            bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT, 0, 0, xdim, ydim, 0);
800
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
800
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
801
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
801
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
802
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
802
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
803
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);
803
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);
804
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
804
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
805
            if (i < 2)
805
            if (i < 2)
806
                bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER);
806
                bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER);
807
            else
807
            else
808
                bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LESS);
808
                bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LESS);
809
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
809
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
810
810
811
            i++;
811
            i++;
812
        }
812
        }
813
813
814
        // create the various peeling layers as well as the FBOs to render to them
814
        // create the various peeling layers as well as the FBOs to render to them
815
        peels = malloc((r_peelscount + 1) * sizeof(GLuint));
815
        peels = malloc((r_peelscount + 1) * sizeof(GLuint));
816
        bglGenTextures(r_peelscount + 1, peels);
816
        bglGenTextures(r_peelscount + 1, peels);
817
817
818
        peelfbos = malloc((r_peelscount + 1) * sizeof(GLuint));
818
        peelfbos = malloc((r_peelscount + 1) * sizeof(GLuint));
819
        bglGenFramebuffersEXT(r_peelscount + 1, peelfbos);
819
        bglGenFramebuffersEXT(r_peelscount + 1, peelfbos);
820
820
821
        i = 0;
821
        i = 0;
822
        while (i <= r_peelscount)
822
        while (i <= r_peelscount)
823
        {
823
        {
824
            bglBindTexture(GL_TEXTURE_RECTANGLE, peels[i]);
824
            bglBindTexture(GL_TEXTURE_RECTANGLE, peels[i]);
825
            bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, xdim, ydim, 0);
825
            bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, xdim, ydim, 0);
826
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
826
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
827
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
827
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
828
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
828
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
829
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);
829
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);
830
830
831
            bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, peelfbos[i]);
831
            bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, peelfbos[i]);
832
            bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE, peels[i], 0);
832
            bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE, peels[i], 0);
833
            if (i == r_peelscount) // bakcbuffer
833
            if (i == r_peelscount) // bakcbuffer
834
                bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[2], 0);
834
                bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[2], 0);
835
            else if (i < (r_peelscount - 1))
835
            else if (i < (r_peelscount - 1))
836
                bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[i % 2], 0);
836
                bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[i % 2], 0);
837
837
838
            if (bglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
838
            if (bglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
839
            {
839
            {
840
                OSD_Printf("FBO #%d initialization failed.\n", i);
840
                OSD_Printf("FBO #%d initialization failed.\n", i);
841
            }
841
            }
842
842
843
            bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
843
            bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
844
844
845
            i++;
845
            i++;
846
        }
846
        }
847
847
848
        // create the peeling fragment programs
848
        // create the peeling fragment programs
849
        bglGenProgramsARB(2, peelprogram);
849
        bglGenProgramsARB(2, peelprogram);
850
        bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[0]);
850
        bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[0]);
851
        bglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(notpeeledprogramstring), notpeeledprogramstring);
851
        bglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(notpeeledprogramstring), notpeeledprogramstring);
852
        bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[1]);
852
        bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[1]);
853
        bglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(peeledprogramstring), peeledprogramstring);
853
        bglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(peeledprogramstring), peeledprogramstring);
854
    }
854
    }
855
855
856
    bglEnableClientState(GL_VERTEX_ARRAY);
856
    bglEnableClientState(GL_VERTEX_ARRAY);
857
    bglEnableClientState(GL_TEXTURE_COORD_ARRAY);
857
    bglEnableClientState(GL_TEXTURE_COORD_ARRAY);
858
}
858
}
859
859
860
void resizeglcheck()
860
void resizeglcheck()
861
{
861
{
862
    float m[4][4];
862
    float m[4][4];
863
    int fovcorrect;
863
    int fovcorrect;
864
864
865
    if (glredbluemode < lastglredbluemode)
865
    if (glredbluemode < lastglredbluemode)
866
    {
866
    {
867
        glox1 = -1;
867
        glox1 = -1;
868
        bglColorMask(1,1,1,1);
868
        bglColorMask(1,1,1,1);
869
    }
869
    }
870
    else if (glredbluemode != lastglredbluemode)
870
    else if (glredbluemode != lastglredbluemode)
871
    {
871
    {
872
        redblueclearcnt = 0;
872
        redblueclearcnt = 0;
873
    }
873
    }
874
    lastglredbluemode = glredbluemode;
874
    lastglredbluemode = glredbluemode;
875
875
876
    //FUK
876
    //FUK
877
    if (lastglpolygonmode != glpolygonmode)
877
    if (lastglpolygonmode != glpolygonmode)
878
    {
878
    {
879
        lastglpolygonmode = glpolygonmode;
879
        lastglpolygonmode = glpolygonmode;
880
        switch (glpolygonmode)
880
        switch (glpolygonmode)
881
        {
881
        {
882
        default:
882
        default:
883
        case 0:
883
        case 0:
884
            bglPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
884
            bglPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
885
        case 1:
885
        case 1:
886
            bglPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
886
            bglPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
887
        case 2:
887
        case 2:
888
            bglPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break;
888
            bglPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break;
889
        }
889
        }
890
    }
890
    }
891
    if (glpolygonmode) //FUK
891
    if (glpolygonmode) //FUK
892
    {
892
    {
893
        bglClearColor(1.0,1.0,1.0,0.0);
893
        bglClearColor(1.0,1.0,1.0,0.0);
894
        bglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
894
        bglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
895
        bglDisable(GL_TEXTURE_2D);
895
        bglDisable(GL_TEXTURE_2D);
896
    }
896
    }
897
897
898
    if ((glox1 != windowx1) || (gloy1 != windowy1) || (glox2 != windowx2) || (gloy2 != windowy2))
898
    if ((glox1 != windowx1) || (gloy1 != windowy1) || (glox2 != windowx2) || (gloy2 != windowy2))
899
    {
899
    {
900
        glox1 = windowx1; gloy1 = windowy1;
900
        glox1 = windowx1; gloy1 = windowy1;
901
        glox2 = windowx2; gloy2 = windowy2;
901
        glox2 = windowx2; gloy2 = windowy2;
902
902
903
        fovcorrect = glprojectionhacks?(glwidescreen?0:(((windowx2-windowx1+1) * 1.2) - (windowx2-windowx1+1))):0;
903
        fovcorrect = glprojectionhacks?(glwidescreen?0:(((windowx2-windowx1+1) * 1.2) - (windowx2-windowx1+1))):0;
904
904
905
        bglViewport(windowx1 - (fovcorrect / 2), yres-(windowy2+1),windowx2-windowx1+1 + fovcorrect, windowy2-windowy1+1);
905
        bglViewport(windowx1 - (fovcorrect / 2), yres-(windowy2+1),windowx2-windowx1+1 + fovcorrect, windowy2-windowy1+1);
906
906
907
        bglMatrixMode(GL_PROJECTION);
907
        bglMatrixMode(GL_PROJECTION);
908
        memset(m,0,sizeof(m));
908
        memset(m,0,sizeof(m));
909
        m[0][0] = (float)ydimen / (glprojectionhacks?1.2:1); m[0][2] = 1.0;
909
        m[0][0] = (float)ydimen / (glprojectionhacks?1.2:1); m[0][2] = 1.0;
910
        m[1][1] = (float)xdimen; m[1][2] = 1.0;
910
        m[1][1] = (float)xdimen; m[1][2] = 1.0;
911
        m[2][2] = 1.0; m[2][3] = (float)ydimen / (glprojectionhacks?1.2:1);
911
        m[2][2] = 1.0; m[2][3] = (float)ydimen / (glprojectionhacks?1.2:1);
912
        m[3][2] =-1.0;
912
        m[3][2] =-1.0;
913
        bglLoadMatrixf(&m[0][0]);
913
        bglLoadMatrixf(&m[0][0]);
914
        //bglLoadIdentity();
914
        //bglLoadIdentity();
915
915
916
        bglMatrixMode(GL_MODELVIEW);
916
        bglMatrixMode(GL_MODELVIEW);
917
        bglLoadIdentity();
917
        bglLoadIdentity();
918
918
919
        if (!nofog) bglEnable(GL_FOG);
919
        if (!nofog) bglEnable(GL_FOG);
920
920
921
        //bglEnable(GL_TEXTURE_2D);
921
        //bglEnable(GL_TEXTURE_2D);
922
    }
922
    }
923
}
923
}
924
924
925
void fixtransparency(coltype *dapic, int daxsiz, int daysiz, int daxsiz2, int daysiz2, int dameth)
925
void fixtransparency(coltype *dapic, int daxsiz, int daysiz, int daxsiz2, int daysiz2, int dameth)
926
{
926
{
927
    coltype *wpptr;
927
    coltype *wpptr;
928
    int j, x, y, r, g, b, dox, doy, naxsiz2;
928
    int j, x, y, r, g, b, dox, doy, naxsiz2;
929
929
930
    dox = daxsiz2-1; doy = daysiz2-1;
930
    dox = daxsiz2-1; doy = daysiz2-1;
931
    if (dameth&4) { dox = min(dox,daxsiz); doy = min(doy,daysiz); }
931
    if (dameth&4) { dox = min(dox,daxsiz); doy = min(doy,daysiz); }
932
    else { daxsiz = daxsiz2; daysiz = daysiz2; } //Make repeating textures duplicate top/left parts
932
    else { daxsiz = daxsiz2; daysiz = daysiz2; } //Make repeating textures duplicate top/left parts
933
933
934
    daxsiz--; daysiz--; naxsiz2 = -daxsiz2; //Hacks for optimization inside loop
934
    daxsiz--; daysiz--; naxsiz2 = -daxsiz2; //Hacks for optimization inside loop
935
935
936
    //Set transparent pixels to average color of neighboring opaque pixels
936
    //Set transparent pixels to average color of neighboring opaque pixels
937
    //Doing this makes bilinear filtering look much better for masked textures (I.E. sprites)
937
    //Doing this makes bilinear filtering look much better for masked textures (I.E. sprites)
938
    for (y=doy;y>=0;y--)
938
    for (y=doy;y>=0;y--)
939
    {
939
    {
940
        wpptr = &dapic[y*daxsiz2+dox];
940
        wpptr = &dapic[y*daxsiz2+dox];
941
        for (x=dox;x>=0;x--,wpptr--)
941
        for (x=dox;x>=0;x--,wpptr--)
942
        {
942
        {
943
            if (wpptr->a) continue;
943
            if (wpptr->a) continue;
944
            r = g = b = j = 0;
944
            r = g = b = j = 0;
945
            if ((x>     0) && (wpptr[     -1].a)) { r += (int)wpptr[     -1].r; g += (int)wpptr[     -1].g; b += (int)wpptr[     -1].b; j++; }
945
            if ((x>     0) && (wpptr[     -1].a)) { r += (int)wpptr[     -1].r; g += (int)wpptr[     -1].g; b += (int)wpptr[     -1].b; j++; }
946
            if ((x<daxsiz) && (wpptr[     +1].a)) { r += (int)wpptr[     +1].r; g += (int)wpptr[     +1].g; b += (int)wpptr[     +1].b; j++; }
946
            if ((x<daxsiz) && (wpptr[     +1].a)) { r += (int)wpptr[     +1].r; g += (int)wpptr[     +1].g; b += (int)wpptr[     +1].b; j++; }
947
            if ((y>     0) && (wpptr[naxsiz2].a)) { r += (int)wpptr[naxsiz2].r; g += (int)wpptr[naxsiz2].g; b += (int)wpptr[naxsiz2].b; j++; }
947
            if ((y>     0) && (wpptr[naxsiz2].a)) { r += (int)wpptr[naxsiz2].r; g += (int)wpptr[naxsiz2].g; b += (int)wpptr[naxsiz2].b; j++; }
948
            if ((y<daysiz) && (wpptr[daxsiz2].a)) { r += (int)wpptr[daxsiz2].r; g += (int)wpptr[daxsiz2].g; b += (int)wpptr[daxsiz2].b; j++; }
948
            if ((y<daysiz) && (wpptr[daxsiz2].a)) { r += (int)wpptr[daxsiz2].r; g += (int)wpptr[daxsiz2].g; b += (int)wpptr[daxsiz2].b; j++; }
949
            switch (j)
949
            switch (j)
950
            {
950
            {
951
            case 1:
951
            case 1:
952
                wpptr->r =   r            ; wpptr->g =   g            ; wpptr->b =   b            ; break;
952
                wpptr->r =   r            ; wpptr->g =   g            ; wpptr->b =   b            ; break;
953
            case 2:
953
            case 2:
954
                wpptr->r = ((r   +  1)>>1); wpptr->g = ((g   +  1)>>1); wpptr->b = ((b   +  1)>>1); break;
954
                wpptr->r = ((r   +  1)>>1); wpptr->g = ((g   +  1)>>1); wpptr->b = ((b   +  1)>>1); break;
955
            case 3:
955
            case 3:
956
                wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break;
956
                wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break;
957
            case 4:
957
            case 4:
958
                wpptr->r = ((r   +  2)>>2); wpptr->g = ((g   +  2)>>2); wpptr->b = ((b   +  2)>>2); break;
958
                wpptr->r = ((r   +  2)>>2); wpptr->g = ((g   +  2)>>2); wpptr->b = ((b   +  2)>>2); break;
959
            default:
959
            default:
960
                break;
960
                break;
961
            }
961
            }
962
        }
962
        }
963
    }
963
    }
964
}
964
}
965
965
966
static void uploadtexture(int doalloc, int xsiz, int ysiz, int intexfmt, int texfmt, coltype *pic, int tsizx, int tsizy, int dameth)
966
static void uploadtexture(int doalloc, int xsiz, int ysiz, int intexfmt, int texfmt, coltype *pic, int tsizx, int tsizy, int dameth)
967
{
967
{
968
    coltype *wpptr, *rpptr;
968
    coltype *wpptr, *rpptr;
969
    int x2, y2, j, js=0, x3, y3, y, x, r, g, b, a, k;
969
    int x2, y2, j, js=0, x3, y3, y, x, r, g, b, a, k;
970
970
971
    if (gltexmaxsize <= 0)
971
    if (gltexmaxsize <= 0)
972
    {
972
    {
973
        GLint i = 0;
973
        GLint i = 0;
974
        bglGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
974
        bglGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
975
        if (!i) gltexmaxsize = 6;   // 2^6 = 64 == default GL max texture size
975
        if (!i) gltexmaxsize = 6;   // 2^6 = 64 == default GL max texture size
976
        else
976
        else
977
        {
977
        {
978
            gltexmaxsize = 0;
978
            gltexmaxsize = 0;
979
            for (; i>1; i>>=1) gltexmaxsize++;
979
            for (; i>1; i>>=1) gltexmaxsize++;
980
        }
980
        }
981
    }
981
    }
982
982
983
    js = max(0,min(gltexmaxsize-1,gltexmiplevel));
983
    js = max(0,min(gltexmaxsize-1,gltexmiplevel));
984
    gltexmiplevel = js;
984
    gltexmiplevel = js;
985
    while ((xsiz>>js) > (1<<gltexmaxsize) || (ysiz>>js) > (1<<gltexmaxsize)) js++;
985
    while ((xsiz>>js) > (1<<gltexmaxsize) || (ysiz>>js) > (1<<gltexmaxsize)) js++;
986
986
987
    /*
987
    /*
988
    OSD_Printf("Uploading %dx%d %s as %s\n", xsiz,ysiz,
988
    OSD_Printf("Uploading %dx%d %s as %s\n", xsiz,ysiz,
989
                (texfmt==GL_RGBA?"GL_RGBA":
989
                (texfmt==GL_RGBA?"GL_RGBA":
990
                 texfmt==GL_RGB?"GL_RGB":
990
                 texfmt==GL_RGB?"GL_RGB":
991
                 texfmt==GL_BGR?"GL_BGR":
991
                 texfmt==GL_BGR?"GL_BGR":
992
                 texfmt==GL_BGRA?"GL_BGRA":"other"),
992
                 texfmt==GL_BGRA?"GL_BGRA":"other"),
993
                (intexfmt==GL_RGBA?"GL_RGBA":
993
                (intexfmt==GL_RGBA?"GL_RGBA":
994
                 intexfmt==GL_RGB?"GL_RGB":
994
                 intexfmt==GL_RGB?"GL_RGB":
995
                 intexfmt==GL_COMPRESSED_RGBA_ARB?"GL_COMPRESSED_RGBA_ARB":
995
                 intexfmt==GL_COMPRESSED_RGBA_ARB?"GL_COMPRESSED_RGBA_ARB":
996
                 intexfmt==GL_COMPRESSED_RGB_ARB?"GL_COMPRESSED_RGB_ARB":"other"));
996
                 intexfmt==GL_COMPRESSED_RGB_ARB?"GL_COMPRESSED_RGB_ARB":"other"));
997
    */
997
    */
998
998
999
    if (js == 0)
999
    if (js == 0)
1000
    {
1000
    {
1001
        if (doalloc&1)
1001
        if (doalloc&1)
1002
            bglTexImage2D(GL_TEXTURE_2D,0,intexfmt,xsiz,ysiz,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
1002
            bglTexImage2D(GL_TEXTURE_2D,0,intexfmt,xsiz,ysiz,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
1003
        else
1003
        else
1004
            bglTexSubImage2D(GL_TEXTURE_2D,0,0,0,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
1004
            bglTexSubImage2D(GL_TEXTURE_2D,0,0,0,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
1005
    }
1005
    }
1006
1006
1007
#if 0
1007
#if 0
1008
    gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //Needs C++ to link?
1008
    gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //Needs C++ to link?
1009
#elif 1
1009
#elif 1
1010
    x2 = xsiz; y2 = ysiz;
1010
    x2 = xsiz; y2 = ysiz;
1011
    for (j=1;(x2 > 1) || (y2 > 1);j++)
1011
    for (j=1;(x2 > 1) || (y2 > 1);j++)
1012
    {
1012
    {
1013
        //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1);
1013
        //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1);
1014
        x3 = max(1, x2 >> 1); y3 = max(1, y2 >> 1);             // this came from the GL_ARB_texture_non_power_of_two spec
1014
        x3 = max(1, x2 >> 1); y3 = max(1, y2 >> 1);             // this came from the GL_ARB_texture_non_power_of_two spec
1015
        for (y=0;y<y3;y++)
1015
        for (y=0;y<y3;y++)
1016
        {
1016
        {
1017
            wpptr = &pic[y*x3]; rpptr = &pic[(y<<1)*x2];
1017
            wpptr = &pic[y*x3]; rpptr = &pic[(y<<1)*x2];
1018
            for (x=0;x<x3;x++,wpptr++,rpptr+=2)
1018
            for (x=0;x<x3;x++,wpptr++,rpptr+=2)
1019
            {
1019
            {
1020
                r = g = b = a = k = 0;
1020
                r = g = b = a = k = 0;
1021
                if (rpptr[0].a)                  { r += (int)rpptr[0].r; g += (int)rpptr[0].g; b += (int)rpptr[0].b; a += (int)rpptr[0].a; k++; }
1021
                if (rpptr[0].a)                  { r += (int)rpptr[0].r; g += (int)rpptr[0].g; b += (int)rpptr[0].b; a += (int)rpptr[0].a; k++; }
1022
                if ((x+x+1 < x2) && (rpptr[1].a)) { r += (int)rpptr[1].r; g += (int)rpptr[1].g; b += (int)rpptr[1].b; a += (int)rpptr[1].a; k++; }
1022
                if ((x+x+1 < x2) && (rpptr[1].a)) { r += (int)rpptr[1].r; g += (int)rpptr[1].g; b += (int)rpptr[1].b; a += (int)rpptr[1].a; k++; }
1023
                if (y+y+1 < y2)
1023
                if (y+y+1 < y2)
1024
                {
1024
                {
1025
                    if ((rpptr[x2].a)) { r += (int)rpptr[x2  ].r; g += (int)rpptr[x2  ].g; b += (int)rpptr[x2  ].b; a += (int)rpptr[x2  ].a; k++; }
1025
                    if ((rpptr[x2].a)) { r += (int)rpptr[x2  ].r; g += (int)rpptr[x2  ].g; b += (int)rpptr[x2  ].b; a += (int)rpptr[x2  ].a; k++; }
1026
                    if ((x+x+1 < x2) && (rpptr[x2+1].a)) { r += (int)rpptr[x2+1].r; g += (int)rpptr[x2+1].g; b += (int)rpptr[x2+1].b; a += (int)rpptr[x2+1].a; k++; }
1026
                    if ((x+x+1 < x2) && (rpptr[x2+1].a)) { r += (int)rpptr[x2+1].r; g += (int)rpptr[x2+1].g; b += (int)rpptr[x2+1].b; a += (int)rpptr[x2+1].a; k++; }
1027
                }
1027
                }
1028
                switch (k)
1028
                switch (k)
1029
                {
1029
                {
1030
                case 0:
1030
                case 0:
1031
                case 1:
1031
                case 1:
1032
                    wpptr->r = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break;
1032
                    wpptr->r = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break;
1033
                case 2:
1033
                case 2:
1034
                    wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break;
1034
                    wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break;
1035
                case 3:
1035
                case 3:
1036
                    wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); wpptr->a = ((a*85+128)>>8); break;
1036
                    wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); wpptr->a = ((a*85+128)>>8); break;
1037
                case 4:
1037
                case 4:
1038
                    wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break;
1038
                    wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break;
1039
                default:
1039
                default:
1040
                    break;
1040
                    break;
1041
                }
1041
                }
1042
                //if (wpptr->a) wpptr->a = 255;
1042
                //if (wpptr->a) wpptr->a = 255;
1043
            }
1043
            }
1044
        }
1044
        }
1045
        if (tsizx >= 0) fixtransparency(pic,(tsizx+(1<<j)-1)>>j,(tsizy+(1<<j)-1)>>j,x3,y3,dameth);
1045
        if (tsizx >= 0) fixtransparency(pic,(tsizx+(1<<j)-1)>>j,(tsizy+(1<<j)-1)>>j,x3,y3,dameth);
1046
        if (j >= js)
1046
        if (j >= js)
1047
        {
1047
        {
1048
            if (doalloc&1)
1048
            if (doalloc&1)
1049
                bglTexImage2D(GL_TEXTURE_2D,j-js,intexfmt,x3,y3,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
1049
                bglTexImage2D(GL_TEXTURE_2D,j-js,intexfmt,x3,y3,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
1050
            else
1050
            else
1051
                bglTexSubImage2D(GL_TEXTURE_2D,j-js,0,0,x3,y3,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
1051
                bglTexSubImage2D(GL_TEXTURE_2D,j-js,0,0,x3,y3,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
1052
        }
1052
        }
1053
        x2 = x3; y2 = y3;
1053
        x2 = x3; y2 = y3;
1054
    }
1054
    }
1055
#endif
1055
#endif
1056
}
1056
}
1057
1057
1058
int gloadtile_art(int dapic, int dapal, int dameth, pthtyp *pth, int doalloc)
1058
int gloadtile_art(int dapic, int dapal, int dameth, pthtyp *pth, int doalloc)
1059
{
1059
{
1060
    coltype *pic, *wpptr;
1060
    coltype *pic, *wpptr;
1061
    int x, y, x2, y2, xsiz, ysiz, dacol, tsizx, tsizy;
1061
    int x, y, x2, y2, xsiz, ysiz, dacol, tsizx, tsizy;
1062
    char hasalpha = 0, hasfullbright = 0;
1062
    char hasalpha = 0, hasfullbright = 0;
1063
1063
1064
    tsizx = tilesizx[dapic];
1064
    tsizx = tilesizx[dapic];
1065
    tsizy = tilesizy[dapic];
1065
    tsizy = tilesizy[dapic];
1066
    if (!glinfo.texnpot)
1066
    if (!glinfo.texnpot)
1067
    {
1067
    {
1068
        for (xsiz=1;xsiz<tsizx;xsiz+=xsiz);
1068
        for (xsiz=1;xsiz<tsizx;xsiz+=xsiz);
1069
        for (ysiz=1;ysiz<tsizy;ysiz+=ysiz);
1069
        for (ysiz=1;ysiz<tsizy;ysiz+=ysiz);
1070
    }
1070
    }
1071
    else
1071
    else
1072
    {
1072
    {
1073
        if ((tsizx|tsizy) == 0)
1073
        if ((tsizx|tsizy) == 0)
1074
        {
1074
        {
1075
            xsiz = ysiz = 1;
1075
            xsiz = ysiz = 1;
1076
        }
1076
        }
1077
        else
1077
        else
1078
        {
1078
        {
1079
            xsiz = tsizx;
1079
            xsiz = tsizx;
1080
            ysiz = tsizy;
1080
            ysiz = tsizy;
1081
        }
1081
        }
1082
    }
1082
    }
1083
1083
1084
    pic = (coltype *)malloc(xsiz*ysiz*sizeof(coltype));
1084
    pic = (coltype *)malloc(xsiz*ysiz*sizeof(coltype));
1085
    if (!pic) return 1;
1085
    if (!pic) return 1;
1086
1086
1087
    if (!waloff[dapic])
1087
    if (!waloff[dapic])
1088
    {
1088
    {
1089
        //Force invalid textures to draw something - an almost purely transparency texture
1089
        //Force invalid textures to draw something - an almost purely transparency texture
1090
        //This allows the Z-buffer to be updated for mirrors (which are invalidated textures)
1090
        //This allows the Z-buffer to be updated for mirrors (which are invalidated textures)
1091
        pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1;
1091
        pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1;
1092
        tsizx = tsizy = 1; hasalpha = 1;
1092
        tsizx = tsizy = 1; hasalpha = 1;
1093
    }
1093
    }
1094
    else
1094
    else
1095
    {
1095
    {
1096
        for (y=0;y<ysiz;y++)
1096
        for (y=0;y<ysiz;y++)
1097
        {
1097
        {
1098
            if (y < tsizy) y2 = y; else y2 = y-tsizy;
1098
            if (y < tsizy) y2 = y; else y2 = y-tsizy;
1099
            wpptr = &pic[y*xsiz];
1099
            wpptr = &pic[y*xsiz];
1100
            for (x=0;x<xsiz;x++,wpptr++)
1100
            for (x=0;x<xsiz;x++,wpptr++)
1101
            {
1101
            {
1102
                if ((dameth&4) && ((x >= tsizx) || (y >= tsizy))) //Clamp texture
1102
                if ((dameth&4) && ((x >= tsizx) || (y >= tsizy))) //Clamp texture
1103
                    { wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0; continue; }
1103
                    { wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0; continue; }
1104
                if (x < tsizx) x2 = x; else x2 = x-tsizx;
1104
                if (x < tsizx) x2 = x; else x2 = x-tsizx;
1105
                dacol = (int)(*(unsigned char *)(waloff[dapic]+x2*tsizy+y2));
1105
                dacol = (int)(*(unsigned char *)(waloff[dapic]+x2*tsizy+y2));
1106
                if (!fullbrightloadingpass)
1106
                if (!fullbrightloadingpass)
1107
                {
1107
                {
1108
                    // regular texture
1108
                    // regular texture
1109
                    if ((dacol > 239) && (dacol != 255))
1109
                    if ((dacol > 239) && (dacol != 255))
1110
                        hasfullbright = 1;
1110
                        hasfullbright = 1;
1111
                    wpptr->a = 255;
1111
                    wpptr->a = 255;
1112
                }
1112
                }
1113
                else if (fullbrightloadingpass == 1)
1113
                else if (fullbrightloadingpass == 1)
1114
                {
1114
                {
1115
                    // texture with only fullbright areas
1115
                    // texture with only fullbright areas
1116
                    if (dacol < 240)    // regular colors
1116
                    if (dacol < 240)    // regular colors
1117
                    {
1117
                    {
1118
                        wpptr->a = 0; hasalpha = 1;
1118
                        wpptr->a = 0; hasalpha = 1;
1119
                    }
1119
                    }
1120
                    else   // fullbright
1120
                    else   // fullbright
1121
                    {
1121
                    {
1122
                        wpptr->a = 255;
1122
                        wpptr->a = 255;
1123
                    }
1123
                    }
1124
                }
1124
                }
1125
                if (dacol != 255)
1125
                if (dacol != 255)
1126
                    dacol = (int)((unsigned char)palookup[dapal][dacol]);
1126
                    dacol = (int)((unsigned char)palookup[dapal][dacol]);
1127
                else
1127
                else
1128
                {
1128
                {
1129
                    wpptr->a = 0; hasalpha = 1;
1129
                    wpptr->a = 0; hasalpha = 1;
1130
                }
1130
                }
1131
                if (gammabrightness)
1131
                if (gammabrightness)
1132
                {
1132
                {
1133
                    wpptr->r = curpalette[dacol].r;
1133
                    wpptr->r = curpalette[dacol].r;
1134
                    wpptr->g = curpalette[dacol].g;
1134
                    wpptr->g = curpalette[dacol].g;
1135
                    wpptr->b = curpalette[dacol].b;
1135
                    wpptr->b = curpalette[dacol].b;
1136
                }
1136
                }
1137
                else
1137
                else
1138
                {
1138
                {
1139
                    wpptr->r = britable[curbrightness][ curpalette[dacol].r ];
1139
                    wpptr->r = britable[curbrightness][ curpalette[dacol].r ];
1140
                    wpptr->g = britable[curbrightness][ curpalette[dacol].g ];
1140
                    wpptr->g = britable[curbrightness][ curpalette[dacol].g ];
1141
                    wpptr->b = britable[curbrightness][ curpalette[dacol].b ];
1141
                    wpptr->b = britable[curbrightness][ curpalette[dacol].b ];
1142
                }
1142
                }
1143
            }
1143
            }
1144
        }
1144
        }
1145
    }
1145
    }
1146
1146
1147
    if (doalloc) bglGenTextures(1,(GLuint*)&pth->glpic);  //# of textures (make OpenGL allocate structure)
1147
    if (doalloc) bglGenTextures(1,(GLuint*)&pth->glpic);  //# of textures (make OpenGL allocate structure)
1148
    bglBindTexture(GL_TEXTURE_2D,pth->glpic);
1148
    bglBindTexture(GL_TEXTURE_2D,pth->glpic);
1149
1149
1150
    fixtransparency(pic,tsizx,tsizy,xsiz,ysiz,dameth);
1150
    fixtransparency(pic,tsizx,tsizy,xsiz,ysiz,dameth);
1151
    uploadtexture(doalloc,xsiz,ysiz,hasalpha?GL_RGBA:GL_RGB,GL_RGBA,pic,tsizx,tsizy,dameth);
1151
    uploadtexture(doalloc,xsiz,ysiz,hasalpha?GL_RGBA:GL_RGB,GL_RGBA,pic,tsizx,tsizy,dameth);
1152
1152
1153
    if (gltexfiltermode < 0) gltexfiltermode = 0;
1153
    if (gltexfiltermode < 0) gltexfiltermode = 0;
1154
    else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1;
1154
    else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1;
1155
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
1155
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
1156
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
1156
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
1157
1157
1158
    if (glinfo.maxanisotropy > 1.0)
1158
    if (glinfo.maxanisotropy > 1.0)
1159
    {
1159
    {
1160
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy;
1160
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy;
1161
        bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
1161
        bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
1162
    }
1162
    }
1163
1163
1164
    if (!(dameth&4))
1164
    if (!(dameth&4))
1165
    {
1165
    {
1166
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1166
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1167
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1167
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1168
    }
1168
    }
1169
    else
1169
    else
1170
    {
1170
    {
1171
        //For sprite textures, clamping looks better than wrapping
1171
        //For sprite textures, clamping looks better than wrapping
1172
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1172
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1173
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1173
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1174
    }
1174
    }
1175
1175
1176
    if (pic) free(pic);
1176
    if (pic) free(pic);
1177
1177
1178
    pth->picnum = dapic;
1178
    pth->picnum = dapic;
1179
    pth->palnum = dapal;
1179
    pth->palnum = dapal;
1180
    pth->effects = 0;
1180
    pth->effects = 0;
1181
    pth->flags = ((dameth&4)>>2) | (hasalpha<<3) | (hasfullbright<<4);
1181
    pth->flags = ((dameth&4)>>2) | (hasalpha<<3) | (hasfullbright<<4);
1182
    pth->hicr = NULL;
1182
    pth->hicr = NULL;
1183
1183
1184
    if ((hasfullbright) && (!fullbrightloadingpass))
1184
    if ((hasfullbright) && (!fullbrightloadingpass))
1185
    {
1185
    {
1186
        // load the ONLY texture that'll be assembled with the regular one to make the final texture with fullbright pixels
1186
        // load the ONLY texture that'll be assembled with the regular one to make the final texture with fullbright pixels
1187
        fullbrightloadingpass = 1;
1187
        fullbrightloadingpass = 1;
1188
        pth->ofb = (pthtyp *)calloc(1,sizeof(pthtyp));
1188
        pth->ofb = (pthtyp *)calloc(1,sizeof(pthtyp));
1189
        if (!pth->ofb) return 1;
1189
        if (!pth->ofb) return 1;
1190
        if (gloadtile_art(dapic, dapal, dameth, pth->ofb, 1)) return 1;
1190
        if (gloadtile_art(dapic, dapal, dameth, pth->ofb, 1)) return 1;
1191
1191
1192
        fullbrightloadingpass = 0;
1192
        fullbrightloadingpass = 0;
1193
    }
1193
    }
1194
    return 0;
1194
    return 0;
1195
}
1195
}
1196
1196
1197
// JONOF'S COMPRESSED TEXTURE CACHE STUFF ---------------------------------------------------
1197
// JONOF'S COMPRESSED TEXTURE CACHE STUFF ---------------------------------------------------
1198
static inline void phex(unsigned char v, char *s)
1198
static inline void phex(unsigned char v, char *s)
1199
{
1199
{
1200
    int x;
1200
    int x;
1201
    x = v>>4;
1201
    x = v>>4;
1202
    s[0] = x<10 ? (x+'0') : (x-10+'a');
1202
    s[0] = x<10 ? (x+'0') : (x-10+'a');
1203
    x = v&15;
1203
    x = v&15;
1204
    s[1] = x<10 ? (x+'0') : (x-10+'a');
1204
    s[1] = x<10 ? (x+'0') : (x-10+'a');
1205
}
1205
}
1206
1206
1207
int trytexcache(char *fn, int len, int dameth, char effect, texcacheheader *head)
1207
int trytexcache(char *fn, int len, int dameth, char effect, texcacheheader *head)
1208
{
1208
{
1209
    int fil, fp;
1209
    int fil, fp;
1210
    char cachefn[BMAX_PATH], *cp;
1210
    char cachefn[BMAX_PATH], *cp;
1211
    unsigned char mdsum[16];
1211
    unsigned char mdsum[16];
1212
1212
1213
    if (!glinfo.texcompr || !glusetexcompr || !glusetexcache) return -1;
1213
    if (!glinfo.texcompr || !glusetexcompr || !glusetexcache) return -1;
1214
    if (!bglCompressedTexImage2DARB || !bglGetCompressedTexImageARB)
1214
    if (!bglCompressedTexImage2DARB || !bglGetCompressedTexImageARB)
1215
    {
1215
    {
1216
        // lacking the necessary extensions to do this
1216
        // lacking the necessary extensions to do this
1217
        initprintf("Warning: the GL driver lacks necessary functions to use caching\n");
1217
        initprintf("Warning: the GL driver lacks necessary functions to use caching\n");
1218
        glusetexcache = 0;
1218
        glusetexcache = 0;
1219
        return -1;
1219
        return -1;
1220
    }
1220
    }
1221
1221
1222
    md4once((unsigned char *)fn, strlen(fn), mdsum);
1222
    md4once((unsigned char *)fn, strlen(fn), mdsum);
1223
    for (cp = cachefn, fp = 0; (*cp = TEXCACHEDIR[fp]); cp++,fp++);
1223
    for (cp = cachefn, fp = 0; (*cp = TEXCACHEDIR[fp]); cp++,fp++);
1224
    *(cp++) = '/';
1224
    *(cp++) = '/';
1225
    for (fp = 0; fp < 16; phex(mdsum[fp++], cp), cp+=2);
1225
    for (fp = 0; fp < 16; phex(mdsum[fp++], cp), cp+=2);
1226
    sprintf(cp, "-%x-%x%x", len, dameth, effect);
1226
    sprintf(cp, "-%x-%x%x", len, dameth, effect);
1227
1227
1228
    fil = kopen4load(cachefn, 0);
1228
    fil = kopen4load(cachefn, 0);
1229
    if (fil < 0) return -1;
1229
    if (fil < 0) return -1;
1230
1230
1231
    /* initprintf("Loading cached tex: %s\n", cachefn); */
1231
    /* initprintf("Loading cached tex: %s\n", cachefn); */
1232
1232
1233
    if (kread(fil, head, sizeof(texcacheheader)) < (int)sizeof(texcacheheader)) goto failure;
1233
    if (kread(fil, head, sizeof(texcacheheader)) < (int)sizeof(texcacheheader)) goto failure;
1234
    if (memcmp(head->magic, "Polymost", 8)) goto failure;
1234
    if (memcmp(head->magic, "Polymost", 8)) goto failure;
1235
1235
1236
    head->xdim = B_LITTLE32(head->xdim);
1236
    head->xdim = B_LITTLE32(head->xdim);
1237
    head->ydim = B_LITTLE32(head->ydim);
1237
    head->ydim = B_LITTLE32(head->ydim);
1238
    head->flags = B_LITTLE32(head->flags);
1238
    head->flags = B_LITTLE32(head->flags);
1239
1239
1240
    if (gltexmaxsize && (head->xdim > (1<<gltexmaxsize) || head->ydim > (1<<gltexmaxsize))) goto failure;
1240
    if (gltexmaxsize && (head->xdim > (1<<gltexmaxsize) || head->ydim > (1<<gltexmaxsize))) goto failure;
1241
    if (!glinfo.texnpot && (head->flags & 1)) goto failure;
1241
    if (!glinfo.texnpot && (head->flags & 1)) goto failure;
1242
1242
1243
    return fil;
1243
    return fil;
1244
failure:
1244
failure:
1245
    kclose(fil);
1245
    kclose(fil);
1246
    return -1;
1246
    return -1;
1247
}
1247
}
1248
1248
1249
void writexcache(char *fn, int len, int dameth, char effect, texcacheheader *head)
1249
void writexcache(char *fn, int len, int dameth, char effect, texcacheheader *head)
1250
{
1250
{
1251
    int fil=-1, fp;
1251
    int fil=-1, fp;
1252
    char cachefn[BMAX_PATH], *cp;
1252
    char cachefn[BMAX_PATH], *cp;
1253
    unsigned char mdsum[16];
1253
    unsigned char mdsum[16];
1254
    texcachepicture pict;
1254
    texcachepicture pict;
1255
    char *pic = NULL, *packbuf = NULL;
1255
    char *pic = NULL, *packbuf = NULL;
1256
    void *midbuf = NULL;
1256
    void *midbuf = NULL;
1257
    unsigned int alloclen=0, level, miplen;
1257
    unsigned int alloclen=0, level, miplen;
1258
    unsigned int padx=0, pady=0;
1258
    unsigned int padx=0, pady=0;
1259
    GLuint gi;
1259
    GLuint gi;
1260
1260
1261
    if (!glinfo.texcompr || !glusetexcompr || !glusetexcache) {initprintf("\n");return;}
1261
    if (!glinfo.texcompr || !glusetexcompr || !glusetexcache) {initprintf("\n");return;}
1262
    if (!bglCompressedTexImage2DARB || !bglGetCompressedTexImageARB)
1262
    if (!bglCompressedTexImage2DARB || !bglGetCompressedTexImageARB)
1263
    {
1263
    {
1264
        // lacking the necessary extensions to do this
1264
        // lacking the necessary extensions to do this
1265
        initprintf("Warning: the GL driver lacks necessary functions to use caching\n");
1265
        initprintf("Warning: the GL driver lacks necessary functions to use caching\n");
1266
        glusetexcache = 0;
1266
        glusetexcache = 0;
1267
        return;
1267
        return;
1268
    }
1268
    }
1269
1269
1270
    {
1270
    {
1271
        struct stat st;
1271
        struct stat st;
1272
        if (stat(TEXCACHEDIR, &st) < 0)
1272
        if (stat(TEXCACHEDIR, &st) < 0)
1273
        {
1273
        {
1274
            if (errno == ENOENT)     // path doesn't exist
1274
            if (errno == ENOENT)     // path doesn't exist
1275
            {
1275
            {
1276
                // try to create the cache directory
1276
                // try to create the cache directory
1277
                if (Bmkdir(TEXCACHEDIR, S_IRWXU) < 0)
1277
                if (Bmkdir(TEXCACHEDIR, S_IRWXU) < 0)
1278
                {
1278
                {
1279
                    initprintf("Failed to create texture cache directory %s\n", TEXCACHEDIR);
1279
                    initprintf("Failed to create texture cache directory %s\n", TEXCACHEDIR);
1280
                    glusetexcache = 0;
1280
                    glusetexcache = 0;
1281
                    return;
1281
                    return;
1282
                }
1282
                }
1283
                else initprintf("Created texture cache directory %s\n", TEXCACHEDIR);
1283
                else initprintf("Created texture cache directory %s\n", TEXCACHEDIR);
1284
            }
1284
            }
1285
            else
1285
            else
1286
            {
1286
            {
1287
                // another type of failure
1287
                // another type of failure
1288
                glusetexcache = 0;
1288
                glusetexcache = 0;
1289
                return;
1289
                return;
1290
            }
1290
            }
1291
        }
1291
        }
1292
        else if ((st.st_mode & S_IFDIR) != S_IFDIR)
1292
        else if ((st.st_mode & S_IFDIR) != S_IFDIR)
1293
        {
1293
        {
1294
            // cache directory isn't a directory
1294
            // cache directory isn't a directory
1295
            glusetexcache = 0;
1295
            glusetexcache = 0;
1296
            return;
1296
            return;
1297
        }
1297
        }
1298
    }
1298
    }
1299
1299
1300
    gi = GL_FALSE;
1300
    gi = GL_FALSE;
1301
    bglGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, (GLint *)&gi);
1301
    bglGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, (GLint *)&gi);
1302
    if (gi != GL_TRUE) return;
1302
    if (gi != GL_TRUE) return;
1303
1303
1304
    md4once((unsigned char *)fn, strlen(fn), mdsum);
1304
    md4once((unsigned char *)fn, strlen(fn), mdsum);
1305
    for (cp = cachefn, fp = 0; (*cp = TEXCACHEDIR[fp]); cp++,fp++);
1305
    for (cp = cachefn, fp = 0; (*cp = TEXCACHEDIR[fp]); cp++,fp++);
1306
    *(cp++) = '/';
1306
    *(cp++) = '/';
1307
    for (fp = 0; fp < 16; phex(mdsum[fp++], cp), cp+=2);
1307
    for (fp = 0; fp < 16; phex(mdsum[fp++], cp), cp+=2);
1308
    sprintf(cp, "-%x-%x%x", len, dameth, effect);
1308
    sprintf(cp, "-%x-%x%x", len, dameth, effect);
1309
1309
1310
    initprintf("Writing cached tex: %s\n", cachefn);
1310
    initprintf("Writing cached tex: %s\n", cachefn);
1311
1311
1312
    fil = Bopen(cachefn,BO_BINARY|BO_CREAT|BO_TRUNC|BO_RDWR,BS_IREAD|BS_IWRITE);
1312
    fil = Bopen(cachefn,BO_BINARY|BO_CREAT|BO_TRUNC|BO_RDWR,BS_IREAD|BS_IWRITE);
1313
    if (fil < 0) return;
1313
    if (fil < 0) return;
1314
1314
1315
    memcpy(head->magic, "Polymost", 8);   // sizes are set by caller
1315
    memcpy(head->magic, "Polymost", 8);   // sizes are set by caller
1316
1316
1317
    if (glusetexcachecompression) head->flags |= 4;
1317
    if (glusetexcachecompression) head->flags |= 4;
1318
1318
1319
    head->xdim = B_LITTLE32(head->xdim);
1319
    head->xdim = B_LITTLE32(head->xdim);
1320
    head->ydim = B_LITTLE32(head->ydim);
1320
    head->ydim = B_LITTLE32(head->ydim);
1321
    head->flags = B_LITTLE32(head->flags);
1321
    head->flags = B_LITTLE32(head->flags);
1322
1322
1323
    if (Bwrite(fil, head, sizeof(texcacheheader)) != sizeof(texcacheheader)) goto failure;
1323
    if (Bwrite(fil, head, sizeof(texcacheheader)) != sizeof(texcacheheader)) goto failure;
1324
1324
1325
    bglGetError();
1325
    bglGetError();
1326
    for (level = 0; level==0 || (padx > 1 || pady > 1); level++)
1326
    for (level = 0; level==0 || (padx > 1 || pady > 1); level++)
1327
    {
1327
    {
1328
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_ARB, (GLint *)&gi);
1328
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_ARB, (GLint *)&gi);
1329
        if (bglGetError() != GL_NO_ERROR) goto failure;
1329
        if (bglGetError() != GL_NO_ERROR) goto failure;
1330
        if (gi != GL_TRUE) goto failure;   // an uncompressed mipmap
1330
        if (gi != GL_TRUE) goto failure;   // an uncompressed mipmap
1331
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&gi);
1331
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&gi);
1332
        if (bglGetError() != GL_NO_ERROR) goto failure;
1332
        if (bglGetError() != GL_NO_ERROR) goto failure;
1333
        pict.format = B_LITTLE32(gi);
1333
        pict.format = B_LITTLE32(gi);
1334
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, (GLint *)&gi);
1334
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, (GLint *)&gi);
1335
        if (bglGetError() != GL_NO_ERROR) goto failure;
1335
        if (bglGetError() != GL_NO_ERROR) goto failure;
1336
        padx = gi; pict.xdim = B_LITTLE32(gi);
1336
        padx = gi; pict.xdim = B_LITTLE32(gi);
1337
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, (GLint *)&gi);
1337
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, (GLint *)&gi);
1338
        if (bglGetError() != GL_NO_ERROR) goto failure;
1338
        if (bglGetError() != GL_NO_ERROR) goto failure;
1339
        pady = gi; pict.ydim = B_LITTLE32(gi);
1339
        pady = gi; pict.ydim = B_LITTLE32(gi);
1340
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_BORDER, (GLint *)&gi);
1340
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_BORDER, (GLint *)&gi);
1341
        if (bglGetError() != GL_NO_ERROR) goto failure;
1341
        if (bglGetError() != GL_NO_ERROR) goto failure;
1342
        pict.border = B_LITTLE32(gi);
1342
        pict.border = B_LITTLE32(gi);
1343
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_DEPTH, (GLint *)&gi);
1343
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_DEPTH, (GLint *)&gi);
1344
        if (bglGetError() != GL_NO_ERROR) goto failure;
1344
        if (bglGetError() != GL_NO_ERROR) goto failure;
1345
        pict.depth = B_LITTLE32(gi);
1345
        pict.depth = B_LITTLE32(gi);
1346
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint *)&gi);
1346
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint *)&gi);
1347
        if (bglGetError() != GL_NO_ERROR) goto failure;
1347
        if (bglGetError() != GL_NO_ERROR) goto failure;
1348
        miplen = (int)gi; pict.size = B_LITTLE32(gi);
1348
        miplen = (int)gi; pict.size = B_LITTLE32(gi);
1349
1349
1350
        if (alloclen < miplen)
1350
        if (alloclen < miplen)
1351
        {
1351
        {
1352
            void *picc = realloc(pic, miplen);
1352
            void *picc = realloc(pic, miplen);
1353
            if (!picc) goto failure; else pic = picc;
1353
            if (!picc) goto failure; else pic = picc;
1354
            alloclen = miplen;
1354
            alloclen = miplen;
1355
1355
1356
            picc = realloc(packbuf, alloclen+16);
1356
            picc = realloc(packbuf, alloclen+16);
1357
            if (!picc) goto failure; else packbuf = picc;
1357
            if (!picc) goto failure; else packbuf = picc;
1358
1358
1359
            picc = realloc(midbuf, miplen);
1359
            picc = realloc(midbuf, miplen);
1360
            if (!picc) goto failure; else midbuf = picc;
1360
            if (!picc) goto failure; else midbuf = picc;
1361
        }
1361
        }
1362
1362
1363
        bglGetCompressedTexImageARB(GL_TEXTURE_2D, level, pic);
1363
        bglGetCompressedTexImageARB(GL_TEXTURE_2D, level, pic);
1364
        if (bglGetError() != GL_NO_ERROR) goto failure;
1364
        if (bglGetError() != GL_NO_ERROR) goto failure;
1365
1365
1366
        if (Bwrite(fil, &pict, sizeof(texcachepicture)) != sizeof(texcachepicture)) goto failure;
1366
        if (Bwrite(fil, &pict, sizeof(texcachepicture)) != sizeof(texcachepicture)) goto failure;
1367
        if (dxtfilter(fil, &pict, pic, midbuf, packbuf, miplen)) goto failure;
1367
        if (dxtfilter(fil, &pict, pic, midbuf, packbuf, miplen)) goto failure;
1368
    }
1368
    }
1369
1369
1370
failure:
1370
failure:
1371
    if (fil>=0) Bclose(fil);
1371
    if (fil>=0) Bclose(fil);
1372
    if (midbuf) free(midbuf);
1372
    if (midbuf) free(midbuf);
1373
    if (pic) free(pic);
1373
    if (pic) free(pic);
1374
    if (packbuf) free(packbuf);
1374
    if (packbuf) free(packbuf);
1375
}
1375
}
1376
1376
1377
int gloadtile_cached(int fil, texcacheheader *head, int *doalloc, pthtyp *pth,int dapalnum)
1377
int gloadtile_cached(int fil, texcacheheader *head, int *doalloc, pthtyp *pth,int dapalnum)
1378
{
1378
{
1379
    int level, r;
1379
    int level, r;
1380
    texcachepicture pict;
1380
    texcachepicture pict;
1381
    char *pic = NULL, *packbuf = NULL;
1381
    char *pic = NULL, *packbuf = NULL;
1382
    void *midbuf = NULL;
1382
    void *midbuf = NULL;
1383
    int alloclen=0;
1383
    int alloclen=0;
1384
1384
1385
    UNREFERENCED_PARAMETER(dapalnum);
1385
    UNREFERENCED_PARAMETER(dapalnum);
1386
1386
1387
    if (*doalloc&1)
1387
    if (*doalloc&1)
1388
    {
1388
    {
1389
        bglGenTextures(1,(GLuint*)&pth->glpic);  //# of textures (make OpenGL allocate structure)
1389
        bglGenTextures(1,(GLuint*)&pth->glpic);  //# of textures (make OpenGL allocate structure)
1390
        *doalloc |= 2;   // prevents bglGenTextures being called again if we fail in here
1390
        *doalloc |= 2;   // prevents bglGenTextures being called again if we fail in here
1391
    }
1391
    }
1392
    bglBindTexture(GL_TEXTURE_2D,pth->glpic);
1392
    bglBindTexture(GL_TEXTURE_2D,pth->glpic);
1393
1393
1394
    pth->sizx = head->xdim;
1394
    pth->sizx = head->xdim;
1395
    pth->sizy = head->ydim;
1395
    pth->sizy = head->ydim;
1396
1396
1397
    bglGetError();
1397
    bglGetError();
1398
1398
1399
    // load the mipmaps
1399
    // load the mipmaps
1400
    for (level = 0; level==0 || (pict.xdim > 1 || pict.ydim > 1); level++)
1400
    for (level = 0; level==0 || (pict.xdim > 1 || pict.ydim > 1); level++)
1401
    {
1401
    {
1402
        r = kread(fil, &pict, sizeof(texcachepicture));
1402
        r = kread(fil, &pict, sizeof(texcachepicture));
1403
        if (r < (int)sizeof(texcachepicture)) goto failure;
1403
        if (r < (int)sizeof(texcachepicture)) goto failure;
1404
1404
1405
        pict.size = B_LITTLE32(pict.size);
1405
        pict.size = B_LITTLE32(pict.size);
1406
        pict.format = B_LITTLE32(pict.format);
1406
        pict.format = B_LITTLE32(pict.format);
1407
        pict.xdim = B_LITTLE32(pict.xdim);
1407
        pict.xdim = B_LITTLE32(pict.xdim);
1408
        pict.ydim = B_LITTLE32(pict.ydim);
1408
        pict.ydim = B_LITTLE32(pict.ydim);
1409
        pict.border = B_LITTLE32(pict.border);
1409
        pict.border = B_LITTLE32(pict.border);
1410
        pict.depth = B_LITTLE32(pict.depth);
1410
        pict.depth = B_LITTLE32(pict.depth);
1411
1411
1412
        if (alloclen < pict.size)
1412
        if (alloclen < pict.size)
1413
        {
1413
        {
1414
            void *picc = realloc(pic, pict.size);
1414
            void *picc = realloc(pic, pict.size);
1415
            if (!picc) goto failure; else pic = picc;
1415
            if (!picc) goto failure; else pic = picc;
1416
            alloclen = pict.size;
1416
            alloclen = pict.size;
1417
1417
1418
            picc = realloc(packbuf, alloclen+16);
1418
            picc = realloc(packbuf, alloclen+16);
1419
            if (!picc) goto failure; else packbuf = picc;
1419
            if (!picc) goto failure; else packbuf = picc;
1420
1420
1421
            picc = realloc(midbuf, pict.size);
1421
            picc = realloc(midbuf, pict.size);
1422
            if (!picc) goto failure; else midbuf = picc;
1422
            if (!picc) goto failure; else midbuf = picc;
1423
        }
1423
        }
1424
1424
1425
        if (dedxtfilter(fil, &pict, pic, midbuf, packbuf, (head->flags&4)==4)) goto failure;
1425
        if (dedxtfilter(fil, &pict, pic, midbuf, packbuf, (head->flags&4)==4)) goto failure;
1426
1426
1427
        bglCompressedTexImage2DARB(GL_TEXTURE_2D,level,pict.format,pict.xdim,pict.ydim,pict.border,
1427
        bglCompressedTexImage2DARB(GL_TEXTURE_2D,level,pict.format,pict.xdim,pict.ydim,pict.border,
1428
                                   pict.size,pic);
1428
                                   pict.size,pic);
1429
        if (bglGetError() != GL_NO_ERROR) goto failure;
1429
        if (bglGetError() != GL_NO_ERROR) goto failure;
1430
1430
1431
        {
1431
        {
1432
            GLint format;
1432
            GLint format;
1433
            bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, &format);
1433
            bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, &format);
1434
            if (bglGetError() != GL_NO_ERROR) goto failure;
1434
            if (bglGetError() != GL_NO_ERROR) goto failure;
1435
            format = B_LITTLE32(format);
1435
            format = B_LITTLE32(format);
1436
            if (pict.format != format)
1436
            if (pict.format != format)
1437
            {
1437
            {
1438
                initprintf("invalid texture cache file format %d %d\n",pict.format, format);
1438
                initprintf("invalid texture cache file format %d %d\n",pict.format, format);
1439
                goto failure;
1439
                goto failure;
1440
            }
1440
            }
1441
        }
1441
        }
1442
1442
1443
    }
1443
    }
1444
1444
1445
    if (midbuf) free(midbuf);
1445
    if (midbuf) free(midbuf);
1446
    if (pic) free(pic);
1446
    if (pic) free(pic);
1447
    if (packbuf) free(packbuf);
1447
    if (packbuf) free(packbuf);
1448
    return 0;
1448
    return 0;
1449
failure:
1449
failure:
1450
    if (midbuf) free(midbuf);
1450
    if (midbuf) free(midbuf);
1451
    if (pic) free(pic);
1451
    if (pic) free(pic);
1452
    if (packbuf) free(packbuf);
1452
    if (packbuf) free(packbuf);
1453
    return -1;
1453
    return -1;
1454
}
1454
}
1455
// --------------------------------------------------- JONOF'S COMPRESSED TEXTURE CACHE STUFF
1455
// --------------------------------------------------- JONOF'S COMPRESSED TEXTURE CACHE STUFF
1456
static void applypalmapsT(char *pic, int sizx, int sizy, int dapic,int dapalnum, int dameth)
1456
static void applypalmapsT(char *pic, int sizx, int sizy, int dapic,int dapalnum, int dameth)
1457
{
1457
{
1458
    //_initprintf("%d\n",pal);
1458
    //_initprintf("%d\n",pal);
1459
    int stage;
1459
    int stage;
1460
    pthtyp *pichead1=pichead;
1460
    pthtyp *pichead1=pichead;
1461
1461
1462
    for (stage=0;stage<MAXPALCONV;stage++)
1462
    for (stage=0;stage<MAXPALCONV;stage++)
1463
    {
1463
    {
1464
        int pal1=0,pal2=dapalnum;
1464
        int pal1=0,pal2=dapalnum;
1465
        pthtyp *pth;
1465
        pthtyp *pth;
1466
        getpalmap(&stage,&pal1,&pal2);
1466
        getpalmap(&stage,&pal1,&pal2);
1467
        if (!pal1)return;
1467
        if (!pal1)return;
1468
1468
1469
        //_initprintf("Pal: %d\n",pal1);
1469
        //_initprintf("Pal: %d\n",pal1);
1470
        if (hicfindsubst(dapic, pal1, 0))
1470
        if (hicfindsubst(dapic, pal1, 0))
1471
            gltexcache(dapic, pal1, dameth);
1471
            gltexcache(dapic, pal1, dameth);
1472
        for (pth=pichead1; pth; pth=pth->next)
1472
        for (pth=pichead1; pth; pth=pth->next)
1473
            if (pth->palnum ==pal1&&pth->palmap)break;
1473
            if (pth->palnum ==pal1&&pth->palmap)break;
1474
        if (!pth||pth->size!=sizx*sizy)continue;
1474
        if (!pth||pth->size!=sizx*sizy)continue;
1475
1475
1476
        applypalmap(pic,pth->palmap,pth->size,pal2);
1476
        applypalmap(pic,pth->palmap,pth->size,pal2);
1477
    }
1477
    }
1478
}
1478
}
1479
1479
1480
int gloadtile_hi(int dapic,int dapalnum, int facen, hicreplctyp *hicr, int dameth, pthtyp *pth, int doalloc, char effect)
1480
int gloadtile_hi(int dapic,int dapalnum, int facen, hicreplctyp *hicr, int dameth, pthtyp *pth, int doalloc, char effect)
1481
{
1481
{
1482
    coltype *pic = NULL, *rpptr;
1482
    coltype *pic = NULL, *rpptr;
1483
    int j, x, y, xsiz=0, ysiz=0, tsizx, tsizy;
1483
    int j, x, y, xsiz=0, ysiz=0, tsizx, tsizy;
1484
    int r, g, b;
1484
    int r, g, b;
1485
1485
1486
    char *picfil = NULL, *fn, hasalpha = 255;
1486
    char *picfil = NULL, *fn, hasalpha = 255;
1487
    int picfillen, texfmt = GL_RGBA, intexfmt = GL_RGBA, filh;
1487
    int picfillen, texfmt = GL_RGBA, intexfmt = GL_RGBA, filh;
1488
1488
1489
    int cachefil = -1;
1489
    int cachefil = -1;
1490
    texcacheheader cachead;
1490
    texcacheheader cachead;
1491
1491
1492
    if (!hicr) return -1;
1492
    if (!hicr) return -1;
1493
    if (facen > 0)
1493
    if (facen > 0)
1494
    {
1494
    {
1495
        if (!hicr->skybox) return -1;
1495
        if (!hicr->skybox) return -1;
1496
        if (facen > 6) return -1;
1496
        if (facen > 6) return -1;
1497
        if (!hicr->skybox->face[facen-1]) return -1;
1497
        if (!hicr->skybox->face[facen-1]) return -1;
1498
        fn = hicr->skybox->face[facen-1];
1498
        fn = hicr->skybox->face[facen-1];
1499
    }
1499
    }
1500
    else
1500
    else
1501
    {
1501
    {
1502
        if (!hicr->filename) return -1;
1502
        if (!hicr->filename) return -1;
1503
        fn = hicr->filename;
1503
        fn = hicr->filename;
1504
    }
1504
    }
1505
1505
1506
    if ((filh = kopen4load(fn, 0)) < 0)
1506
    if ((filh = kopen4load(fn, 0)) < 0)
1507
    {
1507
    {
1508
        initprintf("hightile: %s (pic %d) not found\n", fn, dapic);
1508
        initprintf("hightile: %s (pic %d) not found\n", fn, dapic);
1509
        if (facen > 0)
1509
        if (facen > 0)
1510
            hicr->skybox->ignore = 1;
1510
            hicr->skybox->ignore = 1;
1511
        else
1511
        else
1512
            hicr->ignore = 1;
1512
            hicr->ignore = 1;
1513
        return -1;
1513
        return -1;
1514
    }
1514
    }
1515
    picfillen = kfilelength(filh);
1515
    picfillen = kfilelength(filh);
1516
1516
1517
    kclose(filh);       // FIXME: shouldn't have to do this. bug in cache1d.c
1517
    kclose(filh);       // FIXME: shouldn't have to do this. bug in cache1d.c
1518
1518
1519
    cachefil = trytexcache(fn, picfillen+(dapalnum<<8), dameth, effect, &cachead);
1519
    cachefil = trytexcache(fn, picfillen+(dapalnum<<8), dameth, effect, &cachead);
1520
    if (cachefil >= 0 && !gloadtile_cached(cachefil, &cachead, &doalloc, pth, dapalnum))
1520
    if (cachefil >= 0 && !gloadtile_cached(cachefil, &cachead, &doalloc, pth, dapalnum))
1521
    {
1521
    {
1522
        tsizx = cachead.xdim;
1522
        tsizx = cachead.xdim;
1523
        tsizy = cachead.ydim;
1523
        tsizy = cachead.ydim;
1524
        hasalpha = (cachead.flags & 2) ? 0 : 255;
1524
        hasalpha = (cachead.flags & 2) ? 0 : 255;
1525
        kclose(cachefil);
1525
        kclose(cachefil);
1526
        //kclose(filh); // FIXME: uncomment when cache1d.c is fixed
1526
        //kclose(filh); // FIXME: uncomment when cache1d.c is fixed
1527
        // cachefil >= 0, so it won't be rewritten
1527
        // cachefil >= 0, so it won't be rewritten
1528
    }
1528
    }
1529
    else
1529
    else
1530
    {
1530
    {
1531
        if (cachefil >= 0) kclose(cachefil);
1531
        if (cachefil >= 0) kclose(cachefil);
1532
        cachefil = -1;  // the compressed version will be saved to disk
1532
        cachefil = -1;  // the compressed version will be saved to disk
1533
1533
1534
        if ((filh = kopen4load(fn, 0)) < 0) return -1;
1534
        if ((filh = kopen4load(fn, 0)) < 0) return -1;
1535
1535
1536
        picfil = (char *)malloc(picfillen); if (!picfil) { kclose(filh); return 1; }
1536
        picfil = (char *)malloc(picfillen); if (!picfil) { kclose(filh); return 1; }
1537
        kread(filh, picfil, picfillen);
1537
        kread(filh, picfil, picfillen);
1538
        kclose(filh);
1538
        kclose(filh);
1539
1539
1540
        // tsizx/y = replacement texture's natural size
1540
        // tsizx/y = replacement texture's natural size
1541
        // xsiz/y = 2^x size of replacement
1541
        // xsiz/y = 2^x size of replacement
1542
1542
1543
        kpgetdim(picfil,picfillen,&tsizx,&tsizy);
1543
        kpgetdim(picfil,picfillen,&tsizx,&tsizy);
1544
        if (tsizx == 0 || tsizy == 0) { free(picfil); return -1; }
1544
        if (tsizx == 0 || tsizy == 0) { free(picfil); return -1; }
1545
        pth->sizx = tsizx;
1545
        pth->sizx = tsizx;
1546
        pth->sizy = tsizy;
1546
        pth->sizy = tsizy;
1547
1547
1548
        if (!glinfo.texnpot)
1548
        if (!glinfo.texnpot)
1549
        {
1549
        {
1550
            for (xsiz=1;xsiz<tsizx;xsiz+=xsiz);
1550
            for (xsiz=1;xsiz<tsizx;xsiz+=xsiz);
1551
            for (ysiz=1;ysiz<tsizy;ysiz+=ysiz);
1551
            for (ysiz