]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_backend.c
5b9a8d2985046049befab0019d80beb805c9f03b
[xonotic/darkplaces.git] / gl_backend.c
1
2 #include "quakedef.h"
3
4 //cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "21760"};
5 cvar_t gl_mesh_maxtriangles = {0, "gl_mesh_maxtriangles", "8192"};
6 //cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "1024"};
7 cvar_t gl_mesh_batchtriangles = {0, "gl_mesh_batchtriangles", "0"};
8 cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "0"};
9 cvar_t gl_mesh_drawmode = {CVAR_SAVE, "gl_mesh_drawmode", "3"};
10
11 cvar_t r_render = {0, "r_render", "1"};
12 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering
13 cvar_t gl_lockarrays = {0, "gl_lockarrays", "1"};
14
15 #ifdef DEBUGGL
16 int errornumber = 0;
17
18 void GL_PrintError(int errornumber, char *filename, int linenumber)
19 {
20         switch(errornumber)
21         {
22 #ifdef GL_INVALID_ENUM
23         case GL_INVALID_ENUM:
24                 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
25                 break;
26 #endif
27 #ifdef GL_INVALID_VALUE
28         case GL_INVALID_VALUE:
29                 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
30                 break;
31 #endif
32 #ifdef GL_INVALID_OPERATION
33         case GL_INVALID_OPERATION:
34                 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
35                 break;
36 #endif
37 #ifdef GL_STACK_OVERFLOW
38         case GL_STACK_OVERFLOW:
39                 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
40                 break;
41 #endif
42 #ifdef GL_STACK_UNDERFLOW
43         case GL_STACK_UNDERFLOW:
44                 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
45                 break;
46 #endif
47 #ifdef GL_OUT_OF_MEMORY
48         case GL_OUT_OF_MEMORY:
49                 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
50                 break;
51 #endif
52 #ifdef GL_TABLE_TOO_LARGE
53     case GL_TABLE_TOO_LARGE:
54                 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
55                 break;
56 #endif
57         default:
58                 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
59                 break;
60         }
61 }
62 #endif
63
64 float r_farclip, r_newfarclip;
65
66 int polyindexarray[768];
67
68 static float viewdist;
69
70 int c_meshs, c_meshtris, c_transmeshs, c_transtris;
71
72 int                     lightscalebit;
73 float           lightscale;
74 float           overbrightscale;
75
76 void SCR_ScreenShot_f (void);
77
78 static int max_meshs;
79 static int max_batch;
80 static int max_verts; // always max_meshs * 3
81 #define TRANSDEPTHRES 4096
82
83 typedef struct buf_mesh_s
84 {
85         int depthmask;
86         int depthtest;
87         int blendfunc1, blendfunc2;
88         int textures[MAX_TEXTUREUNITS];
89         int texturergbscale[MAX_TEXTUREUNITS];
90         int firsttriangle;
91         int triangles;
92         int firstvert;
93         int verts;
94         struct buf_mesh_s *chain;
95         struct buf_transtri_s *transchain;
96 }
97 buf_mesh_t;
98
99 typedef struct buf_transtri_s
100 {
101         struct buf_transtri_s *next;
102         struct buf_transtri_s *meshsortchain;
103         buf_mesh_t *mesh;
104         int index[3];
105 }
106 buf_transtri_t;
107
108 typedef struct buf_tri_s
109 {
110         int index[3];
111 }
112 buf_tri_t;
113
114 typedef struct
115 {
116         float v[4];
117 }
118 buf_vertex_t;
119
120 typedef struct
121 {
122         float c[4];
123 }
124 buf_fcolor_t;
125
126 typedef struct
127 {
128         qbyte c[4];
129 }
130 buf_bcolor_t;
131
132 typedef struct
133 {
134         float t[2];
135 }
136 buf_texcoord_t;
137
138 static float meshfarclip;
139 static int currentmesh, currenttriangle, currentvertex, backendunits, backendactive, transranout;
140 static buf_mesh_t *buf_mesh;
141 static buf_tri_t *buf_tri;
142 static buf_vertex_t *buf_vertex;
143 static buf_fcolor_t *buf_fcolor;
144 static buf_bcolor_t *buf_bcolor;
145 static buf_texcoord_t *buf_texcoord[MAX_TEXTUREUNITS];
146
147 static int currenttransmesh, currenttransvertex, currenttranstriangle;
148 static buf_mesh_t *buf_transmesh;
149 static buf_transtri_t *buf_sorttranstri;
150 static buf_transtri_t **buf_sorttranstri_list;
151 static buf_tri_t *buf_transtri;
152 static buf_vertex_t *buf_transvertex;
153 static buf_fcolor_t *buf_transfcolor;
154 static buf_texcoord_t *buf_transtexcoord[MAX_TEXTUREUNITS];
155
156 static mempool_t *gl_backend_mempool;
157 static int resizingbuffers = false;
158
159 static void gl_backend_start(void)
160 {
161         int i;
162
163         max_verts = max_meshs * 3;
164
165         if (!gl_backend_mempool)
166                 gl_backend_mempool = Mem_AllocPool("GL_Backend");
167
168 #define BACKENDALLOC(var, count, sizeofstruct)\
169         {\
170                 var = Mem_Alloc(gl_backend_mempool, count * sizeof(sizeofstruct));\
171                 if (var == NULL)\
172                         Sys_Error("gl_backend_start: unable to allocate memory\n");\
173                 memset(var, 0, count * sizeof(sizeofstruct));\
174         }
175
176         BACKENDALLOC(buf_mesh, max_meshs, buf_mesh_t)
177         BACKENDALLOC(buf_tri, max_meshs, buf_tri_t)
178         BACKENDALLOC(buf_vertex, max_verts, buf_vertex_t)
179         BACKENDALLOC(buf_fcolor, max_verts, buf_fcolor_t)
180         BACKENDALLOC(buf_bcolor, max_verts, buf_bcolor_t)
181
182         BACKENDALLOC(buf_transmesh, max_meshs, buf_mesh_t)
183         BACKENDALLOC(buf_sorttranstri, max_meshs, buf_transtri_t)
184         BACKENDALLOC(buf_sorttranstri_list, TRANSDEPTHRES, buf_transtri_t *)
185         BACKENDALLOC(buf_transtri, max_meshs, buf_tri_t)
186         BACKENDALLOC(buf_transvertex, max_verts, buf_vertex_t)
187         BACKENDALLOC(buf_transfcolor, max_verts, buf_fcolor_t)
188
189         for (i = 0;i < MAX_TEXTUREUNITS;i++)
190         {
191                 // only allocate as many texcoord arrays as we need
192                 if (i < gl_textureunits)
193                 {
194                         BACKENDALLOC(buf_texcoord[i], max_verts, buf_texcoord_t)
195                         BACKENDALLOC(buf_transtexcoord[i], max_verts, buf_texcoord_t)
196                 }
197                 else
198                 {
199                         buf_texcoord[i] = NULL;
200                         buf_transtexcoord[i] = NULL;
201                 }
202         }
203         backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
204         backendactive = true;
205 }
206
207 static void gl_backend_shutdown(void)
208 {
209         if (resizingbuffers)
210                 Mem_EmptyPool(gl_backend_mempool);
211         else
212                 Mem_FreePool(&gl_backend_mempool);
213
214         backendunits = 0;
215         backendactive = false;
216 }
217
218 static void gl_backend_bufferchanges(int init)
219 {
220         // 21760 is (65536 / 3) rounded off to a multiple of 128
221         if (gl_mesh_maxtriangles.integer < 256)
222                 Cvar_SetValue("gl_mesh_maxtriangles", 256);
223         if (gl_mesh_maxtriangles.integer > 21760)
224                 Cvar_SetValue("gl_mesh_maxtriangles", 21760);
225
226         if (gl_mesh_batchtriangles.integer < 0)
227                 Cvar_SetValue("gl_mesh_batchtriangles", 0);
228         if (gl_mesh_batchtriangles.integer > gl_mesh_maxtriangles.integer)
229                 Cvar_SetValue("gl_mesh_batchtriangles", gl_mesh_maxtriangles.integer);
230
231         max_batch = gl_mesh_batchtriangles.integer;
232
233         if (max_meshs != gl_mesh_maxtriangles.integer)
234         {
235                 max_meshs = gl_mesh_maxtriangles.integer;
236
237                 if (!init)
238                 {
239                         resizingbuffers = true;
240                         gl_backend_shutdown();
241                         gl_backend_start();
242                         resizingbuffers = false;
243                 }
244         }
245 }
246
247 static void gl_backend_newmap(void)
248 {
249         r_farclip = r_newfarclip = 2048.0f;
250 }
251
252 void gl_backend_init(void)
253 {
254         int i;
255
256         Cvar_RegisterVariable(&r_render);
257         Cvar_RegisterVariable(&gl_dither);
258         Cvar_RegisterVariable(&gl_lockarrays);
259 #ifdef NORENDER
260         Cvar_SetValue("r_render", 0);
261 #endif
262
263         Cvar_RegisterVariable(&gl_mesh_maxtriangles);
264         Cvar_RegisterVariable(&gl_mesh_batchtriangles);
265         Cvar_RegisterVariable(&gl_mesh_floatcolors);
266         Cvar_RegisterVariable(&gl_mesh_drawmode);
267         R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
268         gl_backend_bufferchanges(true);
269         for (i = 0;i < 256;i++)
270         {
271                 polyindexarray[i*3+0] = 0;
272                 polyindexarray[i*3+1] = i + 1;
273                 polyindexarray[i*3+2] = i + 2;
274         }
275 }
276
277 int arraylocked = false;
278
279 void GL_LockArray(int first, int count)
280 {
281         if (!arraylocked && gl_supportslockarrays && gl_lockarrays.integer && gl_mesh_drawmode.integer != 0)
282         {
283                 qglLockArraysEXT(first, count);
284                 CHECKGLERROR
285                 arraylocked = true;
286         }
287 }
288
289 void GL_UnlockArray(void)
290 {
291         if (arraylocked)
292         {
293                 qglUnlockArraysEXT();
294                 CHECKGLERROR
295                 arraylocked = false;
296         }
297 }
298
299 //static float gldepthmin, gldepthmax;
300
301 /*
302 =============
303 GL_SetupFrame
304 =============
305 */
306 static void GL_SetupFrame (void)
307 {
308         double xmax, ymax;
309         double fovx, fovy, zNear, zFar, aspect;
310
311         // update farclip based on previous frame
312         r_farclip = r_newfarclip;
313
314         if (!r_render.integer)
315                 return;
316
317 //      qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
318 //      gldepthmin = 0;
319 //      gldepthmax = 1;
320         qglDepthFunc (GL_LEQUAL);CHECKGLERROR
321
322 //      qglDepthRange (gldepthmin, gldepthmax);CHECKGLERROR
323
324         // set up viewpoint
325         qglMatrixMode(GL_PROJECTION);CHECKGLERROR
326         qglLoadIdentity ();CHECKGLERROR
327
328         // y is weird beause OpenGL is bottom to top, we use top to bottom
329         qglViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);CHECKGLERROR
330
331         // depth range
332         zNear = 1.0;
333         zFar = r_farclip;
334
335         // fov angles
336         fovx = r_refdef.fov_x;
337         fovy = r_refdef.fov_y;
338         aspect = r_refdef.width / r_refdef.height;
339
340         // pyramid slopes
341         xmax = zNear * tan(fovx * M_PI / 360.0) * aspect;
342         ymax = zNear * tan(fovy * M_PI / 360.0);
343
344         // set view pyramid
345         qglFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar);CHECKGLERROR
346
347 //      qglCullFace(GL_FRONT);CHECKGLERROR
348
349         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
350         qglLoadIdentity ();CHECKGLERROR
351
352         // put Z going up
353         qglRotatef (-90,  1, 0, 0);CHECKGLERROR
354         qglRotatef (90,  0, 0, 1);CHECKGLERROR
355         // camera rotation
356         qglRotatef (-r_refdef.viewangles[2],  1, 0, 0);CHECKGLERROR
357         qglRotatef (-r_refdef.viewangles[0],  0, 1, 0);CHECKGLERROR
358         qglRotatef (-r_refdef.viewangles[1],  0, 0, 1);CHECKGLERROR
359         // camera location
360         qglTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);CHECKGLERROR
361
362 //      qglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
363
364         //
365         // set drawing parms
366         //
367 //      if (gl_cull.integer)
368 //      {
369 //              qglEnable(GL_CULL_FACE);CHECKGLERROR
370 //      }
371 //      else
372 //      {
373 //              qglDisable(GL_CULL_FACE);CHECKGLERROR
374 //      }
375
376 //      qglEnable(GL_BLEND);CHECKGLERROR
377 //      qglEnable(GL_DEPTH_TEST);CHECKGLERROR
378 //      qglDepthMask(1);CHECKGLERROR
379 }
380
381 static int mesh_blendfunc1;
382 static int mesh_blendfunc2;
383 static int mesh_blend;
384 static GLboolean mesh_depthmask;
385 static int mesh_depthtest;
386 static int mesh_unit;
387 static int mesh_clientunit;
388 static int mesh_texture[MAX_TEXTUREUNITS];
389 static float mesh_texturergbscale[MAX_TEXTUREUNITS];
390
391 void GL_SetupTextureState(void)
392 {
393         int i;
394         if (backendunits > 1)
395         {
396                 for (i = 0;i < backendunits;i++)
397                 {
398                         qglActiveTexture(GL_TEXTURE0_ARB + (mesh_unit = i));CHECKGLERROR
399                         qglBindTexture(GL_TEXTURE_2D, mesh_texture[i]);CHECKGLERROR
400                         if (gl_combine.integer)
401                         {
402                                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
403                                 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
404                                 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
405                                 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
406                                 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);CHECKGLERROR
407                                 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
408                                 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
409                                 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
410                                 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
411                                 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
412                                 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
413                                 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
414                                 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
415                                 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
416                                 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
417                                 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, mesh_texturergbscale[i]);CHECKGLERROR
418                                 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
419                         }
420                         else
421                         {
422                                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
423                         }
424                         if (mesh_texture[i])
425                         {
426                                 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
427                         }
428                         else
429                         {
430                                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
431                         }
432                         if (gl_mesh_drawmode.integer != 0)
433                         {
434                                 qglClientActiveTexture(GL_TEXTURE0_ARB + (mesh_clientunit = i));CHECKGLERROR
435                                 qglTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[i]);CHECKGLERROR
436                                 if (mesh_texture[i])
437                                 {
438                                         qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
439                                 }
440                                 else
441                                 {
442                                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
443                                 }
444                         }
445                 }
446         }
447         else
448         {
449                 qglBindTexture(GL_TEXTURE_2D, mesh_texture[0]);CHECKGLERROR
450                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
451                 if (mesh_texture[0])
452                 {
453                         qglEnable(GL_TEXTURE_2D);CHECKGLERROR
454                 }
455                 else
456                 {
457                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
458                 }
459                 if (gl_mesh_drawmode.integer != 0)
460                 {
461                         qglTexCoordPointer(2, GL_FLOAT, sizeof(buf_texcoord_t), buf_texcoord[0]);CHECKGLERROR
462                         if (mesh_texture[0])
463                         {
464                                 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
465                         }
466                         else
467                         {
468                                 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
469                         }
470                 }
471         }
472 }
473
474 // called at beginning of frame
475 int usedarrays;
476 void R_Mesh_Start(void)
477 {
478         int i;
479         if (!backendactive)
480                 Sys_Error("R_Mesh_Clear: called when backend is not active\n");
481
482         CHECKGLERROR
483
484         gl_backend_bufferchanges(false);
485
486         currentmesh = 0;
487         currenttriangle = 0;
488         currentvertex = 0;
489         currenttransmesh = 0;
490         currenttranstriangle = 0;
491         currenttransvertex = 0;
492         meshfarclip = 0;
493         transranout = false;
494         viewdist = DotProduct(r_origin, vpn);
495
496         c_meshs = 0;
497         c_meshtris = 0;
498         c_transmeshs = 0;
499         c_transtris = 0;
500
501         GL_SetupFrame();
502
503         mesh_unit = 0;
504         mesh_clientunit = 0;
505
506         for (i = 0;i < backendunits;i++)
507         {
508                 mesh_texture[i] = 0;
509                 mesh_texturergbscale[i] = 1;
510         }
511
512         qglEnable(GL_CULL_FACE);CHECKGLERROR
513         qglCullFace(GL_FRONT);CHECKGLERROR
514
515         mesh_depthtest = true;
516         qglEnable(GL_DEPTH_TEST);CHECKGLERROR
517
518         mesh_blendfunc1 = GL_ONE;
519         mesh_blendfunc2 = GL_ZERO;
520         qglBlendFunc(mesh_blendfunc1, mesh_blendfunc2);CHECKGLERROR
521
522         mesh_blend = 0;
523         qglDisable(GL_BLEND);CHECKGLERROR
524
525         mesh_depthmask = GL_TRUE;
526         qglDepthMask(mesh_depthmask);CHECKGLERROR
527
528         usedarrays = false;
529         if (gl_mesh_drawmode.integer != 0)
530         {
531                 usedarrays = true;
532                 qglVertexPointer(3, GL_FLOAT, sizeof(buf_vertex_t), &buf_vertex[0].v[0]);CHECKGLERROR
533                 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
534                 if (gl_mesh_floatcolors.integer)
535                 {
536                         qglColorPointer(4, GL_FLOAT, sizeof(buf_fcolor_t), &buf_fcolor[0].c[0]);CHECKGLERROR
537                 }
538                 else
539                 {
540                         qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(buf_bcolor_t), &buf_bcolor[0].c[0]);CHECKGLERROR
541                 }
542                 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
543         }
544
545         GL_SetupTextureState();
546 }
547
548 int gl_backend_rebindtextures;
549
550 void GL_UpdateFarclip(void)
551 {
552         int i;
553         float farclip;
554
555         // push out farclip based on vertices
556         // FIXME: wouldn't this be slow when using matrix transforms?
557         for (i = 0;i < currentvertex;i++)
558         {
559                 farclip = DotProduct(buf_vertex[i].v, vpn);
560                 if (meshfarclip < farclip)
561                         meshfarclip = farclip;
562         }
563
564         farclip = meshfarclip + 256.0f - viewdist; // + 256 just to be safe
565
566         // push out farclip for next frame
567         if (farclip > r_newfarclip)
568                 r_newfarclip = ceil((farclip + 255) / 256) * 256 + 256;
569 }
570
571 void GL_ConvertColorsFloatToByte(void)
572 {
573         int i, k, *icolor;
574         float *fcolor;
575         qbyte *bcolor;
576
577         // shift float to have 8bit fraction at base of number
578         for (i = 0, fcolor = &buf_fcolor->c[0];i < currentvertex;i++)
579         {
580                 *fcolor++ += 32768.0f;
581                 *fcolor++ += 32768.0f;
582                 *fcolor++ += 32768.0f;
583                 *fcolor++ += 32768.0f;
584         }
585         // then read as integer and kill float bits...
586         for (i = 0, icolor = (int *)&buf_fcolor->c[0], bcolor = &buf_bcolor->c[0];i < currentvertex;i++)
587         {
588                 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
589                 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
590                 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
591                 k = (*icolor++) & 0x7FFFFF;*bcolor++ = k > 255 ? 255 : k;
592         }
593 }
594
595 void GL_MeshState(buf_mesh_t *mesh)
596 {
597         int i;
598         if (backendunits > 1)
599         {
600                 for (i = 0;i < backendunits;i++)
601                 {
602                         if (mesh_texture[i] != mesh->textures[i])
603                         {
604                                 if (mesh_unit != i)
605                                 {
606                                         qglActiveTexture(GL_TEXTURE0_ARB + (mesh_unit = i));CHECKGLERROR
607                                 }
608                                 if (mesh_texture[i] == 0)
609                                 {
610                                         qglEnable(GL_TEXTURE_2D);CHECKGLERROR
611                                         // have to disable texcoord array on disabled texture
612                                         // units due to NVIDIA driver bug with
613                                         // compiled_vertex_array
614                                         if (mesh_clientunit != i)
615                                         {
616                                                 qglClientActiveTexture(GL_TEXTURE0_ARB + (mesh_clientunit = i));CHECKGLERROR
617                                         }
618                                         qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
619                                 }
620                                 qglBindTexture(GL_TEXTURE_2D, (mesh_texture[i] = mesh->textures[i]));CHECKGLERROR
621                                 if (mesh_texture[i] == 0)
622                                 {
623                                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
624                                         // have to disable texcoord array on disabled texture
625                                         // units due to NVIDIA driver bug with
626                                         // compiled_vertex_array
627                                         if (mesh_clientunit != i)
628                                         {
629                                                 qglClientActiveTexture(GL_TEXTURE0_ARB + (mesh_clientunit = i));CHECKGLERROR
630                                         }
631                                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
632                                 }
633                         }
634                         if (mesh_texturergbscale[i] != mesh->texturergbscale[i])
635                         {
636                                 if (mesh_unit != i)
637                                 {
638                                         qglActiveTexture(GL_TEXTURE0_ARB + (mesh_unit = i));CHECKGLERROR
639                                 }
640                                 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (mesh_texturergbscale[i] = mesh->texturergbscale[i]));CHECKGLERROR
641                         }
642                 }
643         }
644         else
645         {
646                 if (mesh_texture[0] != mesh->textures[0])
647                 {
648                         if (mesh_texture[0] == 0)
649                         {
650                                 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
651                                 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
652                         }
653                         qglBindTexture(GL_TEXTURE_2D, (mesh_texture[0] = mesh->textures[0]));CHECKGLERROR
654                         if (mesh_texture[0] == 0)
655                         {
656                                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
657                                 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
658                         }
659                 }
660         }
661         if (mesh_blendfunc1 != mesh->blendfunc1 || mesh_blendfunc2 != mesh->blendfunc2)
662         {
663                 qglBlendFunc(mesh_blendfunc1 = mesh->blendfunc1, mesh_blendfunc2 = mesh->blendfunc2);CHECKGLERROR
664                 if (mesh_blendfunc2 == GL_ZERO)
665                 {
666                         if (mesh_blendfunc1 == GL_ONE)
667                         {
668                                 if (mesh_blend)
669                                 {
670                                         mesh_blend = 0;
671                                         qglDisable(GL_BLEND);CHECKGLERROR
672                                 }
673                         }
674                         else
675                         {
676                                 if (!mesh_blend)
677                                 {
678                                         mesh_blend = 1;
679                                         qglEnable(GL_BLEND);CHECKGLERROR
680                                 }
681                         }
682                 }
683                 else
684                 {
685                         if (!mesh_blend)
686                         {
687                                 mesh_blend = 1;
688                                 qglEnable(GL_BLEND);CHECKGLERROR
689                         }
690                 }
691         }
692         if (mesh_depthtest != mesh->depthtest)
693         {
694                 mesh_depthtest = mesh->depthtest;
695                 if (mesh_depthtest)
696                         qglEnable(GL_DEPTH_TEST);
697                 else
698                         qglDisable(GL_DEPTH_TEST);
699         }
700         if (mesh_depthmask != mesh->depthmask)
701         {
702                 qglDepthMask(mesh_depthmask = mesh->depthmask);CHECKGLERROR
703         }
704 }
705
706 void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, GLuint *index)
707 {
708         unsigned int i, j, in;
709         if (gl_mesh_drawmode.integer == 3 && qglDrawRangeElements == NULL)
710                 Cvar_SetValueQuick(&gl_mesh_drawmode, 2);
711
712         if (gl_mesh_drawmode.integer == 3)
713         {
714                 // GL 1.2 or GL 1.1 with extension
715                 qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, GL_UNSIGNED_INT, index);
716         }
717         else if (gl_mesh_drawmode.integer == 2)
718         {
719                 // GL 1.1
720                 qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, index);
721         }
722         else if (gl_mesh_drawmode.integer == 1)
723         {
724                 // GL 1.1
725                 // feed it manually using glArrayElement
726                 qglBegin(GL_TRIANGLES);
727                 for (i = 0;i < indexcount;i++)
728                         qglArrayElement(index[i]);
729                 qglEnd();
730         }
731         else
732         {
733                 // GL 1.1 but not using vertex arrays - 3dfx glquake minigl driver
734                 // feed it manually
735                 if (gl_mesh_drawmode.integer != 0)
736                         Cvar_SetValueQuick(&gl_mesh_drawmode, 0);
737                 qglBegin(GL_TRIANGLES);
738                 if (r_multitexture.integer)
739                 {
740                         // the minigl doesn't have this (because it does not have ARB_multitexture)
741                         for (i = 0;i < indexcount;i++)
742                         {
743                                 in = index[i];
744                                 qglColor4ub(buf_bcolor[in].c[0], buf_bcolor[in].c[1], buf_bcolor[in].c[2], buf_bcolor[in].c[3]);
745                                 for (j = 0;j < backendunits;j++)
746                                         if (mesh_texture[j])
747                                                 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, buf_texcoord[j][in].t[0], buf_texcoord[j][in].t[1]);
748                                 qglVertex3f(buf_vertex[in].v[0], buf_vertex[in].v[1], buf_vertex[in].v[2]);
749                         }
750                 }
751                 else
752                 {
753                         for (i = 0;i < indexcount;i++)
754                         {
755                                 in = index[i];
756                                 qglColor4ub(buf_bcolor[in].c[0], buf_bcolor[in].c[1], buf_bcolor[in].c[2], buf_bcolor[in].c[3]);
757                                 if (mesh_texture[0])
758                                         qglTexCoord2f(buf_texcoord[0][in].t[0], buf_texcoord[0][in].t[1]);
759                                 qglVertex3f(buf_vertex[in].v[0], buf_vertex[in].v[1], buf_vertex[in].v[2]);
760                         }
761                 }
762                 qglEnd();
763         }
764         /*
765         if (qglDrawRangeElements)
766                 qglDrawRangeElements(GL_TRIANGLES, firstvert, endvert, indexcount, index);
767         else
768         {
769         }
770         #ifdef WIN32
771         // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
772         qglDrawElements(GL_TRIANGLES, indexcount, GL_UNSIGNED_INT, index);CHECKGLERROR
773         #else
774         qglDrawRangeElements(GL_TRIANGLES, firstvert, firstvert + mesh->verts, indexcount, GL_UNSIGNED_INT, index);CHECKGLERROR
775         #endif
776         */
777 }
778
779 // renders mesh buffers, called to flush buffers when full
780 void R_Mesh_Render(void)
781 {
782         int i;
783         int k;
784         int indexcount;
785         int firstvert;
786         buf_mesh_t *mesh;
787         unsigned int *index;
788
789         if (!backendactive)
790                 Sys_Error("R_Mesh_Render: called when backend is not active\n");
791
792         if (!currentmesh)
793                 return;
794
795         CHECKGLERROR
796
797         GL_UpdateFarclip();
798
799         if (!gl_mesh_floatcolors.integer || gl_mesh_drawmode.integer == 0)
800                 GL_ConvertColorsFloatToByte();
801
802         // lock the arrays now that they will have no further modifications
803         //GL_LockArray(0, currentvertex);CHECKGLERROR
804         if (gl_backend_rebindtextures)
805         {
806                 gl_backend_rebindtextures = false;
807                 GL_SetupTextureState();
808         }
809
810         GL_MeshState(buf_mesh);
811         GL_LockArray(0, currentvertex);
812         GL_DrawRangeElements(buf_mesh->firstvert, buf_mesh->firstvert + buf_mesh->verts, buf_mesh->triangles * 3, (unsigned int *)&buf_tri[buf_mesh->firsttriangle].index[0]);CHECKGLERROR
813
814         if (currentmesh >= 2)
815         {
816                 for (k = 1, mesh = buf_mesh + k;k < currentmesh;k++, mesh++)
817                 {
818                         GL_MeshState(mesh);
819
820                         firstvert = mesh->firstvert;
821                         indexcount = mesh->triangles * 3;
822                         index = (unsigned int *)&buf_tri[mesh->firsttriangle].index[0];
823
824                         // if not using batching, skip the index adjustment
825                         if (firstvert != 0)
826                                 for (i = 0;i < indexcount;i++)
827                                         index[i] += firstvert;
828
829                         GL_DrawRangeElements(firstvert, firstvert + mesh->verts, indexcount, index);CHECKGLERROR
830                 }
831         }
832
833         currentmesh = 0;
834         currenttriangle = 0;
835         currentvertex = 0;
836
837         GL_UnlockArray();CHECKGLERROR
838 }
839
840 // restores backend state, used when done with 3D rendering
841 void R_Mesh_Finish(void)
842 {
843         int i;
844         // flush any queued meshs
845         R_Mesh_Render();
846
847         if (backendunits > 1)
848         {
849                 for (i = backendunits - 1;i >= 0;i--)
850                 {
851                         qglActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR
852                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
853                         if (gl_combine.integer)
854                         {
855                                 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
856                         }
857                         if (i > 0)
858                         {
859                                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
860                         }
861                         else
862                         {
863                                 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
864                         }
865                         qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
866
867                         if (usedarrays)
868                         {
869                                 qglClientActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR
870                                 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
871                         }
872                 }
873         }
874         else
875         {
876                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
877                 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
878                 if (usedarrays)
879                 {
880                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
881                 }
882         }
883         if (usedarrays)
884         {
885                 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
886                 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
887         }
888
889         qglDisable(GL_BLEND);CHECKGLERROR
890         qglEnable(GL_DEPTH_TEST);CHECKGLERROR
891         qglDepthMask(GL_TRUE);CHECKGLERROR
892         qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
893 }
894
895 void R_Mesh_ClearDepth(void)
896 {
897         R_Mesh_AddTransparent();
898         R_Mesh_Finish();
899         qglClear(GL_DEPTH_BUFFER_BIT);
900         R_Mesh_Start();
901 }
902
903 void R_Mesh_AddTransparent(void)
904 {
905         int i, j, k, *index;
906         float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
907         buf_vertex_t *vert1, *vert2, *vert3;
908         buf_transtri_t *tri;
909         buf_mesh_t *mesh, *transmesh;
910
911         if (!currenttransmesh)
912                 return;
913
914         // convert index data to transtris for sorting
915         for (j = 0;j < currenttransmesh;j++)
916         {
917                 mesh = buf_transmesh + j;
918                 k = mesh->firsttriangle;
919                 index = &buf_transtri[k].index[0];
920                 for (i = 0;i < mesh->triangles;i++)
921                 {
922                         tri = &buf_sorttranstri[k++];
923                         tri->mesh = mesh;
924                         tri->index[0] = *index++;
925                         tri->index[1] = *index++;
926                         tri->index[2] = *index++;
927                 }
928         }
929
930         // map farclip to 0-4095 list range
931         centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
932         viewdistcompare = viewdist + 4.0f;
933
934         memset(buf_sorttranstri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
935
936         k = 0;
937         for (j = 0;j < currenttranstriangle;j++)
938         {
939                 tri = &buf_sorttranstri[j];
940                 i = tri->mesh->firstvert;
941
942                 vert1 = &buf_transvertex[tri->index[0] + i];
943                 vert2 = &buf_transvertex[tri->index[1] + i];
944                 vert3 = &buf_transvertex[tri->index[2] + i];
945
946                 dist1 = DotProduct(vert1->v, vpn);
947                 dist2 = DotProduct(vert2->v, vpn);
948                 dist3 = DotProduct(vert3->v, vpn);
949
950                 maxdist = max(dist1, max(dist2, dist3));
951                 if (maxdist < viewdistcompare)
952                         continue;
953
954                 center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
955 #if SLOWMATH
956                 i = (int) center;
957                 i = bound(0, i, (TRANSDEPTHRES - 1));
958 #else
959                 if (center < 0.0f)
960                         center = 0.0f;
961                 center += 8388608.0f;
962                 i = *((int *)&center) & 0x7FFFFF;
963                 i = min(i, (TRANSDEPTHRES - 1));
964 #endif
965                 tri->next = buf_sorttranstri_list[i];
966                 buf_sorttranstri_list[i] = tri;
967                 k++;
968         }
969
970         for (i = 0;i < currenttransmesh;i++)
971                 buf_transmesh[i].transchain = NULL;
972         transmesh = NULL;
973         for (j = 0;j < TRANSDEPTHRES;j++)
974         {
975                 if ((tri = buf_sorttranstri_list[j]))
976                 {
977                         for (;tri;tri = tri->next)
978                         {
979                                 if (!tri->mesh->transchain)
980                                 {
981                                         tri->mesh->chain = transmesh;
982                                         transmesh = tri->mesh;
983                                 }
984                                 tri->meshsortchain = tri->mesh->transchain;
985                                 tri->mesh->transchain = tri;
986                         }
987                 }
988         }
989
990         for (;transmesh;transmesh = transmesh->chain)
991         {
992                 if (currentmesh >= max_meshs || currenttriangle + transmesh->triangles > max_batch || currentvertex + transmesh->verts > max_verts)
993                         R_Mesh_Render();
994
995                 mesh = &buf_mesh[currentmesh++];
996                 *mesh = *transmesh; // copy mesh properties
997
998                 mesh->firstvert = currentvertex;
999                 memcpy(&buf_vertex[currentvertex], &buf_transvertex[transmesh->firstvert], transmesh->verts * sizeof(buf_vertex_t));
1000                 memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[transmesh->firstvert], transmesh->verts * sizeof(buf_fcolor_t));
1001                 for (i = 0;i < backendunits && transmesh->textures[i];i++)
1002                         memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][transmesh->firstvert], transmesh->verts * sizeof(buf_texcoord_t));
1003                 currentvertex += mesh->verts;
1004
1005                 mesh->firsttriangle = currenttriangle;
1006                 for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
1007                 {
1008                         buf_tri[currenttriangle].index[0] = tri->index[0];
1009                         buf_tri[currenttriangle].index[1] = tri->index[1];
1010                         buf_tri[currenttriangle].index[2] = tri->index[2];
1011                         currenttriangle++;
1012                 }
1013                 mesh->triangles = currenttriangle - mesh->firsttriangle;
1014         }
1015
1016         currenttransmesh = 0;
1017         currenttranstriangle = 0;
1018         currenttransvertex = 0;
1019 }
1020
1021 void R_Mesh_Draw(const rmeshinfo_t *m)
1022 {
1023         // these are static because gcc runs out of virtual registers otherwise
1024         static int i, j, overbright, *index;
1025         static float *in, scaler;
1026         static float cr, cg, cb, ca;
1027         static buf_mesh_t *mesh;
1028         static buf_vertex_t *vert;
1029         static buf_fcolor_t *fcolor;
1030         static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
1031
1032         if (!backendactive)
1033                 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1034
1035         if (m->index == NULL
1036          || !m->numtriangles
1037          || m->vertex == NULL
1038          || !m->numverts)
1039                 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1040
1041         // ignore meaningless alpha meshs
1042         if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
1043         {
1044                 if (m->color)
1045                 {
1046                         for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
1047                                 if (*in >= 0.01f)
1048                                         break;
1049                         if (i == m->numverts)
1050                                 return;
1051                 }
1052                 else if (m->ca < 0.01f)
1053                         return;
1054         }
1055
1056         if (!backendactive)
1057                 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1058
1059 #ifdef DEBUGGL
1060         for (i = 0;i < m->numtriangles * 3;i++)
1061                 if ((unsigned int) m->index[i] >= (unsigned int) m->numverts)
1062                         Host_Error("R_Mesh_Draw: invalid index (%i of %i verts)\n", m->index, m->numverts);
1063 #endif
1064
1065         if (m->transparent)
1066         {
1067                 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1068                 {
1069                         if (!transranout)
1070                         {
1071                                 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1072                                 transranout = true;
1073                         }
1074                         return;
1075                 }
1076
1077                 c_transmeshs++;
1078                 c_transtris += m->numtriangles;
1079                 vert = &buf_transvertex[currenttransvertex];
1080                 fcolor = &buf_transfcolor[currenttransvertex];
1081                 for (i = 0;i < backendunits;i++)
1082                         texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
1083
1084                 // transmesh is only for storage of transparent meshs until they
1085                 // are inserted into the main mesh array
1086                 mesh = &buf_transmesh[currenttransmesh++];
1087                 mesh->firsttriangle = currenttranstriangle;
1088                 mesh->firstvert = currenttransvertex;
1089                 index = &buf_transtri[currenttranstriangle].index[0];
1090
1091                 currenttranstriangle += m->numtriangles;
1092                 currenttransvertex += m->numverts;
1093         }
1094         else
1095         {
1096                 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1097                 {
1098                         Con_Printf("R_Mesh_Draw: mesh too big for buffers\n");
1099                         return;
1100                 }
1101
1102                 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1103                         R_Mesh_Render();
1104
1105                 c_meshs++;
1106                 c_meshtris += m->numtriangles;
1107                 vert = &buf_vertex[currentvertex];
1108                 fcolor = &buf_fcolor[currentvertex];
1109                 for (i = 0;i < backendunits;i++)
1110                         texcoord[i] = &buf_texcoord[i][currentvertex];
1111
1112                 // opaque meshs are rendered directly
1113                 mesh = &buf_mesh[currentmesh++];
1114                 mesh->firsttriangle = currenttriangle;
1115                 mesh->firstvert = currentvertex;
1116                 index = &buf_tri[currenttriangle].index[0];
1117
1118                 currenttriangle += m->numtriangles;
1119                 currentvertex += m->numverts;
1120         }
1121
1122         // code shared for transparent and opaque meshs
1123         memcpy(index, m->index, sizeof(int[3]) * m->numtriangles);
1124         mesh->blendfunc1 = m->blendfunc1;
1125         mesh->blendfunc2 = m->blendfunc2;
1126         mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1127         mesh->depthtest = !m->depthdisable;
1128         mesh->triangles = m->numtriangles;
1129         mesh->verts = m->numverts;
1130
1131         overbright = false;
1132         scaler = 1;
1133         if (m->blendfunc2 == GL_SRC_COLOR)
1134         {
1135                 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1136                         scaler *= 0.5f;
1137         }
1138         else
1139         {
1140                 if (m->tex[0])
1141                 {
1142                         overbright = gl_combine.integer;
1143                         if (overbright)
1144                                 scaler *= 0.25f;
1145                 }
1146                 scaler *= overbrightscale;
1147         }
1148
1149
1150         j = -1;
1151         for (i = 0;i < backendunits;i++)
1152         {
1153                 if ((mesh->textures[i] = m->tex[i]))
1154                         j = i;
1155                 mesh->texturergbscale[i] = m->texrgbscale[i];
1156                 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1157                         mesh->texturergbscale[i] = 1;
1158         }
1159         if (overbright && j >= 0)
1160                 mesh->texturergbscale[j] = 4;
1161
1162         if (m->vertexstep != sizeof(buf_vertex_t))
1163         {
1164                 for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
1165                 {
1166                         vert[i].v[0] = in[0];
1167                         vert[i].v[1] = in[1];
1168                         vert[i].v[2] = in[2];
1169                 }
1170         }
1171         else
1172                 memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1173
1174         if (m->color)
1175         {
1176                 for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
1177                 {
1178                         fcolor[i].c[0] = in[0] * scaler;
1179                         fcolor[i].c[1] = in[1] * scaler;
1180                         fcolor[i].c[2] = in[2] * scaler;
1181                         fcolor[i].c[3] = in[3];
1182                 }
1183         }
1184         else
1185         {
1186                 cr = m->cr * scaler;
1187                 cg = m->cg * scaler;
1188                 cb = m->cb * scaler;
1189                 ca = m->ca;
1190                 for (i = 0;i < m->numverts;i++)
1191                 {
1192                         fcolor[i].c[0] = cr;
1193                         fcolor[i].c[1] = cg;
1194                         fcolor[i].c[2] = cb;
1195                         fcolor[i].c[3] = ca;
1196                 }
1197         }
1198
1199         for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1200         {
1201                 if (j >= backendunits)
1202                         Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1203                 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1204                 {
1205                         for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
1206                         {
1207                                 texcoord[j][i].t[0] = in[0];
1208                                 texcoord[j][i].t[1] = in[1];
1209                         }
1210                 }
1211                 else
1212                         memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1213         }
1214         #if 0
1215         for (;j < backendunits;j++)
1216                 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1217         #endif
1218 }
1219
1220 void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m)
1221 {
1222         // these are static because gcc runs out of virtual registers otherwise
1223         static int i, j, overbright, *index;
1224         static float *in, scaler;
1225         static buf_mesh_t *mesh;
1226         static buf_vertex_t *vert;
1227         static buf_fcolor_t *fcolor;
1228         static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
1229
1230         if (!backendactive)
1231                 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1232
1233         if (m->index == NULL
1234          || !m->numtriangles
1235          || m->vertex == NULL
1236          || !m->numverts)
1237                 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1238
1239         // ignore meaningless alpha meshs
1240         if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
1241         {
1242                 if (m->color)
1243                 {
1244                         for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
1245                                 if (*in >= 0.01f)
1246                                         break;
1247                         if (i == m->numverts)
1248                                 return;
1249                 }
1250                 else if (m->ca < 0.01f)
1251                         return;
1252         }
1253
1254         if (m->transparent)
1255         {
1256                 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1257                 {
1258                         if (!transranout)
1259                         {
1260                                 Con_Printf("R_Mesh_Draw_NativeOnly: ran out of room for transparent meshs\n");
1261                                 transranout = true;
1262                         }
1263                         return;
1264                 }
1265
1266                 c_transmeshs++;
1267                 c_transtris += m->numtriangles;
1268                 vert = &buf_transvertex[currenttransvertex];
1269                 fcolor = &buf_transfcolor[currenttransvertex];
1270                 for (i = 0;i < backendunits;i++)
1271                         texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
1272
1273                 // transmesh is only for storage of transparent meshs until they
1274                 // are inserted into the main mesh array
1275                 mesh = &buf_transmesh[currenttransmesh++];
1276                 mesh->firsttriangle = currenttranstriangle;
1277                 mesh->firstvert = currenttransvertex;
1278                 index = &buf_transtri[currenttranstriangle].index[0];
1279                 currenttranstriangle += m->numtriangles;
1280                 currenttransvertex += m->numverts;
1281         }
1282         else
1283         {
1284                 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1285                 {
1286                         Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for buffers\n");
1287                         return;
1288                 }
1289
1290                 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1291                         R_Mesh_Render();
1292
1293                 c_meshs++;
1294                 c_meshtris += m->numtriangles;
1295                 vert = &buf_vertex[currentvertex];
1296                 fcolor = &buf_fcolor[currentvertex];
1297                 for (i = 0;i < backendunits;i++)
1298                         texcoord[i] = &buf_texcoord[i][currentvertex];
1299
1300                 // opaque meshs are rendered directly
1301                 mesh = &buf_mesh[currentmesh++];
1302                 mesh->firsttriangle = currenttriangle;
1303                 mesh->firstvert = currentvertex;
1304                 index = &buf_tri[currenttriangle].index[0];
1305                 currenttriangle += m->numtriangles;
1306                 currentvertex += m->numverts;
1307         }
1308
1309         // code shared for transparent and opaque meshs
1310         memcpy(index, m->index, sizeof(int[3]) * m->numtriangles);
1311         mesh->blendfunc1 = m->blendfunc1;
1312         mesh->blendfunc2 = m->blendfunc2;
1313         mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1314         mesh->depthtest = !m->depthdisable;
1315         mesh->triangles = m->numtriangles;
1316         mesh->verts = m->numverts;
1317
1318         overbright = false;
1319         scaler = 1;
1320         if (m->blendfunc2 == GL_SRC_COLOR)
1321         {
1322                 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1323                         scaler *= 0.5f;
1324         }
1325         else
1326         {
1327                 if (m->tex[0])
1328                 {
1329                         overbright = gl_combine.integer;
1330                         if (overbright)
1331                                 scaler *= 0.25f;
1332                 }
1333                 scaler *= overbrightscale;
1334         }
1335
1336         j = -1;
1337         for (i = 0;i < backendunits;i++)
1338         {
1339                 if ((mesh->textures[i] = m->tex[i]))
1340                         j = i;
1341                 mesh->texturergbscale[i] = m->texrgbscale[i];
1342                 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1343                         mesh->texturergbscale[i] = 1;
1344         }
1345         if (overbright && j >= 0)
1346                 mesh->texturergbscale[j] = 4;
1347
1348         if (m->vertexstep != sizeof(buf_vertex_t))
1349                 Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n");
1350         if (m->colorstep != sizeof(buf_fcolor_t))
1351                 Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n");
1352         if (m->color == NULL)
1353                 Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n");
1354         for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1355         {
1356                 if (j >= backendunits)
1357                         Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1358                 if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
1359                         Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n");
1360         }
1361
1362         memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
1363         for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
1364                 memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
1365         #if 0
1366         for (;j < backendunits;j++)
1367                 memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t));
1368         #endif
1369
1370         memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t));
1371
1372         // do this as a second step because memcpy preloaded the cache, which we can't easily do
1373         if (scaler != 1)
1374         {
1375                 for (i = 0;i < m->numverts;i++)
1376                 {
1377                         fcolor[i].c[0] *= scaler;
1378                         fcolor[i].c[1] *= scaler;
1379                         fcolor[i].c[2] *= scaler;
1380                 }
1381         }
1382 }
1383
1384 // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct
1385 // (this is used for very high speed rendering, no copying)
1386 int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m)
1387 {
1388         // these are static because gcc runs out of virtual registers otherwise
1389         int i, j, overbright;
1390         float scaler;
1391         buf_mesh_t *mesh;
1392
1393         if (!backendactive)
1394                 Sys_Error("R_Mesh_Draw: called when backend is not active\n");
1395
1396         if (!m->numtriangles
1397          || !m->numverts)
1398                 Host_Error("R_Mesh_Draw: no triangles or verts\n");
1399
1400         if (m->transparent)
1401         {
1402                 if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts)
1403                 {
1404                         if (!transranout)
1405                         {
1406                                 Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
1407                                 transranout = true;
1408                         }
1409                         return false;
1410                 }
1411
1412                 c_transmeshs++;
1413                 c_transtris += m->numtriangles;
1414                 m->index = &buf_transtri[currenttranstriangle].index[0];
1415                 m->vertex = &buf_transvertex[currenttransvertex].v[0];
1416                 m->color = &buf_transfcolor[currenttransvertex].c[0];
1417                 for (i = 0;i < backendunits;i++)
1418                         m->texcoords[i] = &buf_transtexcoord[i][currenttransvertex].t[0];
1419
1420                 // transmesh is only for storage of transparent meshs until they
1421                 // are inserted into the main mesh array
1422                 mesh = &buf_transmesh[currenttransmesh++];
1423                 mesh->firsttriangle = currenttranstriangle;
1424                 mesh->firstvert = currenttransvertex;
1425                 currenttranstriangle += m->numtriangles;
1426                 currenttransvertex += m->numverts;
1427         }
1428         else
1429         {
1430                 if (m->numtriangles > max_meshs || m->numverts > max_verts)
1431                 {
1432                         Con_Printf("R_Mesh_Draw_GetBuffer: mesh too big for buffers\n");
1433                         return false;
1434                 }
1435
1436                 if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
1437                         R_Mesh_Render();
1438
1439                 c_meshs++;
1440                 c_meshtris += m->numtriangles;
1441                 m->index = &buf_tri[currenttriangle].index[0];
1442                 m->vertex = &buf_vertex[currentvertex].v[0];
1443                 m->color = &buf_fcolor[currentvertex].c[0];
1444                 for (i = 0;i < backendunits;i++)
1445                         m->texcoords[i] = &buf_texcoord[i][currentvertex].t[0];
1446
1447                 // opaque meshs are rendered directly
1448                 mesh = &buf_mesh[currentmesh++];
1449                 mesh->firsttriangle = currenttriangle;
1450                 mesh->firstvert = currentvertex;
1451                 currenttriangle += m->numtriangles;
1452                 currentvertex += m->numverts;
1453         }
1454
1455         // code shared for transparent and opaque meshs
1456         mesh->blendfunc1 = m->blendfunc1;
1457         mesh->blendfunc2 = m->blendfunc2;
1458         mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
1459         mesh->depthtest = !m->depthdisable;
1460         mesh->triangles = m->numtriangles;
1461         mesh->verts = m->numverts;
1462
1463         overbright = false;
1464         scaler = 1;
1465         if (m->blendfunc2 == GL_SRC_COLOR)
1466         {
1467                 if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
1468                         scaler *= 0.5f;
1469         }
1470         else
1471         {
1472                 if (m->tex[0])
1473                 {
1474                         overbright = gl_combine.integer;
1475                         if (overbright)
1476                                 scaler *= 0.25f;
1477                 }
1478                 scaler *= overbrightscale;
1479         }
1480         m->colorscale = scaler;
1481
1482         j = -1;
1483         for (i = 0;i < MAX_TEXTUREUNITS;i++)
1484         {
1485                 if ((mesh->textures[i] = m->tex[i]))
1486                 {
1487                         j = i;
1488                         if (i >= backendunits)
1489                                 Sys_Error("R_Mesh_Draw_GetBuffer: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
1490                 }
1491                 mesh->texturergbscale[i] = m->texrgbscale[i];
1492                 if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
1493                         mesh->texturergbscale[i] = 1;
1494         }
1495         if (overbright && j >= 0)
1496                 mesh->texturergbscale[j] = 4;
1497
1498         return true;
1499 }
1500
1501 void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts)
1502 {
1503         m->index = polyindexarray;
1504         m->numverts = numverts;
1505         m->numtriangles = numverts - 2;
1506         if (m->numtriangles < 1)
1507         {
1508                 Con_Printf("R_Mesh_DrawPolygon: invalid vertex count\n");
1509                 return;
1510         }
1511         if (m->numtriangles >= 256)
1512         {
1513                 Con_Printf("R_Mesh_DrawPolygon: only up to 256 triangles (258 verts) supported\n");
1514                 return;
1515         }
1516         R_Mesh_Draw(m);
1517 }
1518
1519 /*
1520 ==============================================================================
1521
1522                                                 SCREEN SHOTS
1523
1524 ==============================================================================
1525 */
1526
1527 qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height)
1528 {
1529         qboolean ret;
1530         int i;
1531         qbyte *buffer;
1532
1533         if (!r_render.integer)
1534                 return false;
1535
1536         buffer = Mem_Alloc(tempmempool, width*height*3);
1537         qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
1538         CHECKGLERROR
1539
1540         // LordHavoc: compensate for v_overbrightbits when using hardware gamma
1541         if (v_hwgamma.integer)
1542                 for (i = 0;i < width * height * 3;i++)
1543                         buffer[i] <<= v_overbrightbits.integer;
1544
1545         ret = Image_WriteTGARGB_preflipped(filename, width, height, buffer);
1546
1547         Mem_Free(buffer);
1548         return ret;
1549 }
1550
1551 //=============================================================================
1552
1553 void R_ClearScreen(void)
1554 {
1555         if (r_render.integer)
1556         {
1557                 // clear to black
1558                 qglClearColor(0,0,0,0);CHECKGLERROR
1559                 // clear the screen
1560                 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);CHECKGLERROR
1561                 // set dithering mode
1562                 if (gl_dither.integer)
1563                 {
1564                         qglEnable(GL_DITHER);CHECKGLERROR
1565                 }
1566                 else
1567                 {
1568                         qglDisable(GL_DITHER);CHECKGLERROR
1569                 }
1570         }
1571 }
1572
1573 /*
1574 ==================
1575 SCR_UpdateScreen
1576
1577 This is called every frame, and can also be called explicitly to flush
1578 text to the screen.
1579 ==================
1580 */
1581 void SCR_UpdateScreen (void)
1582 {
1583         //Mem_CheckSentinelsGlobal();
1584         //R_TimeReport("memtest");
1585
1586         VID_Finish ();
1587
1588         R_TimeReport("finish");
1589
1590         if (gl_combine.integer && !gl_combine_extension)
1591                 Cvar_SetValue("gl_combine", 0);
1592
1593         lightscalebit = v_overbrightbits.integer;
1594         if (gl_combine.integer && r_multitexture.integer)
1595                 lightscalebit += 2;
1596
1597         lightscale = 1.0f / (float) (1 << lightscalebit);
1598         overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer);
1599
1600         R_TimeReport("setup");
1601
1602         R_ClearScreen();
1603
1604         R_TimeReport("clear");
1605
1606         if (scr_conlines < vid.conheight)
1607                 R_RenderView();
1608
1609         // draw 2D stuff
1610         R_DrawQueue();
1611
1612         // tell driver to commit it's partially full geometry queue to the rendering queue
1613         // (this doesn't wait for the commands themselves to complete)
1614         qglFlush();
1615 }