📄 gl_draw.c
字号:
/*
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;
cvar_t *gl_max_size;
cvar_t *gl_picmip;
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;
int lhcsum; // 2001-09-09 GL Texture memory leak fix by LordHavoc
} gltexture_t;
#define MAX_GLTEXTURES 1024
gltexture_t gltextures[MAX_GLTEXTURES];
int numgltextures;
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 bestx;
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");
return (0); // 2001-12-10 Reduced compiler warnings by Jeff Ford
}
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;
loadedfile_t *fileinfo; // 2001-09-12 Returning information about loaded file by Maddes
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
//
// 2001-09-12 Returning information about loaded file by Maddes start
/*
dat = (qpic_t *)COM_LoadTempFile (path);
if (!dat)
*/
fileinfo = COM_LoadTempFile (path);
if (!fileinfo)
// 2001-09-12 Returning information about loaded file by Maddes end
Sys_Error ("Draw_CachePic: failed to load %s", path);
dat = (qpic_t *)fileinfo->data; // 2001-09-12 Returning information about loaded file by Maddes
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);
}
}
}
// 2001-09-18 New cvar system by Maddes (Init) start
/*
===============
Draw_Init_Cvars
===============
*/
void
Draw_Init_Cvars (void)
{
gl_nobind = Cvar_Get ("gl_nobind", "0", CVAR_ORIGINAL);
gl_max_size = Cvar_Get ("gl_max_size", "1024", CVAR_ORIGINAL);
gl_picmip = Cvar_Get ("gl_picmip", "0", CVAR_ORIGINAL);
// 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");
}
// 2001-09-18 New cvar system by Maddes (Init) end
/*
===============
Draw_Init
===============
*/
void Draw_Init (void)
{
int i;
qpic_t *cb;
byte *dest, *src;
int x, y;
char ver[40];
glpic_t *gl;
int start;
byte *ncdata;
int f, fstep;
loadedfile_t *fileinfo; // 2001-09-12 Returning information about loaded file by Maddes
// 2001-09-18 New cvar system by Maddes (Init) start
/*
gl_nobind = Cvar_Get ("gl_nobind", "0", CVAR_ORIGINAL);
gl_max_size = Cvar_Get ("gl_max_size", "1024", CVAR_ORIGINAL);
gl_picmip = Cvar_Get ("gl_picmip", "0", CVAR_ORIGINAL);
// 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");
*/
// 2001-09-18 New cvar system by Maddes (Init) end
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();
// 2001-09-12 Returning information about loaded file by Maddes start
/*
cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp");
if (!cb)
*/
fileinfo = COM_LoadTempFile ("gfx/conback.lmp");
if (!fileinfo)
// 2001-09-12 Returning information about loaded file by Maddes end
Sys_Error ("Couldn't load gfx/conback.lmp");
cb = (qpic_t *)fileinfo->data; // 2001-09-12 Returning information about loaded file by Maddes
SwapPic (cb);
// hack the version number directly into the pic
#if defined(__linux__)
sprintf (ver, "(%s, Linux %2.2f, gl %4.2f) %4.2f", QIP_VERSION, (float)LINUX_VERSION, (float)GLQUAKE_VERSION, (float)VERSION); // 2001-10-25 QIP version in the console background by Maddes
#else
sprintf (ver, "(%s, gl %4.2f) %4.2f", QIP_VERSION, (float)GLQUAKE_VERSION, (float)VERSION); // 2001-10-25 QIP version in the console background by Maddes
#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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -