quakespasm/source/gl_draw.c
cypress bc28b5c593 NX/VITA: Total UI Re-Scale/Overhaul
Fixes the HUD completely on NX, some HUD issues on VITA. Most VITA Menus
are now properly scaled. Adds social badges to main menu. Fixes load
screens on both platforms.
2023-09-01 11:44:39 -04:00

1420 lines
No EOL
32 KiB
C

/*
Copyright (C) 1996-2001 Id Software, Inc.
Copyright (C) 2002-2009 John Fitzgibbons and others
Copyright (C) 2007-2008 Kristian Duske
Copyright (C) 2010-2014 QuakeSpasm developers
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 -- 2d drawing
#include "quakedef.h"
//extern unsigned char d_15to8table[65536]; //johnfitz -- never used
cvar_t scr_conalpha = {"scr_conalpha", "0.5", CVAR_ARCHIVE}; //johnfitz
cvar_t gl_nobind = {"gl_nobind", "0"};
cvar_t gl_max_size = {"gl_max_size", "4096"};
cvar_t gl_picmip = {"gl_picmip", "0"};
qpic_t *draw_disc;
qpic_t *draw_backtile;
gltexture_t *char_texture; //johnfitz
qpic_t *pic_ovr, *pic_ins; //johnfitz -- new cursor handling
qpic_t *pic_nul; //johnfitz -- for missing gfx, don't crash
qpic_t *sniper_scope;
int zombie_skins[2][2];
//Loading Fill by Crow_bar
float loading_cur_step;
char loading_name[32];
float loading_num_step;
int loading_step;
float loading_cur_step_bk;
//johnfitz -- new pics
byte pic_ovr_data[8][8] =
{
{255,255,255,255,255,255,255,255},
{255, 15, 15, 15, 15, 15, 15,255},
{255, 15, 15, 15, 15, 15, 15, 2},
{255, 15, 15, 15, 15, 15, 15, 2},
{255, 15, 15, 15, 15, 15, 15, 2},
{255, 15, 15, 15, 15, 15, 15, 2},
{255, 15, 15, 15, 15, 15, 15, 2},
{255,255, 2, 2, 2, 2, 2, 2},
};
byte pic_ins_data[9][8] =
{
{ 15, 15,255,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{255, 2, 2,255,255,255,255,255},
};
byte pic_nul_data[8][8] =
{
{252,252,252,252, 0, 0, 0, 0},
{252,252,252,252, 0, 0, 0, 0},
{252,252,252,252, 0, 0, 0, 0},
{252,252,252,252, 0, 0, 0, 0},
{ 0, 0, 0, 0,252,252,252,252},
{ 0, 0, 0, 0,252,252,252,252},
{ 0, 0, 0, 0,252,252,252,252},
{ 0, 0, 0, 0,252,252,252,252},
};
byte pic_stipple_data[8][8] =
{
{255, 0, 0, 0,255, 0, 0, 0},
{ 0, 0,255, 0, 0, 0,255, 0},
{255, 0, 0, 0,255, 0, 0, 0},
{ 0, 0,255, 0, 0, 0,255, 0},
{255, 0, 0, 0,255, 0, 0, 0},
{ 0, 0,255, 0, 0, 0,255, 0},
{255, 0, 0, 0,255, 0, 0, 0},
{ 0, 0,255, 0, 0, 0,255, 0},
};
byte pic_crosshair_data[8][8] =
{
{255,255,255,255,255,255,255,255},
{255,255,255, 8, 9,255,255,255},
{255,255,255, 6, 8, 2,255,255},
{255, 6, 8, 8, 6, 8, 8,255},
{255,255, 2, 8, 8, 2, 2, 2},
{255,255,255, 7, 8, 2,255,255},
{255,255,255,255, 2, 2,255,255},
{255,255,255,255,255,255,255,255},
};
//johnfitz
typedef struct
{
gltexture_t *gltexture;
float sl, tl, sh, th;
} glpic_t;
int gl_lightmap_format = GL_RGBA;
int gl_solid_format = 3;
int gl_alpha_format = 4;
int gl_filter_min = GL_LINEAR;
int gl_filter_max = GL_LINEAR;
int texels;
extern int texture_extension_number;
canvastype currentcanvas = CANVAS_NONE; //johnfitz -- for GL_SetCanvas
//==============================================================================
//
// PIC CACHING
//
//==============================================================================
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];
// 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]; //johnfitz -- removed *4 after BLOCK_HEIGHT
qboolean scrap_dirty;
gltexture_t *scrap_textures[MAX_SCRAPS]; //johnfitz
/*
================
Scrap_AllocBlock
returns an index into scrap_texnums[] 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"); //johnfitz -- correct function name
return 0; //johnfitz -- shut up compiler
}
/*
================
Scrap_Upload -- johnfitz -- now uses TexMgr
================
*/
void Scrap_Upload (void)
{
char name[8];
int i;
for (i=0; i<MAX_SCRAPS; i++)
{
sprintf (name, "scrap%i", i);
scrap_textures[i] = TexMgr_LoadImage (NULL, name, BLOCK_WIDTH, BLOCK_HEIGHT, SRC_INDEXED, scrap_texels[i],
"", (src_offset_t)scrap_texels[i], TEXPREF_ALPHA | TEXPREF_OVERWRITE | TEXPREF_NOPICMIP);
}
scrap_dirty = false;
}
/*
================
Draw_PicFromWad
================
*/
qpic_t *Draw_PicFromWad (const char *name)
{
qpic_t *p;
glpic_t gl;
src_offset_t offset; //johnfitz
p = (qpic_t *) W_GetLumpName (name);
if (!p) return pic_nul; //johnfitz
// load little ones into the scrap
if (p->width < 64 && p->height < 64)
{
int x, y;
int i, j, k;
int texnum;
x = 0;
y = 0;
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];
}
gl.gltexture = scrap_textures[texnum]; //johnfitz -- changed to an array
//johnfitz -- no longer go from 0.01 to 0.99
gl.sl = x/(float)BLOCK_WIDTH;
gl.sh = (x+p->width)/(float)BLOCK_WIDTH;
gl.tl = y/(float)BLOCK_WIDTH;
gl.th = (y+p->height)/(float)BLOCK_WIDTH;
}
else
{
char texturename[64]; //johnfitz
q_snprintf (texturename, sizeof(texturename), "%s:%s", WADFILENAME, name); //johnfitz
offset = (src_offset_t)p - (src_offset_t)wad_base + sizeof(int)*2; //johnfitz
gl.gltexture = TexMgr_LoadImage (NULL, texturename, p->width, p->height, SRC_INDEXED, p->data, WADFILENAME,
offset, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr
gl.sl = 0;
gl.sh = (float)p->width/(float)TexMgr_PadConditional(p->width); //johnfitz
gl.tl = 0;
gl.th = (float)p->height/(float)TexMgr_PadConditional(p->height); //johnfitz
}
memcpy (p->data, &gl, sizeof(glpic_t));
return p;
}
/*
================
Draw_CachePic
================
*/
extern char cwd[MAX_OSPATH];
qpic_t *Draw_CachePic (const char *path)
{
cachepic_t *pic;
int i;
qpic_t *dat;
glpic_t gl;
if (!COM_FileExists(path, NULL))
return NULL;
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);
// Determine whether or not we need to have a source by index or by something else
//
char extension[16];
char path_noext[2*MAX_OSPATH];
COM_StripExtension(path, path_noext, 2*MAX_OSPATH);
strcpy(extension, COM_FileGetExtension(path));
int src_type;
if (!strcmp("tga", extension)) {
src_type = SRC_TGA;
dat = (qpic_t *)LoadTGAPic(path_noext);
if (!dat) {
Host_Error ("Draw_CachePic: failed to load %s", path);
}
} else if (!strcmp("png", extension)) {
src_type = SRC_RGBA;
dat = (qpic_t *)LoadPNGPic(path_noext);
if (!dat) {
Host_Error ("Draw_CachePic: failed to load %s", path);
}
} else {
src_type = SRC_INDEXED;
dat = (qpic_t *)COM_LoadTempFile (path, NULL);
if (!dat) {
Host_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;
// naievil -- modified to change extension
gl.gltexture = TexMgr_LoadImage (NULL, path, dat->width, dat->height, src_type, dat->data, path,
sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr
gl.sl = 0;
gl.sh = (float)dat->width/(float)TexMgr_PadConditional(dat->width); //johnfitz
gl.tl = 0;
gl.th = (float)dat->height/(float)TexMgr_PadConditional(dat->height); //johnfitz
memcpy (pic->pic.data, &gl, sizeof(glpic_t));
return &pic->pic;
}
/*
================
Draw_MakePic -- johnfitz -- generate pics from internal data
================
*/
qpic_t *Draw_MakePic (const char *name, int width, int height, byte *data)
{
int flags = TEXPREF_NEAREST | TEXPREF_ALPHA | TEXPREF_PERSIST | TEXPREF_NOPICMIP | TEXPREF_PAD;
qpic_t *pic;
glpic_t gl;
pic = (qpic_t *) Hunk_Alloc (sizeof(qpic_t) - 4 + sizeof (glpic_t));
pic->width = width;
pic->height = height;
gl.gltexture = TexMgr_LoadImage (NULL, name, width, height, SRC_INDEXED, data, "", (src_offset_t)data, flags);
gl.sl = 0;
gl.sh = (float)width/(float)TexMgr_PadConditional(width);
gl.tl = 0;
gl.th = (float)height/(float)TexMgr_PadConditional(height);
memcpy (pic->data, &gl, sizeof(glpic_t));
return pic;
}
//==============================================================================
//
// INIT
//
//==============================================================================
/*
===============
Draw_LoadPics -- johnfitz
===============
*/
void Draw_LoadPics (void)
{
qpic_t *dat;
dat = (qpic_t *)LoadTGAPic("gfx/charset");
char_texture = TexMgr_LoadImage (NULL, "gfx/charset", dat->width, dat->height, SRC_TGA, dat->data,
"gfx/charset", sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_NEAREST | TEXPREF_NOPICMIP | TEXPREF_CONCHARS);
draw_disc = Draw_PicFromWad ("disc");
draw_backtile = Draw_PicFromWad ("backtile");
}
/*
===============
Draw_NewGame -- johnfitz
===============
*/
void Draw_NewGame (void)
{
cachepic_t *pic;
int i;
// empty scrap and reallocate gltextures
memset(scrap_allocated, 0, sizeof(scrap_allocated));
memset(scrap_texels, 255, sizeof(scrap_texels));
Scrap_Upload (); //creates 2 empty gltextures
// reload wad pics
W_LoadWadFile (); //johnfitz -- filename is now hard-coded for honesty
Draw_LoadPics ();
SCR_LoadPics ();
Sbar_LoadPics ();
// empty lmp cache
for (pic = menu_cachepics, i = 0; i < menu_numcachepics; pic++, i++)
pic->name[0] = 0;
menu_numcachepics = 0;
}
/*
===============
Draw_Init -- johnfitz -- rewritten
===============
*/
void Draw_Init (void)
{
Cvar_RegisterVariable (&scr_conalpha);
// clear scrap and allocate gltextures
memset(scrap_allocated, 0, sizeof(scrap_allocated));
memset(scrap_texels, 255, sizeof(scrap_texels));
Scrap_Upload (); //creates 2 empty textures
// create internal pics
pic_ins = Draw_MakePic ("ins", 8, 9, &pic_ins_data[0][0]);
pic_ovr = Draw_MakePic ("ovr", 8, 8, &pic_ovr_data[0][0]);
pic_nul = Draw_MakePic ("nul", 8, 8, &pic_nul_data[0][0]);
sniper_scope = Draw_CachePic ("gfx/hud/scope.tga");
//zombie_skins[0][0] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR);
//zombie_skins[0][1] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR);
//zombie_skins[1][0] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR);
//zombie_skins[1][1] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR);
// load game pics
Draw_LoadPics ();
Clear_LoadingFill ();
}
//==============================================================================
//
// 2D DRAWING
//
//==============================================================================
/*
================
Draw_CharacterQuadScale
Draw_CharacterQuad with scale parm
================
*/
void Draw_CharacterQuadScale (int x, int y, char num, float s)
{
int row, col;
float frow, fcol, size;
row = num>>4;
col = num&15;
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625*s;
glTexCoord2f (fcol, frow);
glVertex2f (x, y);
glTexCoord2f (fcol + (float)(size/s), frow);
glVertex2f (x+(8*(s)), y);
glTexCoord2f (fcol + (float)(size/s), frow + (float)(size/s));
glVertex2f (x+(8*(s)), y+(8*(s)));
glTexCoord2f (fcol, frow + (float)(size/s));
glVertex2f (x, y+(8*(s)));
}
/*
================
Draw_CharacterQuad -- johnfitz -- seperate function to spit out verts
================
*/
void Draw_CharacterQuad (int x, int y, char num)
{
int row, col;
float frow, fcol, size;
row = num>>4;
col = num&15;
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625;
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);
}
/*
================
Draw_Character -- johnfitz -- modified to call Draw_CharacterQuad
================
*/
void Draw_Character (int x, int y, int num)
{
if (y <= -8)
return; // totally off screen
num &= 255;
if (num == 32)
return; //don't waste verts on spaces
GL_Bind (char_texture);
glBegin (GL_QUADS);
Draw_CharacterQuad (x, y, (char) num);
glEnd ();
}
void Draw_CharacterScale (int x, int y, int num, float scale)
{
if (y <= -8)
return; // totally off screen
num &= 255;
if (num == 32)
return; //don't waste verts on spaces
GL_Bind (char_texture);
glBegin (GL_QUADS);
Draw_CharacterQuadScale (x, y, (char) num, scale);
glEnd ();
}
/*
================
Draw_CharacterRGBA
This is the same as Draw_Character, but with RGBA color codes.
- MotoLegacy and ported to Quakespasm by sB :)
================
*/
void Draw_CharacterRGBA(int x, int y, int num, float r, float g, float b, float a)
{
int row, col;
float frow, fcol, size;
if (y <= -8)
return; // totally off screen
num &= 255;
if (num == 32)
return; //don't waste verts on spaces
glEnable (GL_BLEND);
glColor4f(r, g, b, a);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind (char_texture);
glBegin (GL_QUADS);
row = num>>4;
col = num&15;
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625;
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 ();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
/*
================
Draw_String -- johnfitz -- modified to call Draw_CharacterQuad
================
*/
void Draw_String (int x, int y, const char *str)
{
if (y <= -8)
return; // totally off screen
GL_Bind (char_texture);
glBegin (GL_QUADS);
while (*str)
{
if (*str != 32) //don't waste verts on spaces
Draw_CharacterQuad (x, y, *str);
str++;
x += 8;
}
glEnd ();
}
/*
================
Draw_ColoredStringScale
Draw_ColoredString with scale parm
================
*/
void Draw_ColoredStringScale (int x, int y, const char *str, float r, float g, float b, float a, float s)
{
if (y <= -8)
return; // totally off screen
glEnable (GL_BLEND);
glColor4f(r, g, b, a);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind (char_texture);
glBegin (GL_QUADS);
while (*str)
{
if (*str != 32) //don't waste verts on spaces
Draw_CharacterQuadScale (x, y, *str, s);
str++;
x += 8*s;
}
glEnd ();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
/*
================
Draw_ColoredString
Assume that all rgba values are divided by 255 already
================
*/
void Draw_ColoredString (int x, int y, const char *str, float r, float g, float b, float a)
{
if (y <= -8)
return; // totally off screen
glEnable (GL_BLEND);
glColor4f(r, g, b, a);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind (char_texture);
glBegin (GL_QUADS);
while (*str)
{
if (*str != 32) //don't waste verts on spaces
Draw_CharacterQuad (x, y, *str);
str++;
x += 8;
}
glEnd ();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
/*
=============
Draw_ColorPic
=============
*/
void Draw_ColorPic (int x, int y, qpic_t *pic, float r, float g, float b, float alpha)
{
glpic_t *gl;
if (alpha <= 1.0) {
glEnable (GL_BLEND);
glColor4f (r,g,b,alpha);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
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 ();
if (alpha <= 1.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
}
//sB needed a way to stretch round pics
void Draw_ColorStretchPic (int x, int y, int width, int height, qpic_t *pic, float r, float g, float b, float alpha)
{
glpic_t *gl;
if (alpha <= 1.0) {
glEnable (GL_BLEND);
glColor4f (r,g,b,alpha);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
#ifdef VITA
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x+width, y);
glTexCoord2f (1, 1);
glVertex2f (x+width, y+height);
glTexCoord2f (0, 1);
glVertex2f (x, y+height);
#else
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+width, y+height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+height);
#endif
glEnd ();
if (alpha <= 1.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
}
/*
=============
Draw_StretchPic
=============
*/
void Draw_StretchPic (int x, int y, qpic_t *pic, int x_value, int y_value)
{
glpic_t *gl;
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
#ifdef VITA
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x+x_value, y);
glTexCoord2f (1, 1);
glVertex2f (x+x_value, y+y_value);
glTexCoord2f (0, 1);
glVertex2f (x, y+y_value);
#else
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+x_value, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+x_value, y+y_value);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+y_value);
#endif
glEnd ();
}
/*
=============
Draw_Pic -- johnfitz -- modified
=============
*/
void Draw_Pic (int x, int y, qpic_t *pic)
{
glpic_t *gl;
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
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_Pic -- johnfitz -- modified
=============
*/
void Draw_SubPic(int x, int y, int width, int height, int start_x, int start_y, int end_x, int end_y, qpic_t *pic)
{
glpic_t *gl;
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
#ifdef VITA
// Calculate texture coordinates for the subsection
float subTexLeft = (start_x / (float)pic->width);
float subTexRight = (end_x / (float)pic->width);
float subTexTop = (start_y / (float)pic->height);
float subTexBottom = (end_y / (float)pic->height);
#else
// Calculate texture coordinates for the subsection
float subTexLeft = gl->sl + (start_x / (float)pic->width);
float subTexRight = gl->sl + (end_x / (float)pic->width);
float subTexTop = gl->tl + (start_y / (float)pic->height);
float subTexBottom = gl->tl + (end_y / (float)pic->height);
#endif // VITA
glTexCoord2f(subTexLeft, subTexTop);
glVertex2f(x, y);
glTexCoord2f(subTexRight, subTexTop);
glVertex2f(x + width, y);
glTexCoord2f(subTexRight, subTexBottom);
glVertex2f(x + width, y + height);
glTexCoord2f(subTexLeft, subTexBottom);
glVertex2f(x, y + height);
glEnd ();
}
// motolegacy -- ultimate draw function!! probably annihilates gl calls so use wisely lol
// TODO: color shifting?
void Draw_AlphaStretchPic (int x, int y, int width, int height, float alpha, qpic_t *pic)
{
glpic_t *gl;
if (alpha <= 1.0) {
glEnable (GL_BLEND);
glColor4f (1,1,1,alpha);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
#ifdef VITA
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x+width, y);
glTexCoord2f (1, 1);
glVertex2f (x+width, y+height);
glTexCoord2f (0, 1);
glVertex2f (x, y+height);
#else
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+width, y+height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+height);
#endif
glEnd ();
if (alpha <= 1.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
}
void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
{
glpic_t *gl;
if (alpha <= 1.0) {
glEnable (GL_BLEND);
glColor4f (1,1,1,alpha);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
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 ();
if (alpha <= 1.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
}
/*
=============
Draw_TransPicTranslate -- johnfitz -- rewritten to use texmgr to do translation
Only used for the player color selection menu
=============
*/
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, int top, int bottom)
{
static int oldtop = -2;
static int oldbottom = -2;
if (top != oldtop || bottom != oldbottom)
{
glpic_t *p = (glpic_t *)pic->data;
gltexture_t *glt = p->gltexture;
oldtop = top;
oldbottom = bottom;
TexMgr_ReloadImage (glt, top, bottom);
}
Draw_Pic (x, y, pic);
}
/*
================
Draw_ConsoleBackground -- johnfitz -- rewritten
================
*/
void Draw_ConsoleBackground (void)
{
GL_SetCanvas (CANVAS_CONSOLE); //in case this is called from weird places
Draw_FillByColor (0, 0, vid.conwidth, vid.conheight, 1, 1, 1, 200);
}
/*
================
Draw_LoadingFill
By Crow_bar
================
*/
void Draw_LoadingFill(void)
{
if(!loading_num_step)
return;
#ifdef VITA
int size = 16;
int max_step = 500;
int x = (vid.width / 2) - (max_step / 2);
int y = vid.height - (size/ 2) - 40;
#else
int size = 8;
int max_step = 350;
int x = (640 / 2) - (max_step / 2);
int y = 360 - (size/ 2) - 29;
#endif // VITA
int l;
char str[64];
char* text;
if(loading_cur_step > loading_num_step)
loading_cur_step = loading_num_step;
if (loading_cur_step < loading_cur_step_bk)
loading_cur_step = loading_cur_step_bk;
if (loading_cur_step == loading_num_step && loading_cur_step_bk != loading_num_step)
loading_cur_step = loading_cur_step_bk;
float loadsize = loading_cur_step * (max_step / loading_num_step);
Draw_FillByColor (x - 2, y - 2, max_step + 4, size + 4, 69, 69, 69, 255);
Draw_FillByColor (x, y, loadsize, size, 0, 0, 0, 200);
switch(loading_step) {
case 1: text = "Loading Models.."; break;
case 2: text = "Loading World.."; break;
case 3: text = "Executing Spawn Functions.."; break;
case 4: text = "Loading Sounds.."; break;
default: text = "Initializing.."; break;
}
l = strlen (text);
#ifdef VITA
Draw_ColoredStringScale((vid.width - l*16)/2, y, text, 1, 1, 1, 1, 2.0f);
#else
Draw_String((640 - l*8)/2, y, text);
#endif // VITA
loading_cur_step_bk = loading_cur_step;
}
void Clear_LoadingFill (void)
{
//it is end loading
loading_cur_step = 0;
loading_cur_step_bk = 0;
loading_num_step = 0;
loading_step = -1;
memset(loading_name, 0, sizeof(loading_name));
}
/*
=============
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)
{
glpic_t *gl;
gl = (glpic_t *)draw_backtile->data;
glColor3f (1,1,1);
GL_Bind (gl->gltexture);
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, float alpha) //johnfitz -- added alpha
{
byte *pal = (byte *)d_8to24table; //johnfitz -- use d_8to24table instead of host_basepal
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND); //johnfitz -- for alpha
glDisable (GL_ALPHA_TEST); //johnfitz -- for alpha
glColor4f (pal[c*4]/255.0, pal[c*4+1]/255.0, pal[c*4+2]/255.0, alpha); //johnfitz -- added alpha
glBegin (GL_QUADS);
glVertex2f (x,y);
glVertex2f (x+w, y);
glVertex2f (x+w, y+h);
glVertex2f (x, y+h);
glEnd ();
glColor3f (1,1,1);
glDisable (GL_BLEND); //johnfitz -- for alpha
glEnable(GL_ALPHA_TEST); //johnfitz -- for alpha
glEnable (GL_TEXTURE_2D);
}
/*
=============
Draw_FillByColor
Fills a box of pixels with a single color not in basepal
=============
*/
void Draw_FillByColor (int x, int y, int w, int h, float r, float g, float b, float a)
{
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND);
glDisable (GL_ALPHA_TEST);
glColor4f (r/255, g/255, b/255, a/255);
glBegin (GL_QUADS);
glVertex2f (x,y);
glVertex2f (x+w, y);
glVertex2f (x+w, y+h);
glVertex2f (x, y+h);
glEnd ();
glColor4f (1,1,1,1);
glDisable (GL_BLEND);
glEnable(GL_ALPHA_TEST);
glEnable (GL_TEXTURE_2D);
}
/*
================
Draw_FadeScreen -- johnfitz -- revised
================
*/
void Draw_FadeScreen (void)
{
GL_SetCanvas (CANVAS_DEFAULT);
glEnable (GL_BLEND);
glDisable (GL_ALPHA_TEST);
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, 0.5);
glBegin (GL_QUADS);
glVertex2f (0,0);
glVertex2f (glwidth, 0);
glVertex2f (glwidth, glheight);
glVertex2f (0, glheight);
glEnd ();
glColor4f (1,1,1,1);
glEnable (GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
Sbar_Changed();
}
/*
================
GL_SetCanvas -- johnfitz -- support various canvas types
================
*/
void GL_SetCanvas (canvastype newcanvas)
{
extern vrect_t scr_vrect;
float s;
int lines;
if (newcanvas == currentcanvas)
return;
currentcanvas = newcanvas;
glMatrixMode(GL_PROJECTION);
glLoadIdentity ();
switch(newcanvas)
{
case CANVAS_DEFAULT:
glOrtho (0, glwidth, glheight, 0, -99999, 99999);
glViewport (glx, gly, glwidth, glheight);
break;
case CANVAS_CONSOLE:
lines = vid.conheight - (scr_con_current * vid.conheight / glheight);
glOrtho (0, vid.conwidth, vid.conheight + lines, lines, -99999, 99999);
glViewport (glx, gly, glwidth, glheight);
break;
case CANVAS_MENU:
s = q_min((float)glwidth / 320.0, (float)glheight / 200.0);
s = CLAMP (1.0, scr_menuscale.value, s);
// ericw -- doubled width to 640 to accommodate long keybindings
glOrtho (0, 640, 200, 0, -99999, 99999);
glViewport (glx + (glwidth - 320*s) / 2, gly + (glheight - 200*s) / 2, 640*s, 200*s);
break;
case CANVAS_SBAR:
s = CLAMP (1.0, scr_sbarscale.value, (float)glwidth / 320.0);
if (cl.gametype == GAME_DEATHMATCH)
{
glOrtho (0, glwidth / s, 48, 0, -99999, 99999);
glViewport (glx, gly, glwidth, 48*s);
}
else
{
glOrtho (0, 320, 48, 0, -99999, 99999);
glViewport (glx + (glwidth - 320*s) / 2, gly, 320*s, 48*s);
}
break;
case CANVAS_WARPIMAGE:
glOrtho (0, 128, 0, 128, -99999, 99999);
glViewport (glx, gly+glheight-gl_warpimagesize, gl_warpimagesize, gl_warpimagesize);
break;
case CANVAS_CROSSHAIR: //0,0 is center of viewport
s = CLAMP (1.0, scr_crosshairscale.value, 10.0);
glOrtho (scr_vrect.width/-2/s, scr_vrect.width/2/s, scr_vrect.height/2/s, scr_vrect.height/-2/s, -99999, 99999);
glViewport (scr_vrect.x, glheight - scr_vrect.y - scr_vrect.height, scr_vrect.width & ~1, scr_vrect.height & ~1);
break;
case CANVAS_BOTTOMLEFT: //used by devstats
s = (float)glwidth/vid.conwidth; //use console scale
glOrtho (0, 320, 200, 0, -99999, 99999);
glViewport (glx, gly, 320*s, 200*s);
break;
case CANVAS_BOTTOMRIGHT: //used by fps/clock
s = (float)glwidth/vid.conwidth; //use console scale
glOrtho (0, 320, 200, 0, -99999, 99999);
glViewport (glx+glwidth-320*s, gly, 320*s, 200*s);
break;
case CANVAS_TOPRIGHT: //used by disc
s = 1;
glOrtho (0, 320, 200, 0, -99999, 99999);
glViewport (glx+glwidth-320*s, gly+glheight-200*s, 320*s, 200*s);
break;
case CANVAS_USEPRINT:
s = (float)glwidth/vid.conwidth; //use console scale
glOrtho (0, glwidth, glheight, 0, -99999, 99999);
glViewport (glx, gly, glwidth*s, glheight*s);
break;
case CANVAS_HUD: // FIXME: Workaround for Vita build, would be better to rework completely gl_hud.c code.
s = (float)glwidth/vid.conwidth; //use console scale
s *= 2;
glOrtho (0, glwidth, glheight, 0, -99999, 99999);
glViewport (glx, gly, glwidth*s, glheight*s);
break;
default:
Sys_Error ("GL_SetCanvas: bad canvas type");
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
}
/*
================
GL_Set2D -- johnfitz -- rewritten
================
*/
void GL_Set2D (void)
{
currentcanvas = CANVAS_INVALID;
GL_SetCanvas (CANVAS_DEFAULT);
glDisable (GL_DEPTH_TEST);
glDisable (GL_CULL_FACE);
glDisable (GL_BLEND);
glEnable(GL_ALPHA_TEST);
glColor4f (1,1,1,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;
}
}
}
/*
int loading_cur_step;
int loading_num_step;
void Clear_LoadingFill (void)
{
//it is end loading
loading_cur_step = 0;
loading_num_step = 0;
}
*/
/*
=============
loadtextureimage
=============
*/
gltexture_t *loadtextureimage (char* filename)
{
byte *data;
glpic_t gl;
int w, h;
data = Image_LoadImage (filename, &w, &h);
if(!data)
{
Sys_Error("loadtextureimage: Cannot load the image %s\n", filename);
//return 0;
}
gl.gltexture = TexMgr_LoadImage (NULL, filename, w, h, SRC_RGBA, data, filename, sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_NEAREST | TEXPREF_NOPICMIP);
return gl.gltexture;
}