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