gl_draw.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // draw.c -- this is the only file outside the refresh that touches the
  16. // vid buffer
  17. #include "quakedef.h"
  18. extern unsigned char d_15to8table[65536];
  19. extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor;
  20. cvar_t gl_nobind = {"gl_nobind", "0"};
  21. cvar_t gl_max_size = {"gl_max_size", "1024"};
  22. cvar_t gl_picmip = {"gl_picmip", "0"};
  23. byte *draw_chars; // 8*8 graphic characters
  24. qpic_t *draw_disc;
  25. qpic_t *draw_backtile;
  26. int translate_texture;
  27. int char_texture;
  28. int cs_texture; // crosshair texture
  29. static byte cs_data[64] = {
  30. 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  31. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  32. 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  33. 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff,
  34. 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  35. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  36. 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  37. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  38. };
  39. typedef struct
  40. {
  41. int texnum;
  42. float sl, tl, sh, th;
  43. } glpic_t;
  44. byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
  45. qpic_t *conback = (qpic_t *)&conback_buffer;
  46. int gl_lightmap_format = 4;
  47. int gl_solid_format = 3;
  48. int gl_alpha_format = 4;
  49. int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
  50. int gl_filter_max = GL_LINEAR;
  51. int texels;
  52. typedef struct
  53. {
  54. int texnum;
  55. char identifier[64];
  56. int width, height;
  57. qboolean mipmap;
  58. } gltexture_t;
  59. #define MAX_GLTEXTURES 1024
  60. gltexture_t gltextures[MAX_GLTEXTURES];
  61. int numgltextures;
  62. void GL_Bind (int texnum)
  63. {
  64. if (gl_nobind.value)
  65. texnum = char_texture;
  66. if (currenttexture == texnum)
  67. return;
  68. currenttexture = texnum;
  69. #ifdef _WIN32
  70. bindTexFunc (GL_TEXTURE_2D, texnum);
  71. #else
  72. glBindTexture (GL_TEXTURE_2D, texnum);
  73. #endif
  74. }
  75. /*
  76. =============================================================================
  77. scrap allocation
  78. Allocate all the little status bar obejcts into a single texture
  79. to crutch up stupid hardware / drivers
  80. =============================================================================
  81. */
  82. #define MAX_SCRAPS 1
  83. #define BLOCK_WIDTH 256
  84. #define BLOCK_HEIGHT 256
  85. int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
  86. byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
  87. qboolean scrap_dirty;
  88. int scrap_texnum;
  89. // returns a texture number and the position inside it
  90. int Scrap_AllocBlock (int w, int h, int *x, int *y)
  91. {
  92. int i, j;
  93. int best, best2;
  94. int texnum;
  95. for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
  96. {
  97. best = BLOCK_HEIGHT;
  98. for (i=0 ; i<BLOCK_WIDTH-w ; i++)
  99. {
  100. best2 = 0;
  101. for (j=0 ; j<w ; j++)
  102. {
  103. if (scrap_allocated[texnum][i+j] >= best)
  104. break;
  105. if (scrap_allocated[texnum][i+j] > best2)
  106. best2 = scrap_allocated[texnum][i+j];
  107. }
  108. if (j == w)
  109. { // this is a valid spot
  110. *x = i;
  111. *y = best = best2;
  112. }
  113. }
  114. if (best + h > BLOCK_HEIGHT)
  115. continue;
  116. for (i=0 ; i<w ; i++)
  117. scrap_allocated[texnum][*x + i] = best + h;
  118. return texnum;
  119. }
  120. Sys_Error ("Scrap_AllocBlock: full");
  121. return 0;
  122. }
  123. int scrap_uploads;
  124. void Scrap_Upload (void)
  125. {
  126. scrap_uploads++;
  127. GL_Bind(scrap_texnum);
  128. GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
  129. scrap_dirty = false;
  130. }
  131. //=============================================================================
  132. /* Support Routines */
  133. typedef struct cachepic_s
  134. {
  135. char name[MAX_QPATH];
  136. qpic_t pic;
  137. byte padding[32]; // for appended glpic
  138. } cachepic_t;
  139. #define MAX_CACHED_PICS 128
  140. cachepic_t menu_cachepics[MAX_CACHED_PICS];
  141. int menu_numcachepics;
  142. byte menuplyr_pixels[4096];
  143. int pic_texels;
  144. int pic_count;
  145. qpic_t *Draw_PicFromWad (char *name)
  146. {
  147. qpic_t *p;
  148. glpic_t *gl;
  149. p = W_GetLumpName (name);
  150. gl = (glpic_t *)p->data;
  151. // load little ones into the scrap
  152. if (p->width < 64 && p->height < 64)
  153. {
  154. int x, y;
  155. int i, j, k;
  156. int texnum;
  157. texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
  158. scrap_dirty = true;
  159. k = 0;
  160. for (i=0 ; i<p->height ; i++)
  161. for (j=0 ; j<p->width ; j++, k++)
  162. scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
  163. texnum += scrap_texnum;
  164. gl->texnum = texnum;
  165. gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
  166. gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
  167. gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
  168. gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
  169. pic_count++;
  170. pic_texels += p->width*p->height;
  171. }
  172. else
  173. {
  174. gl->texnum = GL_LoadPicTexture (p);
  175. gl->sl = 0;
  176. gl->sh = 1;
  177. gl->tl = 0;
  178. gl->th = 1;
  179. }
  180. return p;
  181. }
  182. /*
  183. ================
  184. Draw_CachePic
  185. ================
  186. */
  187. qpic_t *Draw_CachePic (char *path)
  188. {
  189. cachepic_t *pic;
  190. int i;
  191. qpic_t *dat;
  192. glpic_t *gl;
  193. for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
  194. if (!strcmp (path, pic->name))
  195. return &pic->pic;
  196. if (menu_numcachepics == MAX_CACHED_PICS)
  197. Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
  198. menu_numcachepics++;
  199. strcpy (pic->name, path);
  200. //
  201. // load the pic from disk
  202. //
  203. dat = (qpic_t *)COM_LoadTempFile (path);
  204. if (!dat)
  205. Sys_Error ("Draw_CachePic: failed to load %s", path);
  206. SwapPic (dat);
  207. // HACK HACK HACK --- we need to keep the bytes for
  208. // the translatable player picture just for the menu
  209. // configuration dialog
  210. if (!strcmp (path, "gfx/menuplyr.lmp"))
  211. memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
  212. pic->pic.width = dat->width;
  213. pic->pic.height = dat->height;
  214. gl = (glpic_t *)pic->pic.data;
  215. gl->texnum = GL_LoadPicTexture (dat);
  216. gl->sl = 0;
  217. gl->sh = 1;
  218. gl->tl = 0;
  219. gl->th = 1;
  220. return &pic->pic;
  221. }
  222. void Draw_CharToConback (int num, byte *dest)
  223. {
  224. int row, col;
  225. byte *source;
  226. int drawline;
  227. int x;
  228. row = num>>4;
  229. col = num&15;
  230. source = draw_chars + (row<<10) + (col<<3);
  231. drawline = 8;
  232. while (drawline--)
  233. {
  234. for (x=0 ; x<8 ; x++)
  235. if (source[x] != 255)
  236. dest[x] = 0x60 + source[x];
  237. source += 128;
  238. dest += 320;
  239. }
  240. }
  241. typedef struct
  242. {
  243. char *name;
  244. int minimize, maximize;
  245. } glmode_t;
  246. glmode_t modes[] = {
  247. {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
  248. {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
  249. {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
  250. {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
  251. {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
  252. {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
  253. };
  254. /*
  255. ===============
  256. Draw_TextureMode_f
  257. ===============
  258. */
  259. void Draw_TextureMode_f (void)
  260. {
  261. int i;
  262. gltexture_t *glt;
  263. if (Cmd_Argc() == 1)
  264. {
  265. for (i=0 ; i< 6 ; i++)
  266. if (gl_filter_min == modes[i].minimize)
  267. {
  268. Con_Printf ("%s\n", modes[i].name);
  269. return;
  270. }
  271. Con_Printf ("current filter is unknown???\n");
  272. return;
  273. }
  274. for (i=0 ; i< 6 ; i++)
  275. {
  276. if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
  277. break;
  278. }
  279. if (i == 6)
  280. {
  281. Con_Printf ("bad filter name\n");
  282. return;
  283. }
  284. gl_filter_min = modes[i].minimize;
  285. gl_filter_max = modes[i].maximize;
  286. // change all the existing mipmap texture objects
  287. for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  288. {
  289. if (glt->mipmap)
  290. {
  291. GL_Bind (glt->texnum);
  292. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  293. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  294. }
  295. }
  296. }
  297. /*
  298. ===============
  299. Draw_Init
  300. ===============
  301. */
  302. void Draw_Init (void)
  303. {
  304. int i;
  305. qpic_t *cb;
  306. byte *dest;
  307. int x;
  308. char ver[40];
  309. glpic_t *gl;
  310. int start;
  311. byte *ncdata;
  312. Cvar_RegisterVariable (&gl_nobind);
  313. Cvar_RegisterVariable (&gl_max_size);
  314. Cvar_RegisterVariable (&gl_picmip);
  315. // 3dfx can only handle 256 wide textures
  316. if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
  317. !Q_strncasecmp ((char *)gl_renderer, "Mesa",4))
  318. Cvar_Set ("gl_max_size", "256");
  319. Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
  320. // load the console background and the charset
  321. // by hand, because we need to write the version
  322. // string into the background before turning
  323. // it into a texture
  324. draw_chars = W_GetLumpName ("conchars");
  325. for (i=0 ; i<256*64 ; i++)
  326. if (draw_chars[i] == 0)
  327. draw_chars[i] = 255; // proper transparent color
  328. // now turn them into textures
  329. char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true);
  330. // Draw_CrosshairAdjust();
  331. cs_texture = GL_LoadTexture ("crosshair", 8, 8, cs_data, false, true);
  332. start = Hunk_LowMark ();
  333. cb = (qpic_t *)COM_LoadHunkFile ("gfx/conback.lmp");
  334. if (!cb)
  335. Sys_Error ("Couldn't load gfx/conback.lmp");
  336. SwapPic (cb);
  337. sprintf (ver, "%4.2f", VERSION);
  338. dest = cb->data + 320 + 320*186 - 11 - 8*strlen(ver);
  339. for (x=0 ; x<strlen(ver) ; x++)
  340. Draw_CharToConback (ver[x], dest+(x<<3));
  341. #if 0
  342. conback->width = vid.conwidth;
  343. conback->height = vid.conheight;
  344. // scale console to vid size
  345. dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback");
  346. for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth)
  347. {
  348. src = cb->data + cb->width * (y*cb->height/vid.conheight);
  349. if (vid.conwidth == cb->width)
  350. memcpy (dest, src, vid.conwidth);
  351. else
  352. {
  353. f = 0;
  354. fstep = cb->width*0x10000/vid.conwidth;
  355. for (x=0 ; x<vid.conwidth ; x+=4)
  356. {
  357. dest[x] = src[f>>16];
  358. f += fstep;
  359. dest[x+1] = src[f>>16];
  360. f += fstep;
  361. dest[x+2] = src[f>>16];
  362. f += fstep;
  363. dest[x+3] = src[f>>16];
  364. f += fstep;
  365. }
  366. }
  367. }
  368. #else
  369. conback->width = cb->width;
  370. conback->height = cb->height;
  371. ncdata = cb->data;
  372. #endif
  373. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  374. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  375. gl = (glpic_t *)conback->data;
  376. gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false);
  377. gl->sl = 0;
  378. gl->sh = 1;
  379. gl->tl = 0;
  380. gl->th = 1;
  381. conback->width = vid.conwidth;
  382. conback->height = vid.conheight;
  383. // free loaded console
  384. Hunk_FreeToLowMark (start);
  385. // save a texture slot for translated picture
  386. translate_texture = texture_extension_number++;
  387. // save slots for scraps
  388. scrap_texnum = texture_extension_number;
  389. texture_extension_number += MAX_SCRAPS;
  390. //
  391. // get the other pics we need
  392. //
  393. draw_disc = Draw_PicFromWad ("disc");
  394. draw_backtile = Draw_PicFromWad ("backtile");
  395. }
  396. /*
  397. ================
  398. Draw_Character
  399. Draws one 8*8 graphics character with 0 being transparent.
  400. It can be clipped to the top of the screen to allow the console to be
  401. smoothly scrolled off.
  402. ================
  403. */
  404. void Draw_Character (int x, int y, int num)
  405. {
  406. int row, col;
  407. float frow, fcol, size;
  408. if (num == 32)
  409. return; // space
  410. num &= 255;
  411. if (y <= -8)
  412. return; // totally off screen
  413. row = num>>4;
  414. col = num&15;
  415. frow = row*0.0625;
  416. fcol = col*0.0625;
  417. size = 0.0625;
  418. GL_Bind (char_texture);
  419. glBegin (GL_QUADS);
  420. glTexCoord2f (fcol, frow);
  421. glVertex2f (x, y);
  422. glTexCoord2f (fcol + size, frow);
  423. glVertex2f (x+8, y);
  424. glTexCoord2f (fcol + size, frow + size);
  425. glVertex2f (x+8, y+8);
  426. glTexCoord2f (fcol, frow + size);
  427. glVertex2f (x, y+8);
  428. glEnd ();
  429. }
  430. /*
  431. ================
  432. Draw_String
  433. ================
  434. */
  435. void Draw_String (int x, int y, char *str)
  436. {
  437. while (*str)
  438. {
  439. Draw_Character (x, y, *str);
  440. str++;
  441. x += 8;
  442. }
  443. }
  444. /*
  445. ================
  446. Draw_Alt_String
  447. ================
  448. */
  449. void Draw_Alt_String (int x, int y, char *str)
  450. {
  451. while (*str)
  452. {
  453. Draw_Character (x, y, (*str) | 0x80);
  454. str++;
  455. x += 8;
  456. }
  457. }
  458. void Draw_Crosshair(void)
  459. {
  460. int x, y;
  461. extern vrect_t scr_vrect;
  462. unsigned char *pColor;
  463. if (crosshair.value == 2) {
  464. x = scr_vrect.x + scr_vrect.width/2 - 3 + cl_crossx.value;
  465. y = scr_vrect.y + scr_vrect.height/2 - 3 + cl_crossy.value;
  466. glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  467. pColor = (unsigned char *) &d_8to24table[(byte) crosshaircolor.value];
  468. glColor4ubv ( pColor );
  469. GL_Bind (cs_texture);
  470. glBegin (GL_QUADS);
  471. glTexCoord2f (0, 0);
  472. glVertex2f (x - 4, y - 4);
  473. glTexCoord2f (1, 0);
  474. glVertex2f (x+12, y-4);
  475. glTexCoord2f (1, 1);
  476. glVertex2f (x+12, y+12);
  477. glTexCoord2f (0, 1);
  478. glVertex2f (x - 4, y+12);
  479. glEnd ();
  480. glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
  481. } else if (crosshair.value)
  482. Draw_Character (scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value,
  483. scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value,
  484. '+');
  485. }
  486. /*
  487. ================
  488. Draw_DebugChar
  489. Draws a single character directly to the upper right corner of the screen.
  490. This is for debugging lockups by drawing different chars in different parts
  491. of the code.
  492. ================
  493. */
  494. void Draw_DebugChar (char num)
  495. {
  496. }
  497. /*
  498. =============
  499. Draw_Pic
  500. =============
  501. */
  502. void Draw_Pic (int x, int y, qpic_t *pic)
  503. {
  504. glpic_t *gl;
  505. if (scrap_dirty)
  506. Scrap_Upload ();
  507. gl = (glpic_t *)pic->data;
  508. glColor4f (1,1,1,1);
  509. GL_Bind (gl->texnum);
  510. glBegin (GL_QUADS);
  511. glTexCoord2f (gl->sl, gl->tl);
  512. glVertex2f (x, y);
  513. glTexCoord2f (gl->sh, gl->tl);
  514. glVertex2f (x+pic->width, y);
  515. glTexCoord2f (gl->sh, gl->th);
  516. glVertex2f (x+pic->width, y+pic->height);
  517. glTexCoord2f (gl->sl, gl->th);
  518. glVertex2f (x, y+pic->height);
  519. glEnd ();
  520. }
  521. /*
  522. =============
  523. Draw_AlphaPic
  524. =============
  525. */
  526. void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
  527. {
  528. glpic_t *gl;
  529. if (scrap_dirty)
  530. Scrap_Upload ();
  531. gl = (glpic_t *)pic->data;
  532. glDisable(GL_ALPHA_TEST);
  533. glEnable (GL_BLEND);
  534. // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  535. glCullFace(GL_FRONT);
  536. glColor4f (1,1,1,alpha);
  537. GL_Bind (gl->texnum);
  538. glBegin (GL_QUADS);
  539. glTexCoord2f (gl->sl, gl->tl);
  540. glVertex2f (x, y);
  541. glTexCoord2f (gl->sh, gl->tl);
  542. glVertex2f (x+pic->width, y);
  543. glTexCoord2f (gl->sh, gl->th);
  544. glVertex2f (x+pic->width, y+pic->height);
  545. glTexCoord2f (gl->sl, gl->th);
  546. glVertex2f (x, y+pic->height);
  547. glEnd ();
  548. glColor4f (1,1,1,1);
  549. glEnable(GL_ALPHA_TEST);
  550. glDisable (GL_BLEND);
  551. }
  552. void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
  553. {
  554. glpic_t *gl;
  555. float newsl, newtl, newsh, newth;
  556. float oldglwidth, oldglheight;
  557. if (scrap_dirty)
  558. Scrap_Upload ();
  559. gl = (glpic_t *)pic->data;
  560. oldglwidth = gl->sh - gl->sl;
  561. oldglheight = gl->th - gl->tl;
  562. newsl = gl->sl + (srcx*oldglwidth)/pic->width;
  563. newsh = newsl + (width*oldglwidth)/pic->width;
  564. newtl = gl->tl + (srcy*oldglheight)/pic->height;
  565. newth = newtl + (height*oldglheight)/pic->height;
  566. glColor4f (1,1,1,1);
  567. GL_Bind (gl->texnum);
  568. glBegin (GL_QUADS);
  569. glTexCoord2f (newsl, newtl);
  570. glVertex2f (x, y);
  571. glTexCoord2f (newsh, newtl);
  572. glVertex2f (x+width, y);
  573. glTexCoord2f (newsh, newth);
  574. glVertex2f (x+width, y+height);
  575. glTexCoord2f (newsl, newth);
  576. glVertex2f (x, y+height);
  577. glEnd ();
  578. }
  579. /*
  580. =============
  581. Draw_TransPic
  582. =============
  583. */
  584. void Draw_TransPic (int x, int y, qpic_t *pic)
  585. {
  586. if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 ||
  587. (unsigned)(y + pic->height) > vid.height)
  588. {
  589. Sys_Error ("Draw_TransPic: bad coordinates");
  590. }
  591. Draw_Pic (x, y, pic);
  592. }
  593. /*
  594. =============
  595. Draw_TransPicTranslate
  596. Only used for the player color selection menu
  597. =============
  598. */
  599. void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
  600. {
  601. int v, u, c;
  602. unsigned trans[64*64], *dest;
  603. byte *src;
  604. int p;
  605. GL_Bind (translate_texture);
  606. c = pic->width * pic->height;
  607. dest = trans;
  608. for (v=0 ; v<64 ; v++, dest += 64)
  609. {
  610. src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
  611. for (u=0 ; u<64 ; u++)
  612. {
  613. p = src[(u*pic->width)>>6];
  614. if (p == 255)
  615. dest[u] = p;
  616. else
  617. dest[u] = d_8to24table[translation[p]];
  618. }
  619. }
  620. glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  621. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  622. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  623. glColor3f (1,1,1);
  624. glBegin (GL_QUADS);
  625. glTexCoord2f (0, 0);
  626. glVertex2f (x, y);
  627. glTexCoord2f (1, 0);
  628. glVertex2f (x+pic->width, y);
  629. glTexCoord2f (1, 1);
  630. glVertex2f (x+pic->width, y+pic->height);
  631. glTexCoord2f (0, 1);
  632. glVertex2f (x, y+pic->height);
  633. glEnd ();
  634. }
  635. /*
  636. ================
  637. Draw_ConsoleBackground
  638. ================
  639. */
  640. void Draw_ConsoleBackground (int lines)
  641. {
  642. char ver[80];
  643. int x, i;
  644. int y;
  645. y = (vid.height * 3) >> 2;
  646. if (lines > y)
  647. Draw_Pic(0, lines-vid.height, conback);
  648. else
  649. Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
  650. // hack the version number directly into the pic
  651. // y = lines-186;
  652. y = lines-14;
  653. if (!cls.download) {
  654. #ifdef __linux__
  655. sprintf (ver, "LinuxGL (%4.2f) QuakeWorld", LINUX_VERSION);
  656. #else
  657. sprintf (ver, "GL (%4.2f) QuakeWorld", GLQUAKE_VERSION);
  658. #endif
  659. x = vid.conwidth - (strlen(ver)*8 + 11) - (vid.conwidth*8/320)*7;
  660. for (i=0 ; i<strlen(ver) ; i++)
  661. Draw_Character (x + i * 8, y, ver[i] | 0x80);
  662. }
  663. }
  664. /*
  665. =============
  666. Draw_TileClear
  667. This repeats a 64*64 tile graphic to fill the screen around a sized down
  668. refresh window.
  669. =============
  670. */
  671. void Draw_TileClear (int x, int y, int w, int h)
  672. {
  673. glColor3f (1,1,1);
  674. GL_Bind (*(int *)draw_backtile->data);
  675. glBegin (GL_QUADS);
  676. glTexCoord2f (x/64.0, y/64.0);
  677. glVertex2f (x, y);
  678. glTexCoord2f ( (x+w)/64.0, y/64.0);
  679. glVertex2f (x+w, y);
  680. glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
  681. glVertex2f (x+w, y+h);
  682. glTexCoord2f ( x/64.0, (y+h)/64.0 );
  683. glVertex2f (x, y+h);
  684. glEnd ();
  685. }
  686. /*
  687. =============
  688. Draw_Fill
  689. Fills a box of pixels with a single color
  690. =============
  691. */
  692. void Draw_Fill (int x, int y, int w, int h, int c)
  693. {
  694. glDisable (GL_TEXTURE_2D);
  695. glColor3f (host_basepal[c*3]/255.0,
  696. host_basepal[c*3+1]/255.0,
  697. host_basepal[c*3+2]/255.0);
  698. glBegin (GL_QUADS);
  699. glVertex2f (x,y);
  700. glVertex2f (x+w, y);
  701. glVertex2f (x+w, y+h);
  702. glVertex2f (x, y+h);
  703. glEnd ();
  704. glColor3f (1,1,1);
  705. glEnable (GL_TEXTURE_2D);
  706. }
  707. //=============================================================================
  708. /*
  709. ================
  710. Draw_FadeScreen
  711. ================
  712. */
  713. void Draw_FadeScreen (void)
  714. {
  715. glEnable (GL_BLEND);
  716. glDisable (GL_TEXTURE_2D);
  717. glColor4f (0, 0, 0, 0.8);
  718. glBegin (GL_QUADS);
  719. glVertex2f (0,0);
  720. glVertex2f (vid.width, 0);
  721. glVertex2f (vid.width, vid.height);
  722. glVertex2f (0, vid.height);
  723. glEnd ();
  724. glColor4f (1,1,1,1);
  725. glEnable (GL_TEXTURE_2D);
  726. glDisable (GL_BLEND);
  727. Sbar_Changed();
  728. }
  729. //=============================================================================
  730. /*
  731. ================
  732. Draw_BeginDisc
  733. Draws the little blue disc in the corner of the screen.
  734. Call before beginning any disc IO.
  735. ================
  736. */
  737. void Draw_BeginDisc (void)
  738. {
  739. if (!draw_disc)
  740. return;
  741. glDrawBuffer (GL_FRONT);
  742. Draw_Pic (vid.width - 24, 0, draw_disc);
  743. glDrawBuffer (GL_BACK);
  744. }
  745. /*
  746. ================
  747. Draw_EndDisc
  748. Erases the disc icon.
  749. Call after completing any disc IO
  750. ================
  751. */
  752. void Draw_EndDisc (void)
  753. {
  754. }
  755. /*
  756. ================
  757. GL_Set2D
  758. Setup as if the screen was 320*200
  759. ================
  760. */
  761. void GL_Set2D (void)
  762. {
  763. glViewport (glx, gly, glwidth, glheight);
  764. glMatrixMode(GL_PROJECTION);
  765. glLoadIdentity ();
  766. glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
  767. glMatrixMode(GL_MODELVIEW);
  768. glLoadIdentity ();
  769. glDisable (GL_DEPTH_TEST);
  770. glDisable (GL_CULL_FACE);
  771. glDisable (GL_BLEND);
  772. glEnable (GL_ALPHA_TEST);
  773. // glDisable (GL_ALPHA_TEST);
  774. glColor4f (1,1,1,1);
  775. }
  776. //====================================================================
  777. /*
  778. ================
  779. GL_FindTexture
  780. ================
  781. */
  782. int GL_FindTexture (char *identifier)
  783. {
  784. int i;
  785. gltexture_t *glt;
  786. for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  787. {
  788. if (!strcmp (identifier, glt->identifier))
  789. return gltextures[i].texnum;
  790. }
  791. return -1;
  792. }
  793. /*
  794. ================
  795. GL_ResampleTexture
  796. ================
  797. */
  798. void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
  799. {
  800. int i, j;
  801. unsigned *inrow;
  802. unsigned frac, fracstep;
  803. fracstep = inwidth*0x10000/outwidth;
  804. for (i=0 ; i<outheight ; i++, out += outwidth)
  805. {
  806. inrow = in + inwidth*(i*inheight/outheight);
  807. frac = fracstep >> 1;
  808. for (j=0 ; j<outwidth ; j+=4)
  809. {
  810. out[j] = inrow[frac>>16];
  811. frac += fracstep;
  812. out[j+1] = inrow[frac>>16];
  813. frac += fracstep;
  814. out[j+2] = inrow[frac>>16];
  815. frac += fracstep;
  816. out[j+3] = inrow[frac>>16];
  817. frac += fracstep;
  818. }
  819. }
  820. }
  821. /*
  822. ================
  823. GL_Resample8BitTexture -- JACK
  824. ================
  825. */
  826. void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
  827. {
  828. int i, j;
  829. unsigned char *inrow;
  830. unsigned frac, fracstep;
  831. fracstep = inwidth*0x10000/outwidth;
  832. for (i=0 ; i<outheight ; i++, out += outwidth)
  833. {
  834. inrow = in + inwidth*(i*inheight/outheight);
  835. frac = fracstep >> 1;
  836. for (j=0 ; j<outwidth ; j+=4)
  837. {
  838. out[j] = inrow[frac>>16];
  839. frac += fracstep;
  840. out[j+1] = inrow[frac>>16];
  841. frac += fracstep;
  842. out[j+2] = inrow[frac>>16];
  843. frac += fracstep;
  844. out[j+3] = inrow[frac>>16];
  845. frac += fracstep;
  846. }
  847. }
  848. }
  849. /*
  850. ================
  851. GL_MipMap
  852. Operates in place, quartering the size of the texture
  853. ================
  854. */
  855. void GL_MipMap (byte *in, int width, int height)
  856. {
  857. int i, j;
  858. byte *out;
  859. width <<=2;
  860. height >>= 1;
  861. out = in;
  862. for (i=0 ; i<height ; i++, in+=width)
  863. {
  864. for (j=0 ; j<width ; j+=8, out+=4, in+=8)
  865. {
  866. out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
  867. out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
  868. out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
  869. out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
  870. }
  871. }
  872. }
  873. /*
  874. ================
  875. GL_MipMap8Bit
  876. Mipping for 8 bit textures
  877. ================
  878. */
  879. void GL_MipMap8Bit (byte *in, int width, int height)
  880. {
  881. int i, j;
  882. byte *out;
  883. unsigned short r,g,b;
  884. byte *at1, *at2, *at3, *at4;
  885. height >>= 1;
  886. out = in;
  887. for (i=0 ; i<height ; i++, in+=width)
  888. for (j=0 ; j<width ; j+=2, out+=1, in+=2)
  889. {
  890. at1 = (byte *) &d_8to24table[in[0]];
  891. at2 = (byte *) &d_8to24table[in[1]];
  892. at3 = (byte *) &d_8to24table[in[width+0]];
  893. at4 = (byte *) &d_8to24table[in[width+1]];
  894. r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
  895. g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
  896. b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
  897. out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
  898. }
  899. }
  900. /*
  901. ===============
  902. GL_Upload32
  903. ===============
  904. */
  905. void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha)
  906. {
  907. int samples;
  908. static unsigned scaled[1024*512]; // [512*256];
  909. int scaled_width, scaled_height;
  910. for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
  911. ;
  912. for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
  913. ;
  914. scaled_width >>= (int)gl_picmip.value;
  915. scaled_height >>= (int)gl_picmip.value;
  916. if (scaled_width > gl_max_size.value)
  917. scaled_width = gl_max_size.value;
  918. if (scaled_height > gl_max_size.value)
  919. scaled_height = gl_max_size.value;
  920. if (scaled_width * scaled_height > sizeof(scaled)/4)
  921. Sys_Error ("GL_LoadTexture: too big");
  922. samples = alpha ? gl_alpha_format : gl_solid_format;
  923. #if 0
  924. if (mipmap)
  925. gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  926. else if (scaled_width == width && scaled_height == height)
  927. glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  928. else
  929. {
  930. gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
  931. scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
  932. glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  933. }
  934. #else
  935. texels += scaled_width * scaled_height;
  936. if (scaled_width == width && scaled_height == height)
  937. {
  938. if (!mipmap)
  939. {
  940. glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  941. goto done;
  942. }
  943. memcpy (scaled, data, width*height*4);
  944. }
  945. else
  946. GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
  947. glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  948. if (mipmap)
  949. {
  950. int miplevel;
  951. miplevel = 0;
  952. while (scaled_width > 1 || scaled_height > 1)
  953. {
  954. GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
  955. scaled_width >>= 1;
  956. scaled_height >>= 1;
  957. if (scaled_width < 1)
  958. scaled_width = 1;
  959. if (scaled_height < 1)
  960. scaled_height = 1;
  961. miplevel++;
  962. glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  963. }
  964. }
  965. done: ;
  966. #endif
  967. if (mipmap)
  968. {
  969. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  970. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  971. }
  972. else
  973. {
  974. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
  975. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  976. }
  977. }
  978. void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
  979. {
  980. int i, s;
  981. qboolean noalpha;
  982. int samples;
  983. static unsigned char scaled[1024*512]; // [512*256];
  984. int scaled_width, scaled_height;
  985. s = width*height;
  986. // if there are no transparent pixels, make it a 3 component
  987. // texture even if it was specified as otherwise
  988. if (alpha)
  989. {
  990. noalpha = true;
  991. for (i=0 ; i<s ; i++)
  992. {
  993. if (data[i] == 255)
  994. noalpha = false;
  995. }
  996. if (alpha && noalpha)
  997. alpha = false;
  998. }
  999. for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
  1000. ;
  1001. for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
  1002. ;
  1003. scaled_width >>= (int)gl_picmip.value;
  1004. scaled_height >>= (int)gl_picmip.value;
  1005. if (scaled_width > gl_max_size.value)
  1006. scaled_width = gl_max_size.value;
  1007. if (scaled_height > gl_max_size.value)
  1008. scaled_height = gl_max_size.value;
  1009. if (scaled_width * scaled_height > sizeof(scaled))
  1010. Sys_Error ("GL_LoadTexture: too big");
  1011. samples = 1; // alpha ? gl_alpha_format : gl_solid_format;
  1012. texels += scaled_width * scaled_height;
  1013. if (scaled_width == width && scaled_height == height)
  1014. {
  1015. if (!mipmap)
  1016. {
  1017. glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
  1018. goto done;
  1019. }
  1020. memcpy (scaled, data, width*height);
  1021. }
  1022. else
  1023. GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
  1024. glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
  1025. if (mipmap)
  1026. {
  1027. int miplevel;
  1028. miplevel = 0;
  1029. while (scaled_width > 1 || scaled_height > 1)
  1030. {
  1031. GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
  1032. scaled_width >>= 1;
  1033. scaled_height >>= 1;
  1034. if (scaled_width < 1)
  1035. scaled_width = 1;
  1036. if (scaled_height < 1)
  1037. scaled_height = 1;
  1038. miplevel++;
  1039. glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
  1040. }
  1041. }
  1042. done: ;
  1043. if (mipmap)
  1044. {
  1045. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  1046. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1047. }
  1048. else
  1049. {
  1050. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
  1051. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  1052. }
  1053. }
  1054. extern qboolean VID_Is8bit();
  1055. /*
  1056. ===============
  1057. GL_Upload8
  1058. ===============
  1059. */
  1060. void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
  1061. {
  1062. static unsigned trans[640*480]; // FIXME, temporary
  1063. int i, s;
  1064. qboolean noalpha;
  1065. int p;
  1066. s = width*height;
  1067. // if there are no transparent pixels, make it a 3 component
  1068. // texture even if it was specified as otherwise
  1069. if (alpha)
  1070. {
  1071. noalpha = true;
  1072. for (i=0 ; i<s ; i++)
  1073. {
  1074. p = data[i];
  1075. if (p == 255)
  1076. noalpha = false;
  1077. trans[i] = d_8to24table[p];
  1078. }
  1079. if (alpha && noalpha)
  1080. alpha = false;
  1081. }
  1082. else
  1083. {
  1084. if (s&3)
  1085. Sys_Error ("GL_Upload8: s&3");
  1086. for (i=0 ; i<s ; i+=4)
  1087. {
  1088. trans[i] = d_8to24table[data[i]];
  1089. trans[i+1] = d_8to24table[data[i+1]];
  1090. trans[i+2] = d_8to24table[data[i+2]];
  1091. trans[i+3] = d_8to24table[data[i+3]];
  1092. }
  1093. }
  1094. if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) {
  1095. GL_Upload8_EXT (data, width, height, mipmap, alpha);
  1096. return;
  1097. }
  1098. GL_Upload32 (trans, width, height, mipmap, alpha);
  1099. }
  1100. /*
  1101. ================
  1102. GL_LoadTexture
  1103. ================
  1104. */
  1105. int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha)
  1106. {
  1107. int i;
  1108. gltexture_t *glt;
  1109. // see if the texture is allready present
  1110. if (identifier[0])
  1111. {
  1112. for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
  1113. {
  1114. if (!strcmp (identifier, glt->identifier))
  1115. {
  1116. if (width != glt->width || height != glt->height)
  1117. Sys_Error ("GL_LoadTexture: cache mismatch");
  1118. return gltextures[i].texnum;
  1119. }
  1120. }
  1121. }
  1122. else
  1123. glt = &gltextures[numgltextures];
  1124. numgltextures++;
  1125. strcpy (glt->identifier, identifier);
  1126. glt->texnum = texture_extension_number;
  1127. glt->width = width;
  1128. glt->height = height;
  1129. glt->mipmap = mipmap;
  1130. GL_Bind(texture_extension_number );
  1131. GL_Upload8 (data, width, height, mipmap, alpha);
  1132. texture_extension_number++;
  1133. return texture_extension_number-1;
  1134. }
  1135. /*
  1136. ================
  1137. GL_LoadPicTexture
  1138. ================
  1139. */
  1140. int GL_LoadPicTexture (qpic_t *pic)
  1141. {
  1142. return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true);
  1143. }
  1144. /****************************************/
  1145. static GLenum oldtarget = TEXTURE0_SGIS;
  1146. void GL_SelectTexture (GLenum target)
  1147. {
  1148. if (!gl_mtexable)
  1149. return;
  1150. #ifndef __linux__ // no multitexture under Linux yet
  1151. qglSelectTextureSGIS(target);
  1152. #endif
  1153. if (target == oldtarget)
  1154. return;
  1155. cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
  1156. currenttexture = cnttextures[target-TEXTURE0_SGIS];
  1157. oldtarget = target;
  1158. }