2009-03-05 09:07:55 +00:00
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
*
|
2010-10-21 07:51:49 +00:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or (at
|
|
|
|
* your option) any later version.
|
2010-10-20 09:02:21 +00:00
|
|
|
*
|
2010-10-21 07:51:49 +00:00
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
2010-10-20 09:02:21 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*
|
|
|
|
* See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2010-10-21 07:51:49 +00:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
2010-10-20 09:02:21 +00:00
|
|
|
*
|
2010-10-21 07:51:49 +00:00
|
|
|
* =======================================================================
|
|
|
|
*
|
|
|
|
* Texture handling
|
|
|
|
*
|
|
|
|
* =======================================================================
|
2010-10-20 09:02:21 +00:00
|
|
|
*/
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
#include "header/local.h"
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
image_t gltextures[MAX_GLTEXTURES];
|
2010-10-20 09:02:21 +00:00
|
|
|
int numgltextures;
|
|
|
|
int base_textureid; /* gltextures[i] = base_textureid+i */
|
2010-10-21 07:29:20 +00:00
|
|
|
extern qboolean scrap_dirty;
|
2012-07-21 12:09:45 +00:00
|
|
|
extern byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH * BLOCK_HEIGHT];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
static byte intensitytable[256];
|
|
|
|
static unsigned char gammatable[256];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
cvar_t *intensity;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
unsigned d_8to24table[256];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
qboolean R_Upload8(byte *data, int width, int height,
|
|
|
|
qboolean mipmap, qboolean is_sky);
|
|
|
|
qboolean R_Upload32(unsigned *data, int width, int height, qboolean mipmap);
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
int gl_solid_format = 3;
|
|
|
|
int gl_alpha_format = 4;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
int gl_tex_solid_format = 3;
|
|
|
|
int gl_tex_alpha_format = 4;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
|
|
|
|
int gl_filter_max = GL_LINEAR;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
int Draw_GetPalette(void);
|
2010-10-21 07:51:49 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int minimize, maximize;
|
|
|
|
} glmode_t;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
glmode_t modes[] = {
|
2012-07-21 12:09:45 +00:00
|
|
|
{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
|
|
|
|
{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
|
|
|
|
{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
|
|
|
|
{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
|
|
|
|
{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
|
|
|
|
{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
|
2010-10-20 09:02:21 +00:00
|
|
|
};
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
#define NUM_GL_MODES (sizeof(modes) / sizeof(glmode_t))
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int mode;
|
|
|
|
} gltmode_t;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
gltmode_t gl_alpha_modes[] = {
|
2012-07-21 12:09:45 +00:00
|
|
|
{"default", 4},
|
|
|
|
{"GL_RGBA", GL_RGBA},
|
|
|
|
{"GL_RGBA8", GL_RGBA8},
|
|
|
|
{"GL_RGB5_A1", GL_RGB5_A1},
|
|
|
|
{"GL_RGBA4", GL_RGBA4},
|
|
|
|
{"GL_RGBA2", GL_RGBA2},
|
2010-10-20 09:02:21 +00:00
|
|
|
};
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
#define NUM_GL_ALPHA_MODES (sizeof(gl_alpha_modes) / sizeof(gltmode_t))
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
gltmode_t gl_solid_modes[] = {
|
2012-07-21 12:09:45 +00:00
|
|
|
{"default", 3},
|
|
|
|
{"GL_RGB", GL_RGB},
|
|
|
|
{"GL_RGB8", GL_RGB8},
|
|
|
|
{"GL_RGB5", GL_RGB5},
|
|
|
|
{"GL_RGB4", GL_RGB4},
|
|
|
|
{"GL_R3_G3_B2", GL_R3_G3_B2},
|
2012-06-04 09:46:08 +00:00
|
|
|
#ifdef GL_RGB2_EXT
|
2012-07-21 12:09:45 +00:00
|
|
|
{"GL_RGB2", GL_RGB2_EXT},
|
2012-06-04 09:46:08 +00:00
|
|
|
#endif
|
2010-10-20 09:02:21 +00:00
|
|
|
};
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
#define NUM_GL_SOLID_MODES (sizeof(gl_solid_modes) / sizeof(gltmode_t))
|
2010-10-21 07:51:49 +00:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
short x, y;
|
|
|
|
} floodfill_t;
|
|
|
|
|
|
|
|
/* must be a power of 2 */
|
|
|
|
#define FLOODFILL_FIFO_SIZE 0x1000
|
2012-07-21 12:09:45 +00:00
|
|
|
#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
|
2010-10-21 07:51:49 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
#define FLOODFILL_STEP(off, dx, dy) \
|
2010-10-21 07:51:49 +00:00
|
|
|
{ \
|
2012-07-21 12:09:45 +00:00
|
|
|
if (pos[off] == fillcolor) \
|
2010-10-21 07:51:49 +00:00
|
|
|
{ \
|
2012-07-21 12:09:45 +00:00
|
|
|
pos[off] = 255; \
|
|
|
|
fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
|
|
|
|
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
|
2010-10-21 07:51:49 +00:00
|
|
|
} \
|
2012-07-21 12:09:45 +00:00
|
|
|
else if (pos[off] != 255) \
|
2010-10-21 07:51:49 +00:00
|
|
|
{ \
|
2012-07-21 12:09:45 +00:00
|
|
|
fdc = pos[off]; \
|
|
|
|
} \
|
2010-10-21 07:51:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int upload_width, upload_height;
|
|
|
|
qboolean uploaded_paletted;
|
|
|
|
|
2010-10-25 12:55:59 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_SetTexturePalette(unsigned palette[256])
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
|
|
|
int i;
|
2012-07-21 12:09:45 +00:00
|
|
|
unsigned char temptable[768];
|
2010-10-25 12:55:59 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (qglColorTableEXT && gl_ext_palettedtexture->value)
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < 256; i++)
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
temptable[i * 3 + 0] = (palette[i] >> 0) & 0xff;
|
|
|
|
temptable[i * 3 + 1] = (palette[i] >> 8) & 0xff;
|
|
|
|
temptable[i * 3 + 2] = (palette[i] >> 16) & 0xff;
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB,
|
|
|
|
256, GL_RGB, GL_UNSIGNED_BYTE, temptable);
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-25 12:33:55 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_EnableMultitexture(qboolean enable)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!qglSelectTextureSGIS && !qglActiveTextureARB)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (enable)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
R_SelectTexture(QGL_TEXTURE1);
|
|
|
|
qglEnable(GL_TEXTURE_2D);
|
|
|
|
R_TexEnv(GL_REPLACE);
|
2010-10-25 12:33:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
R_SelectTexture(QGL_TEXTURE1);
|
|
|
|
qglDisable(GL_TEXTURE_2D);
|
|
|
|
R_TexEnv(GL_REPLACE);
|
2010-10-25 12:33:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
R_SelectTexture(QGL_TEXTURE0);
|
|
|
|
R_TexEnv(GL_REPLACE);
|
2010-10-25 12:33:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_SelectTexture(GLenum texture)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
|
|
|
int tmu;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!qglSelectTextureSGIS && !qglActiveTextureARB)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (texture == QGL_TEXTURE0)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
|
|
|
tmu = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmu = 1;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (tmu == gl_state.currenttmu)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gl_state.currenttmu = tmu;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (qglSelectTextureSGIS)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglSelectTextureSGIS(texture);
|
2010-10-25 12:33:55 +00:00
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
else if (qglActiveTextureARB)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglActiveTextureARB(texture);
|
|
|
|
qglClientActiveTextureARB(texture);
|
2010-10-25 12:33:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_TexEnv(GLenum mode)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
static int lastmodes[2] = {-1, -1};
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (mode != lastmodes[gl_state.currenttmu])
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
|
|
|
|
lastmodes[gl_state.currenttmu] = mode;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_Bind(int texnum)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
extern image_t *draw_chars;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (gl_nobind->value && draw_chars) /* performance evaluation option */
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
texnum = draw_chars->texnum;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (gl_state.currenttextures[gl_state.currenttmu] == texnum)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
gl_state.currenttextures[gl_state.currenttmu] = texnum;
|
|
|
|
qglBindTexture(GL_TEXTURE_2D, texnum);
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_MBind(GLenum target, int texnum)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
R_SelectTexture(target);
|
2010-10-25 12:33:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (target == QGL_TEXTURE0)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (gl_state.currenttextures[0] == texnum)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (gl_state.currenttextures[1] == texnum)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
R_Bind(texnum);
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-25 12:33:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_TextureMode(char *string)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i;
|
|
|
|
image_t *glt;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < NUM_GL_MODES; i++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!Q_stricmp(modes[i].name, string))
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
break;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (i == NUM_GL_MODES)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "bad filter name\n");
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
gl_filter_min = modes[i].minimize;
|
|
|
|
gl_filter_max = modes[i].maximize;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2011-10-17 10:43:48 +00:00
|
|
|
/* clamp selected anisotropy */
|
|
|
|
if (gl_config.anisotropic)
|
|
|
|
{
|
|
|
|
if (gl_anisotropic->value > gl_config.max_anisotropy)
|
|
|
|
{
|
|
|
|
ri.Cvar_SetValue("gl_anisotropic", gl_config.max_anisotropy);
|
|
|
|
}
|
|
|
|
else if (gl_anisotropic->value < 1.0)
|
|
|
|
{
|
|
|
|
ri.Cvar_SetValue("gl_anisotropic", 1.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* change all the existing mipmap texture objects */
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0, glt = gltextures; i < numgltextures; i++, glt++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if ((glt->type != it_pic) && (glt->type != it_sky))
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
R_Bind(glt->texnum);
|
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
|
|
|
gl_filter_min);
|
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
|
|
|
gl_filter_max);
|
2011-10-17 10:43:48 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
/* Set anisotropic filter if supported and enabled */
|
2011-10-17 10:43:48 +00:00
|
|
|
if (gl_config.anisotropic && gl_anisotropic->value)
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
|
|
|
gl_anisotropic->value);
|
2011-10-17 10:43:48 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_TextureAlphaMode(char *string)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < NUM_GL_ALPHA_MODES; i++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!Q_stricmp(gl_alpha_modes[i].name, string))
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
break;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (i == NUM_GL_ALPHA_MODES)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "bad alpha texture mode name\n");
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
gl_tex_alpha_format = gl_alpha_modes[i].mode;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_TextureSolidMode(char *string)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < NUM_GL_SOLID_MODES; i++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!Q_stricmp(gl_solid_modes[i].name, string))
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
break;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (i == NUM_GL_SOLID_MODES)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "bad solid texture mode name\n");
|
2009-03-05 09:07:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
gl_tex_solid_format = gl_solid_modes[i].mode;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_ImageList_f(void)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i;
|
|
|
|
image_t *image;
|
|
|
|
int texels;
|
2012-07-21 12:09:45 +00:00
|
|
|
const char *palstrings[2] = {
|
2009-03-05 09:07:55 +00:00
|
|
|
"RGB",
|
|
|
|
"PAL"
|
|
|
|
};
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "------------------\n");
|
2009-03-05 09:07:55 +00:00
|
|
|
texels = 0;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (image->texnum <= 0)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
continue;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
texels += image->upload_width * image->upload_height;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
switch (image->type)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
case it_skin:
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "M");
|
2010-10-20 09:02:21 +00:00
|
|
|
break;
|
|
|
|
case it_sprite:
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "S");
|
2010-10-20 09:02:21 +00:00
|
|
|
break;
|
|
|
|
case it_wall:
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "W");
|
2010-10-20 09:02:21 +00:00
|
|
|
break;
|
|
|
|
case it_pic:
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "P");
|
2010-10-20 09:02:21 +00:00
|
|
|
break;
|
|
|
|
default:
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, " ");
|
2010-10-20 09:02:21 +00:00
|
|
|
break;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, " %3i %3i %s: %s\n",
|
|
|
|
image->upload_width, image->upload_height,
|
|
|
|
palstrings[image->paletted], image->name);
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL,
|
|
|
|
"Total texel count (not counting mipmaps): %i\n",
|
|
|
|
texels);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Fill background pixels so mipmapping doesn't have haloes
|
|
|
|
*/
|
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_FloodFillSkin(byte *skin, int skinwidth, int skinheight)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
byte fillcolor = *skin; /* assume this is the pixel to fill */
|
2012-07-21 12:09:45 +00:00
|
|
|
floodfill_t fifo[FLOODFILL_FIFO_SIZE];
|
2010-10-20 09:02:21 +00:00
|
|
|
int inpt = 0, outpt = 0;
|
|
|
|
int filledcolor = -1;
|
|
|
|
int i;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (filledcolor == -1)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
filledcolor = 0;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
|
|
|
/* attempt to find opaque black */
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < 256; ++i)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (LittleLong(d_8to24table[i]) == (255 << 0)) /* alpha 1.0 */
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
filledcolor = i;
|
|
|
|
break;
|
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* can't fill to filled color or to transparent color (used as visited marker) */
|
2012-07-21 12:09:45 +00:00
|
|
|
if ((fillcolor == filledcolor) || (fillcolor == 255))
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
fifo[inpt].x = 0, fifo[inpt].y = 0;
|
|
|
|
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
while (outpt != inpt)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
int x = fifo[outpt].x, y = fifo[outpt].y;
|
2010-10-20 09:02:21 +00:00
|
|
|
int fdc = filledcolor;
|
2012-07-21 12:09:45 +00:00
|
|
|
byte *pos = &skin[x + skinwidth * y];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (x > 0)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
FLOODFILL_STEP(-1, -1, 0);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (x < skinwidth - 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
FLOODFILL_STEP(1, 1, 0);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (y > 0)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
FLOODFILL_STEP(-skinwidth, 0, -1);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (y < skinheight - 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
FLOODFILL_STEP(skinwidth, 0, 1);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
skin[x + skinwidth * y] = fdc;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_ResampleTexture(unsigned *in, int inwidth, int inheight,
|
|
|
|
unsigned *out, int outwidth, int outheight)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i, j;
|
|
|
|
unsigned *inrow, *inrow2;
|
|
|
|
unsigned frac, fracstep;
|
2012-07-21 12:09:45 +00:00
|
|
|
unsigned p1[1024], p2[1024];
|
2010-10-20 09:02:21 +00:00
|
|
|
byte *pix1, *pix2, *pix3, *pix4;
|
|
|
|
|
|
|
|
fracstep = inwidth * 0x10000 / outwidth;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
frac = fracstep >> 2;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < outwidth; i++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p1[i] = 4 * (frac >> 16);
|
2009-03-05 09:07:55 +00:00
|
|
|
frac += fracstep;
|
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
frac = 3 * (fracstep >> 2);
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < outwidth; i++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p2[i] = 4 * (frac >> 16);
|
2009-03-05 09:07:55 +00:00
|
|
|
frac += fracstep;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < outheight; i++, out += outwidth)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
inrow = in + inwidth * (int)((i + 0.25) * inheight / outheight);
|
|
|
|
inrow2 = in + inwidth * (int)((i + 0.75) * inheight / outheight);
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (j = 0; j < outwidth; j++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
pix1 = (byte *)inrow + p1[j];
|
|
|
|
pix2 = (byte *)inrow + p2[j];
|
|
|
|
pix3 = (byte *)inrow2 + p1[j];
|
|
|
|
pix4 = (byte *)inrow2 + p2[j];
|
|
|
|
((byte *)(out + j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2;
|
|
|
|
((byte *)(out + j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2;
|
|
|
|
((byte *)(out + j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2;
|
|
|
|
((byte *)(out + j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Scale up the pixel values in a
|
|
|
|
* texture to increase the
|
|
|
|
* lighting range
|
|
|
|
*/
|
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_LightScaleTexture(unsigned *in, int inwidth,
|
|
|
|
int inheight, qboolean only_gamma)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (only_gamma)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i, c;
|
2012-07-21 12:09:45 +00:00
|
|
|
byte *p;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
p = (byte *)in;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
c = inwidth * inheight;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < c; i++, p += 4)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p[0] = gammatable[p[0]];
|
|
|
|
p[1] = gammatable[p[1]];
|
|
|
|
p[2] = gammatable[p[2]];
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i, c;
|
2012-07-21 12:09:45 +00:00
|
|
|
byte *p;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
p = (byte *)in;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
c = inwidth * inheight;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < c; i++, p += 4)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p[0] = gammatable[intensitytable[p[0]]];
|
|
|
|
p[1] = gammatable[intensitytable[p[1]]];
|
|
|
|
p[2] = gammatable[intensitytable[p[2]]];
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Operates in place, quartering the size of the texture
|
|
|
|
*/
|
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_MipMap(byte *in, int width, int height)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i, j;
|
2012-07-21 12:09:45 +00:00
|
|
|
byte *out;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
width <<= 2;
|
2009-03-05 09:07:55 +00:00
|
|
|
height >>= 1;
|
|
|
|
out = in;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < height; i++, in += width)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
for (j = 0; j < width; j += 8, out += 4, in += 8)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
out[0] = (in[0] + in[4] + in[width + 0] + in[width + 4]) >> 2;
|
|
|
|
out[1] = (in[1] + in[5] + in[width + 1] + in[width + 5]) >> 2;
|
|
|
|
out[2] = (in[2] + in[6] + in[width + 2] + in[width + 6]) >> 2;
|
|
|
|
out[3] = (in[3] + in[7] + in[width + 3] + in[width + 7]) >> 2;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Returns has_alpha
|
|
|
|
*/
|
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_BuildPalettedTexture(unsigned char *paletted_texture, unsigned char *scaled,
|
|
|
|
int scaled_width, int scaled_height)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < scaled_width * scaled_height; i++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
unsigned int r, g, b, c;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
r = (scaled[0] >> 3) & 31;
|
|
|
|
g = (scaled[1] >> 2) & 63;
|
|
|
|
b = (scaled[2] >> 3) & 31;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
c = r | (g << 5) | (b << 11);
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
paletted_texture[i] = gl_state.d_16to8table[c];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
scaled += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
qboolean
|
2012-07-21 12:09:45 +00:00
|
|
|
R_Upload32(unsigned *data, int width, int height, qboolean mipmap)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int samples;
|
2012-07-21 12:09:45 +00:00
|
|
|
unsigned scaled[256 * 256];
|
|
|
|
unsigned char paletted_texture[256 * 256];
|
2010-10-20 09:02:21 +00:00
|
|
|
int scaled_width, scaled_height;
|
|
|
|
int i, c;
|
2012-07-21 12:09:45 +00:00
|
|
|
byte *scan;
|
2009-03-05 09:07:55 +00:00
|
|
|
int comp;
|
|
|
|
|
|
|
|
uploaded_paletted = false;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (scaled_width = 1; scaled_width < width; scaled_width <<= 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (gl_round_down->value && (scaled_width > width) && mipmap)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_width >>= 1;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (scaled_height = 1; scaled_height < height; scaled_height <<= 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (gl_round_down->value && (scaled_height > height) && mipmap)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_height >>= 1;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* let people sample down the world textures for speed */
|
2012-07-21 12:09:45 +00:00
|
|
|
if (mipmap)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
scaled_width >>= (int)gl_picmip->value;
|
|
|
|
scaled_height >>= (int)gl_picmip->value;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* don't ever bother with >256 textures */
|
2012-07-21 12:09:45 +00:00
|
|
|
if (scaled_width > 256)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_width = 256;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (scaled_height > 256)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_height = 256;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (scaled_width < 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_width = 1;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (scaled_height < 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_height = 1;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
upload_width = scaled_width;
|
|
|
|
upload_height = scaled_height;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (scaled_width * scaled_height > sizeof(scaled) / 4)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Sys_Error(ERR_DROP, "R_Upload32: too big");
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* scan the texture for any non-255 alpha */
|
|
|
|
c = width * height;
|
2012-07-21 12:09:45 +00:00
|
|
|
scan = ((byte *)data) + 3;
|
2009-03-05 09:07:55 +00:00
|
|
|
samples = gl_solid_format;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < c; i++, scan += 4)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (*scan != 255)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
samples = gl_alpha_format;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (samples == gl_solid_format)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
comp = gl_tex_solid_format;
|
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
else if (samples == gl_alpha_format)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
comp = gl_tex_alpha_format;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_ALL, "Unknown number of texture components %i\n",
|
|
|
|
samples);
|
2010-10-20 09:02:21 +00:00
|
|
|
comp = samples;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if ((scaled_width == width) && (scaled_height == height))
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!mipmap)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (qglColorTableEXT && gl_ext_palettedtexture->value &&
|
|
|
|
(samples == gl_solid_format))
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
|
|
|
uploaded_paletted = true;
|
2012-07-21 12:09:45 +00:00
|
|
|
R_BuildPalettedTexture(paletted_texture, (unsigned char *)data,
|
|
|
|
scaled_width, scaled_height);
|
|
|
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
|
|
|
|
scaled_width, scaled_height, 0, GL_COLOR_INDEX,
|
|
|
|
GL_UNSIGNED_BYTE, paletted_texture);
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexImage2D(GL_TEXTURE_2D, 0, comp, scaled_width,
|
|
|
|
scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
|
|
|
data);
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
memcpy(scaled, data, width * height * 4);
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
else
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
R_ResampleTexture(data, width, height, scaled,
|
|
|
|
scaled_width, scaled_height);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
R_LightScaleTexture(scaled, scaled_width, scaled_height, !mipmap);
|
2010-10-25 12:55:59 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (qglColorTableEXT && gl_ext_palettedtexture->value &&
|
|
|
|
(samples == gl_solid_format))
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
|
|
|
uploaded_paletted = true;
|
2012-07-21 12:09:45 +00:00
|
|
|
R_BuildPalettedTexture(paletted_texture, (unsigned char *)scaled,
|
|
|
|
scaled_width, scaled_height);
|
|
|
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
|
|
|
|
scaled_width, scaled_height, 0, GL_COLOR_INDEX,
|
|
|
|
GL_UNSIGNED_BYTE, paletted_texture);
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexImage2D(GL_TEXTURE_2D, 0, comp, scaled_width,
|
|
|
|
scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
|
|
|
scaled);
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (mipmap)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int miplevel;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
miplevel = 0;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
while (scaled_width > 1 || scaled_height > 1)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
R_MipMap((byte *)scaled, scaled_width, scaled_height);
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_width >>= 1;
|
|
|
|
scaled_height >>= 1;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (scaled_width < 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_width = 1;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (scaled_height < 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
scaled_height = 1;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
miplevel++;
|
2010-10-25 12:55:59 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (qglColorTableEXT && gl_ext_palettedtexture->value &&
|
|
|
|
(samples == gl_solid_format))
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
|
|
|
uploaded_paletted = true;
|
2012-07-21 12:09:45 +00:00
|
|
|
R_BuildPalettedTexture(paletted_texture, (unsigned char *)scaled,
|
|
|
|
scaled_width, scaled_height);
|
|
|
|
qglTexImage2D(GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT,
|
|
|
|
scaled_width, scaled_height, 0, GL_COLOR_INDEX,
|
|
|
|
GL_UNSIGNED_BYTE, paletted_texture);
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexImage2D(GL_TEXTURE_2D, miplevel, comp, scaled_width,
|
|
|
|
scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 07:51:49 +00:00
|
|
|
done:
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (mipmap)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
|
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2011-10-17 10:43:48 +00:00
|
|
|
if (mipmap && gl_config.anisotropic && gl_anisotropic->value)
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
|
|
|
gl_anisotropic->value);
|
2011-10-17 10:43:48 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
return samples == gl_alpha_format;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Returns has_alpha
|
|
|
|
*/
|
|
|
|
qboolean
|
2012-07-21 12:09:45 +00:00
|
|
|
R_Upload8(byte *data, int width, int height, qboolean mipmap, qboolean is_sky)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
unsigned trans[512 * 256];
|
2010-10-20 09:02:21 +00:00
|
|
|
int i, s;
|
|
|
|
int p;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
s = width * height;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (s > sizeof(trans) / 4)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Sys_Error(ERR_DROP, "R_Upload8: too large");
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (qglColorTableEXT && gl_ext_palettedtexture->value && is_sky)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
|
|
|
|
width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE,
|
|
|
|
data);
|
2010-10-25 12:55:59 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
|
|
|
|
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
2010-10-25 12:33:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
return false; /* SBF: FIXME - what is the correct return value? */
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < s; i++)
|
2010-10-25 12:33:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p = data[i];
|
|
|
|
trans[i] = d_8to24table[p];
|
2010-10-25 12:55:59 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
/* transparent, so scan around for
|
|
|
|
another color to avoid alpha fringes */
|
|
|
|
if (p == 255)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if ((i > width) && (data[i - width] != 255))
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p = data[i - width];
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
else if ((i < s - width) && (data[i + width] != 255))
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p = data[i + width];
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
else if ((i > 0) && (data[i - 1] != 255))
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p = data[i - 1];
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
else if ((i < s - 1) && (data[i + 1] != 255))
|
2010-10-25 12:55:59 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
p = data[i + 1];
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy rgb components */
|
2012-07-21 12:09:45 +00:00
|
|
|
((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0];
|
|
|
|
((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1];
|
|
|
|
((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2];
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2009-10-04 10:58:42 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
return R_Upload32(trans, width, height, mipmap);
|
2010-10-25 12:55:59 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* This is also used as an entry point for the generated r_notexture
|
|
|
|
*/
|
|
|
|
image_t *
|
2012-07-21 12:09:45 +00:00
|
|
|
R_LoadPic(char *name, byte *pic, int width, int realwidth,
|
|
|
|
int height, int realheight, imagetype_t type, int bits)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
image_t *image;
|
2010-10-20 09:02:21 +00:00
|
|
|
int i;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* find a free image_t */
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!image->texnum)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
break;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (i == numgltextures)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (numgltextures == MAX_GLTEXTURES)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Sys_Error(ERR_DROP, "MAX_GLTEXTURES");
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
numgltextures++;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
image = &gltextures[i];
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (strlen(name) >= sizeof(image->name))
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Sys_Error(ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
strcpy(image->name, name);
|
2009-03-05 09:07:55 +00:00
|
|
|
image->registration_sequence = registration_sequence;
|
|
|
|
|
|
|
|
image->width = width;
|
|
|
|
image->height = height;
|
|
|
|
image->type = type;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if ((type == it_skin) && (bits == 8))
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
R_FloodFillSkin(pic, width, height);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* load little pics into the scrap */
|
2012-07-21 12:09:45 +00:00
|
|
|
if ((image->type == it_pic) && (bits == 8) &&
|
|
|
|
(image->width < 64) && (image->height < 64))
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int x, y;
|
|
|
|
int i, j, k;
|
|
|
|
int texnum;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
texnum = Scrap_AllocBlock(image->width, image->height, &x, &y);
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (texnum == -1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
goto nonscrap;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
scrap_dirty = true;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* copy the texels into the scrap block */
|
2009-03-05 09:07:55 +00:00
|
|
|
k = 0;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < image->height; i++)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
for (j = 0; j < image->width; j++, k++)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
scrap_texels[texnum][(y + i) * BLOCK_WIDTH + x + j] = pic[k];
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
image->texnum = TEXNUM_SCRAPS + texnum;
|
|
|
|
image->scrap = true;
|
|
|
|
image->has_alpha = true;
|
2012-07-21 12:09:45 +00:00
|
|
|
image->sl = (x + 0.01) / (float)BLOCK_WIDTH;
|
|
|
|
image->sh = (x + image->width - 0.01) / (float)BLOCK_WIDTH;
|
|
|
|
image->tl = (y + 0.01) / (float)BLOCK_WIDTH;
|
|
|
|
image->th = (y + image->height - 0.01) / (float)BLOCK_WIDTH;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
nonscrap:
|
2009-03-05 09:07:55 +00:00
|
|
|
image->scrap = false;
|
2012-07-21 12:09:45 +00:00
|
|
|
image->texnum = TEXNUM_IMAGES + (image - gltextures);
|
|
|
|
R_Bind(image->texnum);
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (bits == 8)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
image->has_alpha = R_Upload8(pic, width, height,
|
|
|
|
(image->type != it_pic && image->type != it_sky),
|
|
|
|
image->type == it_sky);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
else
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
image->has_alpha = R_Upload32((unsigned *)pic, width, height,
|
|
|
|
(image->type != it_pic && image->type != it_sky));
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
image->upload_width = upload_width; /* after power of 2 and scales */
|
2009-03-05 09:07:55 +00:00
|
|
|
image->upload_height = upload_height;
|
|
|
|
image->paletted = uploaded_paletted;
|
2012-03-12 08:53:22 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (realwidth && realheight)
|
2012-03-12 08:53:22 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if ((realwidth <= image->width) && (realheight <= image->height))
|
2012-03-12 08:53:22 +00:00
|
|
|
{
|
|
|
|
image->width = realwidth;
|
|
|
|
image->height = realheight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Con_Printf(PRINT_DEVELOPER,
|
|
|
|
"Warning, image '%s' has hi-res replacement smaller than the original! (%d x %d) < (%d x %d)\n",
|
|
|
|
name, image->width, image->height, realwidth, realheight);
|
2012-03-12 08:53:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-05 09:07:55 +00:00
|
|
|
image->sl = 0;
|
|
|
|
image->sh = 1;
|
|
|
|
image->tl = 0;
|
|
|
|
image->th = 1;
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
return image;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-20 09:02:21 +00:00
|
|
|
* Finds or loads the given image
|
|
|
|
*/
|
|
|
|
image_t *
|
2012-07-21 12:09:45 +00:00
|
|
|
R_FindImage(char *name, imagetype_t type)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
image_t *image;
|
|
|
|
int i, len;
|
2012-07-21 12:09:45 +00:00
|
|
|
byte *pic, *palette;
|
2010-10-20 09:02:21 +00:00
|
|
|
int width, height;
|
2009-03-05 09:07:55 +00:00
|
|
|
char *ptr;
|
2012-03-11 19:01:49 +00:00
|
|
|
char namewe[256];
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
#ifdef RETEXTURE
|
2012-06-04 10:40:58 +00:00
|
|
|
int realwidth = 0, realheight = 0;
|
|
|
|
#endif
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!name)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
return NULL;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2012-04-29 13:57:33 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
len = strlen(name);
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-03-12 08:11:22 +00:00
|
|
|
/* Remove the extension */
|
2012-03-11 19:01:49 +00:00
|
|
|
memset(namewe, 0, 256);
|
2012-03-12 08:11:22 +00:00
|
|
|
memcpy(namewe, name, len - 4);
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (len < 5)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
return NULL;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* fix backslashes */
|
2012-07-21 12:09:45 +00:00
|
|
|
while ((ptr = strchr(name, '\\')))
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
*ptr = '/';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* look for it */
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!strcmp(name, image->name))
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
|
|
|
image->registration_sequence = registration_sequence;
|
2012-07-21 12:09:45 +00:00
|
|
|
return image;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* load the pic from disk */
|
2009-03-05 09:07:55 +00:00
|
|
|
pic = NULL;
|
|
|
|
palette = NULL;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!strcmp(name + len - 4, ".pcx"))
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-04-25 08:59:40 +00:00
|
|
|
#ifdef RETEXTURE
|
2012-07-21 12:09:45 +00:00
|
|
|
|
2012-03-12 09:54:04 +00:00
|
|
|
if (gl_retexturing->value)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
GetPCXInfo(name, &realwidth, &realheight);
|
2012-03-12 09:54:04 +00:00
|
|
|
|
|
|
|
/* Try to load a TGA */
|
2012-07-21 12:09:45 +00:00
|
|
|
LoadTGA(namewe, &pic, &width, &height);
|
2012-03-12 09:54:04 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!pic)
|
2012-03-12 09:54:04 +00:00
|
|
|
{
|
|
|
|
/* JPEG if no TGA available */
|
2012-07-21 12:09:45 +00:00
|
|
|
LoadJPG(namewe, &pic, &width, &height);
|
2012-03-12 09:54:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Upload TGA */
|
2012-07-21 12:09:45 +00:00
|
|
|
R_LoadPic(name, pic, width, realwidth, height,
|
|
|
|
realheight, type, 32);
|
2012-03-12 09:54:04 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!pic)
|
2012-03-12 09:54:04 +00:00
|
|
|
{
|
|
|
|
/* PCX if no JPEG available (exists always) */
|
2012-07-21 12:09:45 +00:00
|
|
|
LoadPCX(name, &pic, &palette, &width, &height);
|
2012-03-12 09:54:04 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!pic)
|
2012-03-12 09:54:04 +00:00
|
|
|
{
|
|
|
|
/* No texture found */
|
2012-07-21 12:09:45 +00:00
|
|
|
return NULL;
|
2012-03-12 09:54:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Upload the PCX */
|
2012-07-21 12:09:45 +00:00
|
|
|
image = R_LoadPic(name, pic, width, 0, height, 0, type, 8);
|
2012-03-12 09:54:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-01 15:05:40 +00:00
|
|
|
/* Upload JPEG or TGA */
|
2012-07-21 12:09:45 +00:00
|
|
|
image = R_LoadPic(name, pic, width, realwidth,
|
|
|
|
height, realheight, type, 32);
|
2012-03-12 09:54:04 +00:00
|
|
|
}
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2012-03-12 09:54:04 +00:00
|
|
|
else
|
2012-04-25 08:59:40 +00:00
|
|
|
#endif
|
2012-03-12 09:54:04 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
LoadPCX(name, &pic, &palette, &width, &height);
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!pic)
|
2012-03-12 09:54:04 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
return NULL;
|
2012-03-12 09:54:04 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
image = R_LoadPic(name, pic, width, 0, height, 0, type, 8);
|
2012-03-12 09:54:04 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
else if (!strcmp(name + len - 4, ".wal"))
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-04-25 08:59:40 +00:00
|
|
|
#ifdef RETEXTURE
|
2012-07-21 12:09:45 +00:00
|
|
|
|
2012-03-12 09:31:33 +00:00
|
|
|
if (gl_retexturing->value)
|
|
|
|
{
|
|
|
|
/* Get size of the original texture */
|
|
|
|
GetWalInfo(name, &realwidth, &realheight);
|
2012-03-11 19:01:49 +00:00
|
|
|
|
2012-03-12 09:31:33 +00:00
|
|
|
/* Try to load a TGA */
|
2012-07-21 12:09:45 +00:00
|
|
|
LoadTGA(namewe, &pic, &width, &height);
|
2012-03-12 08:11:22 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!pic)
|
2012-03-12 09:31:33 +00:00
|
|
|
{
|
|
|
|
/* JPEG if no TGA available */
|
2012-07-21 12:09:45 +00:00
|
|
|
LoadJPG(namewe, &pic, &width, &height);
|
2012-03-12 09:31:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Upload TGA */
|
2012-07-21 12:09:45 +00:00
|
|
|
R_LoadPic(name, pic, width, realwidth, height,
|
|
|
|
realheight, type, 32);
|
2012-03-12 09:31:33 +00:00
|
|
|
}
|
2012-03-11 19:01:49 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!pic)
|
2012-03-12 09:31:33 +00:00
|
|
|
{
|
|
|
|
/* WAL of no JPEG available (exists always) */
|
2012-07-21 12:09:45 +00:00
|
|
|
image = LoadWal(namewe);
|
2012-03-12 09:31:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-01 15:05:40 +00:00
|
|
|
/* Upload JPEG or TGA */
|
2012-07-21 12:09:45 +00:00
|
|
|
image = R_LoadPic(name, pic, width, realwidth,
|
|
|
|
height, realheight, type, 32);
|
2012-03-12 09:31:33 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!image)
|
2012-03-12 09:31:33 +00:00
|
|
|
{
|
|
|
|
/* No texture found */
|
2012-07-21 12:09:45 +00:00
|
|
|
return NULL;
|
2012-03-12 09:31:33 +00:00
|
|
|
}
|
2012-03-11 19:01:49 +00:00
|
|
|
}
|
2012-03-12 08:11:22 +00:00
|
|
|
else
|
2012-04-25 08:59:40 +00:00
|
|
|
#endif
|
2012-03-12 08:11:22 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
image = LoadWal(name);
|
2012-03-12 08:11:22 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!image)
|
2012-03-12 09:31:33 +00:00
|
|
|
{
|
|
|
|
/* No texture found */
|
2012-07-21 12:09:45 +00:00
|
|
|
return NULL;
|
2012-03-12 09:31:33 +00:00
|
|
|
}
|
2012-03-12 08:11:22 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
|
2012-06-04 10:40:58 +00:00
|
|
|
#ifdef RETEXTURE
|
2012-07-21 12:09:45 +00:00
|
|
|
else if (!strcmp(name + len - 4, ".tga"))
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
LoadTGA(name, &pic, &width, &height);
|
|
|
|
image = R_LoadPic(name, pic, width, realwidth,
|
|
|
|
height, realwidth, type, 32);
|
2012-03-11 16:50:57 +00:00
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
else if (!strcmp(name + len - 4, ".jpg"))
|
2012-03-11 16:50:57 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
LoadJPG(name, &pic, &width, &height);
|
|
|
|
image = R_LoadPic(name, pic, width, realwidth,
|
|
|
|
height, realheight, type, 32);
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
2012-06-04 10:40:58 +00:00
|
|
|
#endif
|
2009-03-05 09:07:55 +00:00
|
|
|
else
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
return NULL;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (pic)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
free(pic);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (palette)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
free(palette);
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
return image;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
struct image_s *
|
2012-07-21 12:09:45 +00:00
|
|
|
R_RegisterSkin(char *name)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
return R_FindImage(name, it_skin);
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-10-25 12:33:55 +00:00
|
|
|
* Any image that was not touched on
|
2010-10-20 09:02:21 +00:00
|
|
|
* this registration sequence
|
|
|
|
* will be freed.
|
|
|
|
*/
|
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_FreeUnusedImages(void)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i;
|
|
|
|
image_t *image;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* never free r_notexture or particle texture */
|
2009-03-05 09:07:55 +00:00
|
|
|
r_notexture->registration_sequence = registration_sequence;
|
|
|
|
r_particletexture->registration_sequence = registration_sequence;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (image->registration_sequence == registration_sequence)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
continue; /* used this sequence */
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!image->registration_sequence)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
continue; /* free image_t slot */
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (image->type == it_pic)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
continue; /* don't free pics */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free it */
|
2012-07-21 12:09:45 +00:00
|
|
|
qglDeleteTextures(1, (GLuint *)&image->texnum);
|
|
|
|
memset(image, 0, sizeof(*image));
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_InitImages(void)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i, j;
|
|
|
|
float g = vid_gamma->value;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
registration_sequence = 1;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
/* init intensity conversions */
|
2012-07-21 12:09:45 +00:00
|
|
|
intensity = ri.Cvar_Get("intensity", "2", CVAR_ARCHIVE);
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (intensity->value <= 1)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Cvar_Set("intensity", "1");
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
|
|
|
|
gl_state.inverse_intensity = 1 / intensity->value;
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
Draw_GetPalette();
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (qglColorTableEXT)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.FS_LoadFile("pics/16to8.dat", (void **)&gl_state.d_16to8table);
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!gl_state.d_16to8table)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
ri.Sys_Error(ERR_FATAL, "Couldn't load pics/16to8.pcx");
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < 256; i++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if ((g == 1) || gl_state.hwgamma)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
gammatable[i] = i;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float inf;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
inf = 255 * pow((i + 0.5) / 255.5, g) + 0.5;
|
2010-10-20 09:02:21 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (inf < 0)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
inf = 0;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (inf > 255)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
inf = 255;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
gammatable[i] = inf;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0; i < 256; i++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
j = i * intensity->value;
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
if (j > 255)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
2009-03-05 09:07:55 +00:00
|
|
|
j = 255;
|
2010-10-20 09:02:21 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
intensitytable[i] = j;
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-20 09:02:21 +00:00
|
|
|
void
|
2012-07-21 12:09:45 +00:00
|
|
|
R_ShutdownImages(void)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2010-10-20 09:02:21 +00:00
|
|
|
int i;
|
|
|
|
image_t *image;
|
2009-03-05 09:07:55 +00:00
|
|
|
|
2012-07-21 12:09:45 +00:00
|
|
|
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
|
2009-03-05 09:07:55 +00:00
|
|
|
{
|
2012-07-21 12:09:45 +00:00
|
|
|
if (!image->registration_sequence)
|
2010-10-20 09:02:21 +00:00
|
|
|
{
|
|
|
|
continue; /* free image_t slot */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free it */
|
2012-07-21 12:09:45 +00:00
|
|
|
qglDeleteTextures(1, (GLuint *)&image->texnum);
|
|
|
|
memset(image, 0, sizeof(*image));
|
2009-03-05 09:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
2012-07-21 12:09:45 +00:00
|
|
|
|