Created new subdir: uquake. Pick your favorite U word for the meaning --
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified,
Unity, etc. You know the drill.
This takes care of the "standalone" problem with the wrong name, and the
recent snafu with multiple developers working on the same files
simultaneously...expect me (and probably others) to start locking dirs when
updates are taking place.
And yes, this update is really as large as it looks. Software only at the
moment, but I will have the makefile updated to build the GL builds as
well.
1999-12-26 13:51:52 +00:00
|
|
|
/*
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
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
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
// draw.c -- this is the only file outside the refresh that touches the
|
|
|
|
// vid buffer
|
|
|
|
|
|
|
|
#include "quakedef.h"
|
|
|
|
|
|
|
|
#define GL_COLOR_INDEX8_EXT 0x80E5
|
|
|
|
|
|
|
|
extern unsigned char d_15to8table[65536];
|
|
|
|
|
|
|
|
cvar_t gl_nobind = {"gl_nobind", "0"};
|
|
|
|
cvar_t gl_max_size = {"gl_max_size", "1024"};
|
|
|
|
cvar_t gl_picmip = {"gl_picmip", "0"};
|
|
|
|
|
|
|
|
byte *draw_chars; // 8*8 graphic characters
|
|
|
|
qpic_t *draw_disc;
|
|
|
|
qpic_t *draw_backtile;
|
|
|
|
|
|
|
|
int translate_texture;
|
|
|
|
int char_texture;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int texnum;
|
|
|
|
float sl, tl, sh, th;
|
|
|
|
} glpic_t;
|
|
|
|
|
|
|
|
byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
|
|
|
|
qpic_t *conback = (qpic_t *)&conback_buffer;
|
|
|
|
|
|
|
|
int gl_lightmap_format = 4;
|
|
|
|
int gl_solid_format = 3;
|
|
|
|
int gl_alpha_format = 4;
|
|
|
|
|
|
|
|
int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
|
|
|
|
int gl_filter_max = GL_LINEAR;
|
|
|
|
|
|
|
|
|
|
|
|
int texels;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int texnum;
|
|
|
|
char identifier[64];
|
|
|
|
int width, height;
|
|
|
|
qboolean mipmap;
|
|
|
|
} gltexture_t;
|
|
|
|
|
|
|
|
#define MAX_GLTEXTURES 1024
|
|
|
|
gltexture_t gltextures[MAX_GLTEXTURES];
|
|
|
|
int numgltextures;
|
|
|
|
|
1999-12-27 22:00:21 +00:00
|
|
|
int GL_LoadPicTexture (qpic_t *pic);
|
|
|
|
|
Created new subdir: uquake. Pick your favorite U word for the meaning --
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified,
Unity, etc. You know the drill.
This takes care of the "standalone" problem with the wrong name, and the
recent snafu with multiple developers working on the same files
simultaneously...expect me (and probably others) to start locking dirs when
updates are taking place.
And yes, this update is really as large as it looks. Software only at the
moment, but I will have the makefile updated to build the GL builds as
well.
1999-12-26 13:51:52 +00:00
|
|
|
|
|
|
|
void GL_Bind (int texnum)
|
|
|
|
{
|
|
|
|
if (gl_nobind.value)
|
|
|
|
texnum = char_texture;
|
|
|
|
if (currenttexture == texnum)
|
|
|
|
return;
|
|
|
|
currenttexture = texnum;
|
|
|
|
#ifdef _WIN32
|
|
|
|
bindTexFunc (GL_TEXTURE_2D, texnum);
|
|
|
|
#else
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texnum);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============================================================================
|
|
|
|
|
|
|
|
scrap allocation
|
|
|
|
|
|
|
|
Allocate all the little status bar obejcts into a single texture
|
|
|
|
to crutch up stupid hardware / drivers
|
|
|
|
|
|
|
|
=============================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define MAX_SCRAPS 2
|
|
|
|
#define BLOCK_WIDTH 256
|
|
|
|
#define BLOCK_HEIGHT 256
|
|
|
|
|
|
|
|
int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
|
|
|
|
byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
|
|
|
|
qboolean scrap_dirty;
|
|
|
|
int scrap_texnum;
|
|
|
|
|
|
|
|
// returns a texture number and the position inside it
|
|
|
|
int Scrap_AllocBlock (int w, int h, int *x, int *y)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
int best, best2;
|
|
|
|
int texnum;
|
|
|
|
|
|
|
|
for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
|
|
|
|
{
|
|
|
|
best = BLOCK_HEIGHT;
|
|
|
|
|
|
|
|
for (i=0 ; i<BLOCK_WIDTH-w ; i++)
|
|
|
|
{
|
|
|
|
best2 = 0;
|
|
|
|
|
|
|
|
for (j=0 ; j<w ; j++)
|
|
|
|
{
|
|
|
|
if (scrap_allocated[texnum][i+j] >= best)
|
|
|
|
break;
|
|
|
|
if (scrap_allocated[texnum][i+j] > best2)
|
|
|
|
best2 = scrap_allocated[texnum][i+j];
|
|
|
|
}
|
|
|
|
if (j == w)
|
|
|
|
{ // this is a valid spot
|
|
|
|
*x = i;
|
|
|
|
*y = best = best2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (best + h > BLOCK_HEIGHT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (i=0 ; i<w ; i++)
|
|
|
|
scrap_allocated[texnum][*x + i] = best + h;
|
|
|
|
|
|
|
|
return texnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sys_Error ("Scrap_AllocBlock: full");
|
1999-12-27 17:18:40 +00:00
|
|
|
return 0;
|
Created new subdir: uquake. Pick your favorite U word for the meaning --
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified,
Unity, etc. You know the drill.
This takes care of the "standalone" problem with the wrong name, and the
recent snafu with multiple developers working on the same files
simultaneously...expect me (and probably others) to start locking dirs when
updates are taking place.
And yes, this update is really as large as it looks. Software only at the
moment, but I will have the makefile updated to build the GL builds as
well.
1999-12-26 13:51:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int scrap_uploads;
|
|
|
|
|
|
|
|
void Scrap_Upload (void)
|
|
|
|
{
|
|
|
|
int texnum;
|
|
|
|
|
|
|
|
scrap_uploads++;
|
|
|
|
|
|
|
|
for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) {
|
|
|
|
GL_Bind(scrap_texnum + texnum);
|
|
|
|
GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
|
|
|
|
}
|
|
|
|
scrap_dirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
/* Support Routines */
|
|
|
|
|
|
|
|
typedef struct cachepic_s
|
|
|
|
{
|
|
|
|
char name[MAX_QPATH];
|
|
|
|
qpic_t pic;
|
|
|
|
byte padding[32]; // for appended glpic
|
|
|
|
} cachepic_t;
|
|
|
|
|
|
|
|
#define MAX_CACHED_PICS 128
|
|
|
|
cachepic_t menu_cachepics[MAX_CACHED_PICS];
|
|
|
|
int menu_numcachepics;
|
|
|
|
|
|
|
|
byte menuplyr_pixels[4096];
|
|
|
|
|
|
|
|
int pic_texels;
|
|
|
|
int pic_count;
|
|
|
|
|
|
|
|
qpic_t *Draw_PicFromWad (char *name)
|
|
|
|
{
|
|
|
|
qpic_t *p;
|
|
|
|
glpic_t *gl;
|
|
|
|
|
|
|
|
p = W_GetLumpName (name);
|
|
|
|
gl = (glpic_t *)p->data;
|
|
|
|
|
|
|
|
// load little ones into the scrap
|
|
|
|
if (p->width < 64 && p->height < 64)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
int i, j, k;
|
|
|
|
int texnum;
|
|
|
|
|
|
|
|
texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
|
|
|
|
scrap_dirty = true;
|
|
|
|
k = 0;
|
|
|
|
for (i=0 ; i<p->height ; i++)
|
|
|
|
for (j=0 ; j<p->width ; j++, k++)
|
|
|
|
scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
|
|
|
|
texnum += scrap_texnum;
|
|
|
|
gl->texnum = texnum;
|
|
|
|
gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
|
|
|
|
gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
|
|
|
|
gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
|
|
|
|
gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
|
|
|
|
|
|
|
|
pic_count++;
|
|
|
|
pic_texels += p->width*p->height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl->texnum = GL_LoadPicTexture (p);
|
|
|
|
gl->sl = 0;
|
|
|
|
gl->sh = 1;
|
|
|
|
gl->tl = 0;
|
|
|
|
gl->th = 1;
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_CachePic
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
qpic_t *Draw_CachePic (char *path)
|
|
|
|
{
|
|
|
|
cachepic_t *pic;
|
|
|
|
int i;
|
|
|
|
qpic_t *dat;
|
|
|
|
glpic_t *gl;
|
|
|
|
|
|
|
|
for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
|
|
|
|
if (!strcmp (path, pic->name))
|
|
|
|
return &pic->pic;
|
|
|
|
|
|
|
|
if (menu_numcachepics == MAX_CACHED_PICS)
|
|
|
|
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
|
|
|
|
menu_numcachepics++;
|
|
|
|
strcpy (pic->name, path);
|
|
|
|
|
|
|
|
//
|
|
|
|
// load the pic from disk
|
|
|
|
//
|
|
|
|
dat = (qpic_t *)COM_LoadTempFile (path);
|
|
|
|
if (!dat)
|
|
|
|
Sys_Error ("Draw_CachePic: failed to load %s", path);
|
|
|
|
SwapPic (dat);
|
|
|
|
|
|
|
|
// HACK HACK HACK --- we need to keep the bytes for
|
|
|
|
// the translatable player picture just for the menu
|
|
|
|
// configuration dialog
|
|
|
|
if (!strcmp (path, "gfx/menuplyr.lmp"))
|
|
|
|
memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
|
|
|
|
|
|
|
|
pic->pic.width = dat->width;
|
|
|
|
pic->pic.height = dat->height;
|
|
|
|
|
|
|
|
gl = (glpic_t *)pic->pic.data;
|
|
|
|
gl->texnum = GL_LoadPicTexture (dat);
|
|
|
|
gl->sl = 0;
|
|
|
|
gl->sh = 1;
|
|
|
|
gl->tl = 0;
|
|
|
|
gl->th = 1;
|
|
|
|
|
|
|
|
return &pic->pic;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Draw_CharToConback (int num, byte *dest)
|
|
|
|
{
|
|
|
|
int row, col;
|
|
|
|
byte *source;
|
|
|
|
int drawline;
|
|
|
|
int x;
|
|
|
|
|
|
|
|
row = num>>4;
|
|
|
|
col = num&15;
|
|
|
|
source = draw_chars + (row<<10) + (col<<3);
|
|
|
|
|
|
|
|
drawline = 8;
|
|
|
|
|
|
|
|
while (drawline--)
|
|
|
|
{
|
|
|
|
for (x=0 ; x<8 ; x++)
|
|
|
|
if (source[x] != 255)
|
|
|
|
dest[x] = 0x60 + source[x];
|
|
|
|
source += 128;
|
|
|
|
dest += 320;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int minimize, maximize;
|
|
|
|
} glmode_t;
|
|
|
|
|
|
|
|
glmode_t modes[] = {
|
|
|
|
{"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}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Draw_TextureMode_f
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Draw_TextureMode_f (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
gltexture_t *glt;
|
|
|
|
|
|
|
|
if (Cmd_Argc() == 1)
|
|
|
|
{
|
|
|
|
for (i=0 ; i< 6 ; i++)
|
|
|
|
if (gl_filter_min == modes[i].minimize)
|
|
|
|
{
|
|
|
|
Con_Printf ("%s\n", modes[i].name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Con_Printf ("current filter is unknown???\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0 ; i< 6 ; i++)
|
|
|
|
{
|
|
|
|
if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == 6)
|
|
|
|
{
|
|
|
|
Con_Printf ("bad filter name\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gl_filter_min = modes[i].minimize;
|
|
|
|
gl_filter_max = modes[i].maximize;
|
|
|
|
|
|
|
|
// change all the existing mipmap texture objects
|
|
|
|
for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
|
|
|
|
{
|
|
|
|
if (glt->mipmap)
|
|
|
|
{
|
|
|
|
GL_Bind (glt->texnum);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Draw_Init
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Draw_Init (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
qpic_t *cb;
|
1999-12-27 17:18:40 +00:00
|
|
|
byte *dest;//, *src;
|
Created new subdir: uquake. Pick your favorite U word for the meaning --
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified,
Unity, etc. You know the drill.
This takes care of the "standalone" problem with the wrong name, and the
recent snafu with multiple developers working on the same files
simultaneously...expect me (and probably others) to start locking dirs when
updates are taking place.
And yes, this update is really as large as it looks. Software only at the
moment, but I will have the makefile updated to build the GL builds as
well.
1999-12-26 13:51:52 +00:00
|
|
|
int x, y;
|
|
|
|
char ver[40];
|
|
|
|
glpic_t *gl;
|
|
|
|
int start;
|
|
|
|
byte *ncdata;
|
1999-12-27 17:18:40 +00:00
|
|
|
//int f, fstep;
|
Created new subdir: uquake. Pick your favorite U word for the meaning --
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified,
Unity, etc. You know the drill.
This takes care of the "standalone" problem with the wrong name, and the
recent snafu with multiple developers working on the same files
simultaneously...expect me (and probably others) to start locking dirs when
updates are taking place.
And yes, this update is really as large as it looks. Software only at the
moment, but I will have the makefile updated to build the GL builds as
well.
1999-12-26 13:51:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
Cvar_RegisterVariable (&gl_nobind);
|
|
|
|
Cvar_RegisterVariable (&gl_max_size);
|
|
|
|
Cvar_RegisterVariable (&gl_picmip);
|
|
|
|
|
|
|
|
// 3dfx can only handle 256 wide textures
|
|
|
|
if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
|
|
|
|
strstr((char *)gl_renderer, "Glide"))
|
|
|
|
Cvar_Set ("gl_max_size", "256");
|
|
|
|
|
|
|
|
Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
|
|
|
|
|
|
|
|
// load the console background and the charset
|
|
|
|
// by hand, because we need to write the version
|
|
|
|
// string into the background before turning
|
|
|
|
// it into a texture
|
|
|
|
draw_chars = W_GetLumpName ("conchars");
|
|
|
|
for (i=0 ; i<256*64 ; i++)
|
|
|
|
if (draw_chars[i] == 0)
|
|
|
|
draw_chars[i] = 255; // proper transparent color
|
|
|
|
|
|
|
|
// now turn them into textures
|
|
|
|
char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true);
|
|
|
|
|
|
|
|
start = Hunk_LowMark();
|
|
|
|
|
|
|
|
cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp");
|
|
|
|
if (!cb)
|
|
|
|
Sys_Error ("Couldn't load gfx/conback.lmp");
|
|
|
|
SwapPic (cb);
|
|
|
|
|
|
|
|
// hack the version number directly into the pic
|
|
|
|
#if defined(__linux__)
|
1999-12-29 03:20:25 +00:00
|
|
|
sprintf (ver, "QuakeForge (Linux GL) Version %4.2f", (float)VERSION);
|
Created new subdir: uquake. Pick your favorite U word for the meaning --
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified,
Unity, etc. You know the drill.
This takes care of the "standalone" problem with the wrong name, and the
recent snafu with multiple developers working on the same files
simultaneously...expect me (and probably others) to start locking dirs when
updates are taking place.
And yes, this update is really as large as it looks. Software only at the
moment, but I will have the makefile updated to build the GL builds as
well.
1999-12-26 13:51:52 +00:00
|
|
|
#else
|
1999-12-29 03:20:25 +00:00
|
|
|
sprintf (ver, "QuakeForge (GL) Version %4.2f", (float)VERSION);
|
Created new subdir: uquake. Pick your favorite U word for the meaning --
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified,
Unity, etc. You know the drill.
This takes care of the "standalone" problem with the wrong name, and the
recent snafu with multiple developers working on the same files
simultaneously...expect me (and probably others) to start locking dirs when
updates are taking place.
And yes, this update is really as large as it looks. Software only at the
moment, but I will have the makefile updated to build the GL builds as
well.
1999-12-26 13:51:52 +00:00
|
|
|
#endif
|
|
|
|
dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
|
|
|
|
y = strlen(ver);
|
|
|
|
for (x=0 ; x<y ; x++)
|
|
|
|
Draw_CharToConback (ver[x], dest+(x<<3));
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
conback->width = vid.conwidth;
|
|
|
|
conback->height = vid.conheight;
|
|
|
|
|
|
|
|
// scale console to vid size
|
|
|
|
dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback");
|
|
|
|
|
|
|
|
for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth)
|
|
|
|
{
|
|
|
|
src = cb->data + cb->width * (y*cb->height/vid.conheight);
|
|
|
|
if (vid.conwidth == cb->width)
|
|
|
|
memcpy (dest, src, vid.conwidth);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
f = 0;
|
|
|
|
fstep = cb->width*0x10000/vid.conwidth;
|
|
|
|
for (x=0 ; x<vid.conwidth ; x+=4)
|
|
|
|
{
|
|
|
|
dest[x] = src[f>>16];
|
|
|
|
f += fstep;
|
|
|
|
dest[x+1] = src[f>>16];
|
|
|
|
f += fstep;
|
|
|
|
dest[x+2] = src[f>>16];
|
|
|
|
f += fstep;
|
|
|
|
dest[x+3] = src[f>>16];
|
|
|
|
f += fstep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
conback->width = cb->width;
|
|
|
|
conback->height = cb->height;
|
|
|
|
ncdata = cb->data;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
|
|
|
|
gl = (glpic_t *)conback->data;
|
|
|
|
gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false);
|
|
|
|
gl->sl = 0;
|
|
|
|
gl->sh = 1;
|
|
|
|
gl->tl = 0;
|
|
|
|
gl->th = 1;
|
|
|
|
conback->width = vid.width;
|
|
|
|
conback->height = vid.height;
|
|
|
|
|
|
|
|
// free loaded console
|
|
|
|
Hunk_FreeToLowMark(start);
|
|
|
|
|
|
|
|
// save a texture slot for translated picture
|
|
|
|
translate_texture = texture_extension_number++;
|
|
|
|
|
|
|
|
// save slots for scraps
|
|
|
|
scrap_texnum = texture_extension_number;
|
|
|
|
texture_extension_number += MAX_SCRAPS;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get the other pics we need
|
|
|
|
//
|
|
|
|
draw_disc = Draw_PicFromWad ("disc");
|
|
|
|
draw_backtile = Draw_PicFromWad ("backtile");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_Character
|
|
|
|
|
|
|
|
Draws one 8*8 graphics character with 0 being transparent.
|
|
|
|
It can be clipped to the top of the screen to allow the console to be
|
|
|
|
smoothly scrolled off.
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_Character (int x, int y, int num)
|
|
|
|
{
|
|
|
|
int row, col;
|
|
|
|
float frow, fcol, size;
|
|
|
|
|
|
|
|
if (num == 32)
|
|
|
|
return; // space
|
|
|
|
|
|
|
|
num &= 255;
|
|
|
|
|
|
|
|
if (y <= -8)
|
|
|
|
return; // totally off screen
|
|
|
|
|
|
|
|
row = num>>4;
|
|
|
|
col = num&15;
|
|
|
|
|
|
|
|
frow = row*0.0625;
|
|
|
|
fcol = col*0.0625;
|
|
|
|
size = 0.0625;
|
|
|
|
|
|
|
|
GL_Bind (char_texture);
|
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (fcol, frow);
|
|
|
|
glVertex2f (x, y);
|
|
|
|
glTexCoord2f (fcol + size, frow);
|
|
|
|
glVertex2f (x+8, y);
|
|
|
|
glTexCoord2f (fcol + size, frow + size);
|
|
|
|
glVertex2f (x+8, y+8);
|
|
|
|
glTexCoord2f (fcol, frow + size);
|
|
|
|
glVertex2f (x, y+8);
|
|
|
|
glEnd ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_String
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_String (int x, int y, char *str)
|
|
|
|
{
|
|
|
|
while (*str)
|
|
|
|
{
|
|
|
|
Draw_Character (x, y, *str);
|
|
|
|
str++;
|
|
|
|
x += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_DebugChar
|
|
|
|
|
|
|
|
Draws a single character directly to the upper right corner of the screen.
|
|
|
|
This is for debugging lockups by drawing different chars in different parts
|
|
|
|
of the code.
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_DebugChar (char num)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_AlphaPic
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
|
|
|
|
{
|
|
|
|
glpic_t *gl;
|
|
|
|
|
|
|
|
if (scrap_dirty)
|
|
|
|
Scrap_Upload ();
|
|
|
|
gl = (glpic_t *)pic->data;
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
glEnable (GL_BLEND);
|
|
|
|
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
// glCullFace(GL_FRONT);
|
|
|
|
glColor4f (1,1,1,alpha);
|
|
|
|
GL_Bind (gl->texnum);
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (gl->sl, gl->tl);
|
|
|
|
glVertex2f (x, y);
|
|
|
|
glTexCoord2f (gl->sh, gl->tl);
|
|
|
|
glVertex2f (x+pic->width, y);
|
|
|
|
glTexCoord2f (gl->sh, gl->th);
|
|
|
|
glVertex2f (x+pic->width, y+pic->height);
|
|
|
|
glTexCoord2f (gl->sl, gl->th);
|
|
|
|
glVertex2f (x, y+pic->height);
|
|
|
|
glEnd ();
|
|
|
|
glColor4f (1,1,1,1);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glDisable (GL_BLEND);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_Pic
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_Pic (int x, int y, qpic_t *pic)
|
|
|
|
{
|
|
|
|
glpic_t *gl;
|
|
|
|
|
|
|
|
if (scrap_dirty)
|
|
|
|
Scrap_Upload ();
|
|
|
|
gl = (glpic_t *)pic->data;
|
|
|
|
glColor4f (1,1,1,1);
|
|
|
|
GL_Bind (gl->texnum);
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (gl->sl, gl->tl);
|
|
|
|
glVertex2f (x, y);
|
|
|
|
glTexCoord2f (gl->sh, gl->tl);
|
|
|
|
glVertex2f (x+pic->width, y);
|
|
|
|
glTexCoord2f (gl->sh, gl->th);
|
|
|
|
glVertex2f (x+pic->width, y+pic->height);
|
|
|
|
glTexCoord2f (gl->sl, gl->th);
|
|
|
|
glVertex2f (x, y+pic->height);
|
|
|
|
glEnd ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_TransPic
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_TransPic (int x, int y, qpic_t *pic)
|
|
|
|
{
|
|
|
|
if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
|
|
|
|
(unsigned)(y + pic->height) > vid.height)
|
|
|
|
{
|
|
|
|
Sys_Error ("Draw_TransPic: bad coordinates");
|
|
|
|
}
|
|
|
|
|
|
|
|
Draw_Pic (x, y, pic);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_TransPicTranslate
|
|
|
|
|
|
|
|
Only used for the player color selection menu
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
|
|
|
|
{
|
|
|
|
int v, u, c;
|
|
|
|
unsigned trans[64*64], *dest;
|
|
|
|
byte *src;
|
|
|
|
int p;
|
|
|
|
|
|
|
|
GL_Bind (translate_texture);
|
|
|
|
|
|
|
|
c = pic->width * pic->height;
|
|
|
|
|
|
|
|
dest = trans;
|
|
|
|
for (v=0 ; v<64 ; v++, dest += 64)
|
|
|
|
{
|
|
|
|
src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
|
|
|
|
for (u=0 ; u<64 ; u++)
|
|
|
|
{
|
|
|
|
p = src[(u*pic->width)>>6];
|
|
|
|
if (p == 255)
|
|
|
|
dest[u] = p;
|
|
|
|
else
|
|
|
|
dest[u] = d_8to24table[translation[p]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
|
|
|
|
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
|
|
|
|
glColor3f (1,1,1);
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (0, 0);
|
|
|
|
glVertex2f (x, y);
|
|
|
|
glTexCoord2f (1, 0);
|
|
|
|
glVertex2f (x+pic->width, y);
|
|
|
|
glTexCoord2f (1, 1);
|
|
|
|
glVertex2f (x+pic->width, y+pic->height);
|
|
|
|
glTexCoord2f (0, 1);
|
|
|
|
glVertex2f (x, y+pic->height);
|
|
|
|
glEnd ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_ConsoleBackground
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_ConsoleBackground (int lines)
|
|
|
|
{
|
|
|
|
int y = (vid.height * 3) >> 2;
|
|
|
|
|
|
|
|
if (lines > y)
|
|
|
|
Draw_Pic(0, lines - vid.height, conback);
|
|
|
|
else
|
|
|
|
Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_TileClear
|
|
|
|
|
|
|
|
This repeats a 64*64 tile graphic to fill the screen around a sized down
|
|
|
|
refresh window.
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_TileClear (int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
glColor3f (1,1,1);
|
|
|
|
GL_Bind (*(int *)draw_backtile->data);
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (x/64.0, y/64.0);
|
|
|
|
glVertex2f (x, y);
|
|
|
|
glTexCoord2f ( (x+w)/64.0, y/64.0);
|
|
|
|
glVertex2f (x+w, y);
|
|
|
|
glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
|
|
|
|
glVertex2f (x+w, y+h);
|
|
|
|
glTexCoord2f ( x/64.0, (y+h)/64.0 );
|
|
|
|
glVertex2f (x, y+h);
|
|
|
|
glEnd ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_Fill
|
|
|
|
|
|
|
|
Fills a box of pixels with a single color
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_Fill (int x, int y, int w, int h, int c)
|
|
|
|
{
|
|
|
|
glDisable (GL_TEXTURE_2D);
|
|
|
|
glColor3f (host_basepal[c*3]/255.0,
|
|
|
|
host_basepal[c*3+1]/255.0,
|
|
|
|
host_basepal[c*3+2]/255.0);
|
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
|
|
|
|
glVertex2f (x,y);
|
|
|
|
glVertex2f (x+w, y);
|
|
|
|
glVertex2f (x+w, y+h);
|
|
|
|
glVertex2f (x, y+h);
|
|
|
|
|
|
|
|
glEnd ();
|
|
|
|
glColor3f (1,1,1);
|
|
|
|
glEnable (GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_FadeScreen
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_FadeScreen (void)
|
|
|
|
{
|
|
|
|
glEnable (GL_BLEND);
|
|
|
|
glDisable (GL_TEXTURE_2D);
|
|
|
|
glColor4f (0, 0, 0, 0.8);
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
|
|
|
|
glVertex2f (0,0);
|
|
|
|
glVertex2f (vid.width, 0);
|
|
|
|
glVertex2f (vid.width, vid.height);
|
|
|
|
glVertex2f (0, vid.height);
|
|
|
|
|
|
|
|
glEnd ();
|
|
|
|
glColor4f (1,1,1,1);
|
|
|
|
glEnable (GL_TEXTURE_2D);
|
|
|
|
glDisable (GL_BLEND);
|
|
|
|
|
|
|
|
Sbar_Changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_BeginDisc
|
|
|
|
|
|
|
|
Draws the little blue disc in the corner of the screen.
|
|
|
|
Call before beginning any disc IO.
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_BeginDisc (void)
|
|
|
|
{
|
|
|
|
if (!draw_disc)
|
|
|
|
return;
|
|
|
|
glDrawBuffer (GL_FRONT);
|
|
|
|
Draw_Pic (vid.width - 24, 0, draw_disc);
|
|
|
|
glDrawBuffer (GL_BACK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_EndDisc
|
|
|
|
|
|
|
|
Erases the disc icon.
|
|
|
|
Call after completing any disc IO
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_EndDisc (void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_Set2D
|
|
|
|
|
|
|
|
Setup as if the screen was 320*200
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void GL_Set2D (void)
|
|
|
|
{
|
|
|
|
glViewport (glx, gly, glwidth, glheight);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
|
|
|
glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity ();
|
|
|
|
|
|
|
|
glDisable (GL_DEPTH_TEST);
|
|
|
|
glDisable (GL_CULL_FACE);
|
|
|
|
glDisable (GL_BLEND);
|
|
|
|
glEnable (GL_ALPHA_TEST);
|
|
|
|
// glDisable (GL_ALPHA_TEST);
|
|
|
|
|
|
|
|
glColor4f (1,1,1,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//====================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_FindTexture
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
int GL_FindTexture (char *identifier)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
gltexture_t *glt;
|
|
|
|
|
|
|
|
for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
|
|
|
|
{
|
|
|
|
if (!strcmp (identifier, glt->identifier))
|
|
|
|
return gltextures[i].texnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_ResampleTexture
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
unsigned *inrow;
|
|
|
|
unsigned frac, fracstep;
|
|
|
|
|
|
|
|
fracstep = inwidth*0x10000/outwidth;
|
|
|
|
for (i=0 ; i<outheight ; i++, out += outwidth)
|
|
|
|
{
|
|
|
|
inrow = in + inwidth*(i*inheight/outheight);
|
|
|
|
frac = fracstep >> 1;
|
|
|
|
for (j=0 ; j<outwidth ; j+=4)
|
|
|
|
{
|
|
|
|
out[j] = inrow[frac>>16];
|
|
|
|
frac += fracstep;
|
|
|
|
out[j+1] = inrow[frac>>16];
|
|
|
|
frac += fracstep;
|
|
|
|
out[j+2] = inrow[frac>>16];
|
|
|
|
frac += fracstep;
|
|
|
|
out[j+3] = inrow[frac>>16];
|
|
|
|
frac += fracstep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_Resample8BitTexture -- JACK
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
unsigned char *inrow;
|
|
|
|
unsigned frac, fracstep;
|
|
|
|
|
|
|
|
fracstep = inwidth*0x10000/outwidth;
|
|
|
|
for (i=0 ; i<outheight ; i++, out += outwidth)
|
|
|
|
{
|
|
|
|
inrow = in + inwidth*(i*inheight/outheight);
|
|
|
|
frac = fracstep >> 1;
|
|
|
|
for (j=0 ; j<outwidth ; j+=4)
|
|
|
|
{
|
|
|
|
out[j] = inrow[frac>>16];
|
|
|
|
frac += fracstep;
|
|
|
|
out[j+1] = inrow[frac>>16];
|
|
|
|
frac += fracstep;
|
|
|
|
out[j+2] = inrow[frac>>16];
|
|
|
|
frac += fracstep;
|
|
|
|
out[j+3] = inrow[frac>>16];
|
|
|
|
frac += fracstep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_MipMap
|
|
|
|
|
|
|
|
Operates in place, quartering the size of the texture
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void GL_MipMap (byte *in, int width, int height)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
byte *out;
|
|
|
|
|
|
|
|
width <<=2;
|
|
|
|
height >>= 1;
|
|
|
|
out = in;
|
|
|
|
for (i=0 ; i<height ; i++, in+=width)
|
|
|
|
{
|
|
|
|
for (j=0 ; j<width ; j+=8, out+=4, in+=8)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_MipMap8Bit
|
|
|
|
|
|
|
|
Mipping for 8 bit textures
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void GL_MipMap8Bit (byte *in, int width, int height)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
unsigned short r,g,b;
|
|
|
|
byte *out, *at1, *at2, *at3, *at4;
|
|
|
|
|
|
|
|
// width <<=2;
|
|
|
|
height >>= 1;
|
|
|
|
out = in;
|
|
|
|
for (i=0 ; i<height ; i++, in+=width)
|
|
|
|
{
|
|
|
|
for (j=0 ; j<width ; j+=2, out+=1, in+=2)
|
|
|
|
{
|
|
|
|
at1 = (byte *) (d_8to24table + in[0]);
|
|
|
|
at2 = (byte *) (d_8to24table + in[1]);
|
|
|
|
at3 = (byte *) (d_8to24table + in[width+0]);
|
|
|
|
at4 = (byte *) (d_8to24table + in[width+1]);
|
|
|
|
|
|
|
|
r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
|
|
|
|
g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
|
|
|
|
b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
|
|
|
|
|
|
|
|
out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
GL_Upload32
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha)
|
|
|
|
{
|
|
|
|
int samples;
|
|
|
|
static unsigned scaled[1024*512]; // [512*256];
|
|
|
|
int scaled_width, scaled_height;
|
|
|
|
|
|
|
|
for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
|
|
|
|
;
|
|
|
|
for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
|
|
|
|
;
|
|
|
|
|
|
|
|
scaled_width >>= (int)gl_picmip.value;
|
|
|
|
scaled_height >>= (int)gl_picmip.value;
|
|
|
|
|
|
|
|
if (scaled_width > gl_max_size.value)
|
|
|
|
scaled_width = gl_max_size.value;
|
|
|
|
if (scaled_height > gl_max_size.value)
|
|
|
|
scaled_height = gl_max_size.value;
|
|
|
|
|
|
|
|
if (scaled_width * scaled_height > sizeof(scaled)/4)
|
|
|
|
Sys_Error ("GL_LoadTexture: too big");
|
|
|
|
|
|
|
|
samples = alpha ? gl_alpha_format : gl_solid_format;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (mipmap)
|
|
|
|
gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
|
|
|
|
else if (scaled_width == width && scaled_height == height)
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
|
|
|
|
scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
texels += scaled_width * scaled_height;
|
|
|
|
|
|
|
|
if (scaled_width == width && scaled_height == height)
|
|
|
|
{
|
|
|
|
if (!mipmap)
|
|
|
|
{
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
memcpy (scaled, data, width*height*4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
|
|
|
|
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
|
|
|
|
if (mipmap)
|
|
|
|
{
|
|
|
|
int miplevel;
|
|
|
|
|
|
|
|
miplevel = 0;
|
|
|
|
while (scaled_width > 1 || scaled_height > 1)
|
|
|
|
{
|
|
|
|
GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
|
|
|
|
scaled_width >>= 1;
|
|
|
|
scaled_height >>= 1;
|
|
|
|
if (scaled_width < 1)
|
|
|
|
scaled_width = 1;
|
|
|
|
if (scaled_height < 1)
|
|
|
|
scaled_height = 1;
|
|
|
|
miplevel++;
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
done: ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (mipmap)
|
|
|
|
{
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
|
|
|
|
{
|
|
|
|
int i, s;
|
|
|
|
qboolean noalpha;
|
|
|
|
int samples;
|
|
|
|
static unsigned char scaled[1024*512]; // [512*256];
|
|
|
|
int scaled_width, scaled_height;
|
|
|
|
|
|
|
|
s = width*height;
|
|
|
|
// if there are no transparent pixels, make it a 3 component
|
|
|
|
// texture even if it was specified as otherwise
|
|
|
|
if (alpha)
|
|
|
|
{
|
|
|
|
noalpha = true;
|
|
|
|
for (i=0 ; i<s ; i++)
|
|
|
|
{
|
|
|
|
if (data[i] == 255)
|
|
|
|
noalpha = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alpha && noalpha)
|
|
|
|
alpha = false;
|
|
|
|
}
|
|
|
|
for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
|
|
|
|
;
|
|
|
|
for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
|
|
|
|
;
|
|
|
|
|
|
|
|
scaled_width >>= (int)gl_picmip.value;
|
|
|
|
scaled_height >>= (int)gl_picmip.value;
|
|
|
|
|
|
|
|
if (scaled_width > gl_max_size.value)
|
|
|
|
scaled_width = gl_max_size.value;
|
|
|
|
if (scaled_height > gl_max_size.value)
|
|
|
|
scaled_height = gl_max_size.value;
|
|
|
|
|
|
|
|
if (scaled_width * scaled_height > sizeof(scaled))
|
|
|
|
Sys_Error ("GL_LoadTexture: too big");
|
|
|
|
|
|
|
|
samples = 1; // alpha ? gl_alpha_format : gl_solid_format;
|
|
|
|
|
|
|
|
texels += scaled_width * scaled_height;
|
|
|
|
|
|
|
|
if (scaled_width == width && scaled_height == height)
|
|
|
|
{
|
|
|
|
if (!mipmap)
|
|
|
|
{
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
memcpy (scaled, data, width*height);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
|
|
|
|
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
|
|
|
|
if (mipmap)
|
|
|
|
{
|
|
|
|
int miplevel;
|
|
|
|
|
|
|
|
miplevel = 0;
|
|
|
|
while (scaled_width > 1 || scaled_height > 1)
|
|
|
|
{
|
|
|
|
GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
|
|
|
|
scaled_width >>= 1;
|
|
|
|
scaled_height >>= 1;
|
|
|
|
if (scaled_width < 1)
|
|
|
|
scaled_width = 1;
|
|
|
|
if (scaled_height < 1)
|
|
|
|
scaled_height = 1;
|
|
|
|
miplevel++;
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
done: ;
|
|
|
|
|
|
|
|
|
|
|
|
if (mipmap)
|
|
|
|
{
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
GL_Upload8
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
|
|
|
|
{
|
|
|
|
static unsigned trans[640*480]; // FIXME, temporary
|
|
|
|
int i, s;
|
|
|
|
qboolean noalpha;
|
|
|
|
int p;
|
|
|
|
|
|
|
|
s = width*height;
|
|
|
|
// if there are no transparent pixels, make it a 3 component
|
|
|
|
// texture even if it was specified as otherwise
|
|
|
|
if (alpha)
|
|
|
|
{
|
|
|
|
noalpha = true;
|
|
|
|
for (i=0 ; i<s ; i++)
|
|
|
|
{
|
|
|
|
p = data[i];
|
|
|
|
if (p == 255)
|
|
|
|
noalpha = false;
|
|
|
|
trans[i] = d_8to24table[p];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alpha && noalpha)
|
|
|
|
alpha = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (s&3)
|
|
|
|
Sys_Error ("GL_Upload8: s&3");
|
|
|
|
for (i=0 ; i<s ; i+=4)
|
|
|
|
{
|
|
|
|
trans[i] = d_8to24table[data[i]];
|
|
|
|
trans[i+1] = d_8to24table[data[i+1]];
|
|
|
|
trans[i+2] = d_8to24table[data[i+2]];
|
|
|
|
trans[i+3] = d_8to24table[data[i+3]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
|
|
|
|
GL_Upload8_EXT (data, width, height, mipmap, alpha);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
GL_Upload32 (trans, width, height, mipmap, alpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_LoadTexture
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
|
|
|
|
{
|
1999-12-27 17:18:40 +00:00
|
|
|
int i;
|
Created new subdir: uquake. Pick your favorite U word for the meaning --
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified,
Unity, etc. You know the drill.
This takes care of the "standalone" problem with the wrong name, and the
recent snafu with multiple developers working on the same files
simultaneously...expect me (and probably others) to start locking dirs when
updates are taking place.
And yes, this update is really as large as it looks. Software only at the
moment, but I will have the makefile updated to build the GL builds as
well.
1999-12-26 13:51:52 +00:00
|
|
|
gltexture_t *glt;
|
|
|
|
|
|
|
|
// see if the texture is allready present
|
|
|
|
if (identifier[0])
|
|
|
|
{
|
|
|
|
for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
|
|
|
|
{
|
|
|
|
if (!strcmp (identifier, glt->identifier))
|
|
|
|
{
|
|
|
|
if (width != glt->width || height != glt->height)
|
|
|
|
Sys_Error ("GL_LoadTexture: cache mismatch");
|
|
|
|
return gltextures[i].texnum;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
glt = &gltextures[numgltextures];
|
|
|
|
numgltextures++;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy (glt->identifier, identifier);
|
|
|
|
glt->texnum = texture_extension_number;
|
|
|
|
glt->width = width;
|
|
|
|
glt->height = height;
|
|
|
|
glt->mipmap = mipmap;
|
|
|
|
|
|
|
|
GL_Bind(texture_extension_number );
|
|
|
|
|
|
|
|
GL_Upload8 (data, width, height, mipmap, alpha);
|
|
|
|
|
|
|
|
texture_extension_number++;
|
|
|
|
|
|
|
|
return texture_extension_number-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_LoadPicTexture
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
int GL_LoadPicTexture (qpic_t *pic)
|
|
|
|
{
|
|
|
|
return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************/
|
|
|
|
|
|
|
|
static GLenum oldtarget = TEXTURE0_SGIS;
|
|
|
|
|
|
|
|
void GL_SelectTexture (GLenum target)
|
|
|
|
{
|
|
|
|
if (!gl_mtexable)
|
|
|
|
return;
|
|
|
|
qglSelectTextureSGIS(target);
|
|
|
|
if (target == oldtarget)
|
|
|
|
return;
|
|
|
|
cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
|
|
|
|
currenttexture = cnttextures[target-TEXTURE0_SGIS];
|
|
|
|
oldtarget = target;
|
|
|
|
}
|