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