]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_backend.c
added gl_vbo cvar to allow disabling of vbo rendering (and vbo creation while loading...
[xonotic/darkplaces.git] / gl_backend.c
1
2 #include "quakedef.h"
3 #include "cl_collision.h"
4
5 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
6 cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0", "use glBegin(GL_TRIANGLES);glArrayElement();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
7 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
8 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
9 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
10
11 cvar_t r_render = {0, "r_render", "1", "enables rendering calls (you want this on!)"};
12 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
13 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
14 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
15 cvar_t gl_lockarrays = {0, "gl_lockarrays", "0", "enables use of glLockArraysEXT, may cause glitches with some broken drivers, and may be slower than normal"};
16 cvar_t gl_lockarrays_minimumvertices = {0, "gl_lockarrays_minimumvertices", "1", "minimum number of vertices required for use of glLockArraysEXT, setting this too low may reduce performance"};
17 cvar_t gl_vbo = {0, "gl_vbo", "1", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering"};
18
19 int gl_maxdrawrangeelementsvertices;
20 int gl_maxdrawrangeelementsindices;
21
22 #ifdef DEBUGGL
23 int errornumber = 0;
24
25 void GL_PrintError(int errornumber, char *filename, int linenumber)
26 {
27         switch(errornumber)
28         {
29 #ifdef GL_INVALID_ENUM
30         case GL_INVALID_ENUM:
31                 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
32                 break;
33 #endif
34 #ifdef GL_INVALID_VALUE
35         case GL_INVALID_VALUE:
36                 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
37                 break;
38 #endif
39 #ifdef GL_INVALID_OPERATION
40         case GL_INVALID_OPERATION:
41                 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
42                 break;
43 #endif
44 #ifdef GL_STACK_OVERFLOW
45         case GL_STACK_OVERFLOW:
46                 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
47                 break;
48 #endif
49 #ifdef GL_STACK_UNDERFLOW
50         case GL_STACK_UNDERFLOW:
51                 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
52                 break;
53 #endif
54 #ifdef GL_OUT_OF_MEMORY
55         case GL_OUT_OF_MEMORY:
56                 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
57                 break;
58 #endif
59 #ifdef GL_TABLE_TOO_LARGE
60         case GL_TABLE_TOO_LARGE:
61                 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
62                 break;
63 #endif
64         default:
65                 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
66                 break;
67         }
68 }
69 #endif
70
71 #define BACKENDACTIVECHECK if (!backendactive) Sys_Error("GL backend function called when backend is not active");
72
73 void SCR_ScreenShot_f (void);
74
75 static matrix4x4_t backend_viewmatrix;
76 static matrix4x4_t backend_modelmatrix;
77 static matrix4x4_t backend_modelviewmatrix;
78 static matrix4x4_t backend_projectmatrix;
79
80 static unsigned int backendunits, backendimageunits, backendarrayunits, backendactive;
81
82 /*
83 note: here's strip order for a terrain row:
84 0--1--2--3--4
85 |\ |\ |\ |\ |
86 | \| \| \| \|
87 A--B--C--D--E
88 clockwise
89
90 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
91
92 *elements++ = i + row;
93 *elements++ = i;
94 *elements++ = i + row + 1;
95 *elements++ = i;
96 *elements++ = i + 1;
97 *elements++ = i + row + 1;
98
99
100 for (y = 0;y < rows - 1;y++)
101 {
102         for (x = 0;x < columns - 1;x++)
103         {
104                 i = y * rows + x;
105                 *elements++ = i + columns;
106                 *elements++ = i;
107                 *elements++ = i + columns + 1;
108                 *elements++ = i;
109                 *elements++ = i + 1;
110                 *elements++ = i + columns + 1;
111         }
112 }
113
114 alternative:
115 0--1--2--3--4
116 | /| /|\ | /|
117 |/ |/ | \|/ |
118 A--B--C--D--E
119 counterclockwise
120
121 for (y = 0;y < rows - 1;y++)
122 {
123         for (x = 0;x < columns - 1;x++)
124         {
125                 i = y * rows + x;
126                 *elements++ = i;
127                 *elements++ = i + columns;
128                 *elements++ = i + columns + 1;
129                 *elements++ = i + columns;
130                 *elements++ = i + columns + 1;
131                 *elements++ = i + 1;
132         }
133 }
134 */
135
136 int polygonelements[(POLYGONELEMENTS_MAXPOINTS-2)*3];
137 int quadelements[QUADELEMENTS_MAXQUADS*6];
138
139 void GL_Backend_AllocArrays(void)
140 {
141 }
142
143 void GL_Backend_FreeArrays(void)
144 {
145 }
146
147 static void gl_backend_start(void)
148 {
149         Con_Print("OpenGL Backend starting...\n");
150         CHECKGLERROR
151
152         if (qglDrawRangeElements != NULL)
153         {
154                 CHECKGLERROR
155                 qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
156                 CHECKGLERROR
157                 qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
158                 CHECKGLERROR
159                 Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
160         }
161
162         backendunits = bound(1, gl_textureunits, MAX_TEXTUREUNITS);
163         backendimageunits = backendunits;
164         backendarrayunits = backendunits;
165         if (gl_support_fragment_shader)
166         {
167                 CHECKGLERROR
168                 qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, (int *)&backendimageunits);
169                 CHECKGLERROR
170                 qglGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, (int *)&backendarrayunits);
171                 CHECKGLERROR
172                 Con_Printf("GLSL shader support detected: texture units = %i texenv, %i image, %i array\n", backendunits, backendimageunits, backendarrayunits);
173                 backendimageunits = bound(1, backendimageunits, MAX_TEXTUREUNITS);
174                 backendarrayunits = bound(1, backendarrayunits, MAX_TEXTUREUNITS);
175         }
176         else if (backendunits > 1)
177                 Con_Printf("multitexture detected: texture units = %i\n", backendunits);
178         else
179                 Con_Printf("singletexture\n");
180
181         GL_Backend_AllocArrays();
182
183         Con_Printf("OpenGL backend started.\n");
184
185         CHECKGLERROR
186
187         backendactive = true;
188 }
189
190 static void gl_backend_shutdown(void)
191 {
192         backendunits = 0;
193         backendimageunits = 0;
194         backendarrayunits = 0;
195         backendactive = false;
196
197         Con_Print("OpenGL Backend shutting down\n");
198
199         GL_Backend_FreeArrays();
200 }
201
202 static void gl_backend_newmap(void)
203 {
204 }
205
206 void gl_backend_init(void)
207 {
208         int i;
209
210         for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
211         {
212                 polygonelements[i * 3 + 0] = 0;
213                 polygonelements[i * 3 + 1] = i + 1;
214                 polygonelements[i * 3 + 2] = i + 2;
215         }
216         // elements for rendering a series of quads as triangles
217         for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
218         {
219                 quadelements[i * 6 + 0] = i * 4;
220                 quadelements[i * 6 + 1] = i * 4 + 1;
221                 quadelements[i * 6 + 2] = i * 4 + 2;
222                 quadelements[i * 6 + 3] = i * 4;
223                 quadelements[i * 6 + 4] = i * 4 + 2;
224                 quadelements[i * 6 + 5] = i * 4 + 3;
225         }
226
227         Cvar_RegisterVariable(&r_render);
228         Cvar_RegisterVariable(&r_waterwarp);
229         Cvar_RegisterVariable(&gl_polyblend);
230         Cvar_RegisterVariable(&gl_dither);
231         Cvar_RegisterVariable(&gl_lockarrays);
232         Cvar_RegisterVariable(&gl_lockarrays_minimumvertices);
233         Cvar_RegisterVariable(&gl_vbo);
234         Cvar_RegisterVariable(&gl_paranoid);
235         Cvar_RegisterVariable(&gl_printcheckerror);
236 #ifdef NORENDER
237         Cvar_SetValue("r_render", 0);
238 #endif
239
240         Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
241         Cvar_RegisterVariable(&gl_mesh_testarrayelement);
242         Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
243
244         R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
245 }
246
247 void GL_SetupView_Orientation_Identity (void)
248 {
249         backend_viewmatrix = identitymatrix;
250         memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
251 }
252
253 void GL_SetupView_Orientation_FromEntity(const matrix4x4_t *matrix)
254 {
255         matrix4x4_t tempmatrix, basematrix;
256         Matrix4x4_Invert_Simple(&tempmatrix, matrix);
257         Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
258         Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
259         Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix);
260         //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
261         //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
262         //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
263         //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
264         memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
265 }
266
267 void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
268 {
269         double m[16];
270
271         // set up viewpoint
272         CHECKGLERROR
273         qglMatrixMode(GL_PROJECTION);CHECKGLERROR
274         qglLoadIdentity();CHECKGLERROR
275         // set view pyramid
276         qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
277         qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
278         Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
279         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
280         GL_SetupView_Orientation_Identity();
281         CHECKGLERROR
282 }
283
284 void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
285 {
286         double nudge, m[16];
287
288         // set up viewpoint
289         CHECKGLERROR
290         qglMatrixMode(GL_PROJECTION);CHECKGLERROR
291         qglLoadIdentity();CHECKGLERROR
292         // set view pyramid
293         nudge = 1.0 - 1.0 / (1<<23);
294         m[ 0] = 1.0 / frustumx;
295         m[ 1] = 0;
296         m[ 2] = 0;
297         m[ 3] = 0;
298         m[ 4] = 0;
299         m[ 5] = 1.0 / frustumy;
300         m[ 6] = 0;
301         m[ 7] = 0;
302         m[ 8] = 0;
303         m[ 9] = 0;
304         m[10] = -nudge;
305         m[11] = -1;
306         m[12] = 0;
307         m[13] = 0;
308         m[14] = -2 * zNear * nudge;
309         m[15] = 0;
310         qglLoadMatrixd(m);CHECKGLERROR
311         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
312         GL_SetupView_Orientation_Identity();
313         CHECKGLERROR
314         Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
315 }
316
317 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
318 {
319         double m[16];
320
321         // set up viewpoint
322         CHECKGLERROR
323         qglMatrixMode(GL_PROJECTION);CHECKGLERROR
324         qglLoadIdentity();CHECKGLERROR
325         qglOrtho(x1, x2, y2, y1, zNear, zFar);CHECKGLERROR
326         qglGetDoublev(GL_PROJECTION_MATRIX, m);CHECKGLERROR
327         Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
328         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
329         GL_SetupView_Orientation_Identity();
330         CHECKGLERROR
331 }
332
333 typedef struct gltextureunit_s
334 {
335         const void *pointer_texcoord;
336         size_t pointer_texcoord_offset;
337         int pointer_texcoord_buffer;
338         int t1d, t2d, t3d, tcubemap;
339         int arrayenabled;
340         unsigned int arraycomponents;
341         int rgbscale, alphascale;
342         int combinergb, combinealpha;
343         // FIXME: add more combine stuff
344         // texmatrixenabled exists only to avoid unnecessary texmatrix compares
345         int texmatrixenabled;
346         matrix4x4_t matrix;
347 }
348 gltextureunit_t;
349
350 static struct gl_state_s
351 {
352         int cullface;
353         int cullfaceenable;
354         int blendfunc1;
355         int blendfunc2;
356         int blend;
357         GLboolean depthmask;
358         int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
359         int depthtest;
360         int alphatest;
361         int scissortest;
362         unsigned int unit;
363         unsigned int clientunit;
364         gltextureunit_t units[MAX_TEXTUREUNITS];
365         float color4f[4];
366         int lockrange_first;
367         int lockrange_count;
368         int vertexbufferobject;
369         int elementbufferobject;
370         qboolean pointer_color_enabled;
371         const void *pointer_vertex;
372         const void *pointer_color;
373         size_t pointer_vertex_offset;
374         size_t pointer_color_offset;
375         int pointer_vertex_buffer;
376         int pointer_color_buffer;
377 }
378 gl_state;
379
380 static void GL_BindVBO(int bufferobject)
381 {
382         if (gl_state.vertexbufferobject != bufferobject)
383         {
384                 gl_state.vertexbufferobject = bufferobject;
385                 CHECKGLERROR
386                 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);
387                 CHECKGLERROR
388         }
389 }
390
391 static void GL_BindEBO(int bufferobject)
392 {
393         if (gl_state.elementbufferobject != bufferobject)
394         {
395                 gl_state.elementbufferobject = bufferobject;
396                 CHECKGLERROR
397                 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);
398                 CHECKGLERROR
399         }
400 }
401
402 void GL_SetupTextureState(void)
403 {
404         unsigned int i;
405         gltextureunit_t *unit;
406         CHECKGLERROR
407         gl_state.unit = MAX_TEXTUREUNITS;
408         gl_state.clientunit = MAX_TEXTUREUNITS;
409         for (i = 0;i < MAX_TEXTUREUNITS;i++)
410         {
411                 unit = gl_state.units + i;
412                 unit->t1d = 0;
413                 unit->t2d = 0;
414                 unit->t3d = 0;
415                 unit->tcubemap = 0;
416                 unit->arrayenabled = false;
417                 unit->arraycomponents = 0;
418                 unit->pointer_texcoord = NULL;
419                 unit->pointer_texcoord_buffer = 0;
420                 unit->pointer_texcoord_offset = 0;
421                 unit->rgbscale = 1;
422                 unit->alphascale = 1;
423                 unit->combinergb = GL_MODULATE;
424                 unit->combinealpha = GL_MODULATE;
425                 unit->texmatrixenabled = false;
426                 unit->matrix = identitymatrix;
427         }
428
429         for (i = 0;i < backendimageunits;i++)
430         {
431                 GL_ActiveTexture(i);
432                 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
433                 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
434                 if (gl_texture3d)
435                 {
436                         qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
437                 }
438                 if (gl_texturecubemap)
439                 {
440                         qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
441                 }
442         }
443
444         for (i = 0;i < backendarrayunits;i++)
445         {
446                 GL_ClientActiveTexture(i);
447                 GL_BindVBO(0);
448                 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
449                 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
450         }
451
452         for (i = 0;i < backendunits;i++)
453         {
454                 GL_ActiveTexture(i);
455                 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
456                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
457                 if (gl_texture3d)
458                 {
459                         qglDisable(GL_TEXTURE_3D);CHECKGLERROR
460                 }
461                 if (gl_texturecubemap)
462                 {
463                         qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
464                 }
465                 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
466                 qglLoadIdentity();CHECKGLERROR
467                 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
468                 if (gl_combine.integer)
469                 {
470                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
471                         qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
472                         qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
473                         qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
474                         qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
475                         qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
476                         qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
477                         qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
478                         qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
479                         qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
480                         qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
481                         qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
482                         qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
483                         qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
484                         qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
485                         qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
486                         qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
487                 }
488                 else
489                 {
490                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
491                 }
492                 CHECKGLERROR
493         }
494         CHECKGLERROR
495 }
496
497 void GL_Backend_ResetState(void)
498 {
499         memset(&gl_state, 0, sizeof(gl_state));
500         gl_state.depthtest = true;
501         gl_state.alphatest = false;
502         gl_state.blendfunc1 = GL_ONE;
503         gl_state.blendfunc2 = GL_ZERO;
504         gl_state.blend = false;
505         gl_state.depthmask = GL_TRUE;
506         gl_state.colormask = 15;
507         gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
508         gl_state.lockrange_first = 0;
509         gl_state.lockrange_count = 0;
510         gl_state.cullface = GL_FRONT; // quake is backwards, this culls back faces
511         gl_state.cullfaceenable = true;
512
513         CHECKGLERROR
514
515         qglColorMask(1, 1, 1, 1);
516         qglAlphaFunc(GL_GEQUAL, 0.5);CHECKGLERROR
517         qglDisable(GL_ALPHA_TEST);CHECKGLERROR
518         qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
519         qglDisable(GL_BLEND);CHECKGLERROR
520         qglCullFace(gl_state.cullface);CHECKGLERROR
521         qglEnable(GL_CULL_FACE);CHECKGLERROR
522         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
523         qglEnable(GL_DEPTH_TEST);CHECKGLERROR
524         qglDepthMask(gl_state.depthmask);CHECKGLERROR
525
526         if (gl_support_arb_vertex_buffer_object)
527         {
528                 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
529                 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
530         }
531
532         qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
533         qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
534
535         qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
536         qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
537
538         GL_Color(0, 0, 0, 0);
539         GL_Color(1, 1, 1, 1);
540
541         GL_SetupTextureState();
542 }
543
544 void GL_ActiveTexture(unsigned int num)
545 {
546         if (gl_state.unit != num)
547         {
548                 gl_state.unit = num;
549                 if (qglActiveTexture)
550                 {
551                         CHECKGLERROR
552                         qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
553                         CHECKGLERROR
554                 }
555         }
556 }
557
558 void GL_ClientActiveTexture(unsigned int num)
559 {
560         if (gl_state.clientunit != num)
561         {
562                 gl_state.clientunit = num;
563                 if (qglActiveTexture)
564                 {
565                         CHECKGLERROR
566                         qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
567                         CHECKGLERROR
568                 }
569         }
570 }
571
572 void GL_BlendFunc(int blendfunc1, int blendfunc2)
573 {
574         if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
575         {
576                 CHECKGLERROR
577                 qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR
578                 if (gl_state.blendfunc2 == GL_ZERO)
579                 {
580                         if (gl_state.blendfunc1 == GL_ONE)
581                         {
582                                 if (gl_state.blend)
583                                 {
584                                         gl_state.blend = 0;
585                                         qglDisable(GL_BLEND);CHECKGLERROR
586                                 }
587                         }
588                         else
589                         {
590                                 if (!gl_state.blend)
591                                 {
592                                         gl_state.blend = 1;
593                                         qglEnable(GL_BLEND);CHECKGLERROR
594                                 }
595                         }
596                 }
597                 else
598                 {
599                         if (!gl_state.blend)
600                         {
601                                 gl_state.blend = 1;
602                                 qglEnable(GL_BLEND);CHECKGLERROR
603                         }
604                 }
605         }
606 }
607
608 void GL_DepthMask(int state)
609 {
610         if (gl_state.depthmask != state)
611         {
612                 CHECKGLERROR
613                 qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
614         }
615 }
616
617 void GL_DepthTest(int state)
618 {
619         if (gl_state.depthtest != state)
620         {
621                 gl_state.depthtest = state;
622                 CHECKGLERROR
623                 if (gl_state.depthtest)
624                 {
625                         qglEnable(GL_DEPTH_TEST);CHECKGLERROR
626                 }
627                 else
628                 {
629                         qglDisable(GL_DEPTH_TEST);CHECKGLERROR
630                 }
631         }
632 }
633
634 void GL_CullFace(int state)
635 {
636         CHECKGLERROR
637         if (state != GL_NONE)
638         {
639                 if (!gl_state.cullfaceenable)
640                 {
641                         gl_state.cullfaceenable = true;
642                         qglEnable(GL_CULL_FACE);CHECKGLERROR
643                 }
644                 if (gl_state.cullface != state)
645                 {
646                         gl_state.cullface = state;
647                         qglCullFace(gl_state.cullface);CHECKGLERROR
648                 }
649         }
650         else
651         {
652                 if (gl_state.cullfaceenable)
653                 {
654                         gl_state.cullfaceenable = false;
655                         qglDisable(GL_CULL_FACE);CHECKGLERROR
656                 }
657         }
658 }
659
660 void GL_AlphaTest(int state)
661 {
662         if (gl_state.alphatest != state)
663         {
664                 gl_state.alphatest = state;
665                 CHECKGLERROR
666                 if (gl_state.alphatest)
667                 {
668                         qglEnable(GL_ALPHA_TEST);CHECKGLERROR
669                 }
670                 else
671                 {
672                         qglDisable(GL_ALPHA_TEST);CHECKGLERROR
673                 }
674         }
675 }
676
677 void GL_ColorMask(int r, int g, int b, int a)
678 {
679         int state = r*8 + g*4 + b*2 + a*1;
680         if (gl_state.colormask != state)
681         {
682                 gl_state.colormask = state;
683                 CHECKGLERROR
684                 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
685         }
686 }
687
688 void GL_Color(float cr, float cg, float cb, float ca)
689 {
690         if (gl_state.pointer_color_enabled || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
691         {
692                 gl_state.color4f[0] = cr;
693                 gl_state.color4f[1] = cg;
694                 gl_state.color4f[2] = cb;
695                 gl_state.color4f[3] = ca;
696                 CHECKGLERROR
697                 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
698                 CHECKGLERROR
699         }
700 }
701
702 void GL_LockArrays(int first, int count)
703 {
704         if (count < gl_lockarrays_minimumvertices.integer)
705         {
706                 first = 0;
707                 count = 0;
708         }
709         if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
710         {
711                 if (gl_state.lockrange_count)
712                 {
713                         gl_state.lockrange_count = 0;
714                         CHECKGLERROR
715                         qglUnlockArraysEXT();
716                         CHECKGLERROR
717                 }
718                 if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer)
719                 {
720                         gl_state.lockrange_first = first;
721                         gl_state.lockrange_count = count;
722                         CHECKGLERROR
723                         qglLockArraysEXT(first, count);
724                         CHECKGLERROR
725                 }
726         }
727 }
728
729 void GL_Scissor (int x, int y, int width, int height)
730 {
731         CHECKGLERROR
732         qglScissor(x, vid.height - (y + height),width,height);
733         CHECKGLERROR
734 }
735
736 void GL_ScissorTest(int state)
737 {
738         if(gl_state.scissortest == state)
739                 return;
740
741         CHECKGLERROR
742         if((gl_state.scissortest = state))
743                 qglEnable(GL_SCISSOR_TEST);
744         else
745                 qglDisable(GL_SCISSOR_TEST);
746         CHECKGLERROR
747 }
748
749 void GL_Clear(int mask)
750 {
751         CHECKGLERROR
752         qglClear(mask);CHECKGLERROR
753 }
754
755 void GL_TransformToScreen(const vec4_t in, vec4_t out)
756 {
757         vec4_t temp;
758         float iw;
759         Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
760         Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
761         iw = 1.0f / out[3];
762         out[0] = r_view.x + (out[0] * iw + 1.0f) * r_view.width * 0.5f;
763         out[1] = r_view.y + r_view.height - (out[1] * iw + 1.0f) * r_view.height * 0.5f;
764         out[2] = r_view.z + (out[2] * iw + 1.0f) * r_view.depth * 0.5f;
765 }
766
767 // called at beginning of frame
768 void R_Mesh_Start(void)
769 {
770         BACKENDACTIVECHECK
771         CHECKGLERROR
772         if (gl_printcheckerror.integer && !gl_paranoid.integer)
773         {
774                 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
775                 Cvar_SetValueQuick(&gl_paranoid, 1);
776         }
777         GL_Backend_ResetState();
778 }
779
780 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
781 {
782         int shaderobject;
783         int shadercompiled;
784         char compilelog[MAX_INPUTLINE];
785         shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
786         if (!shaderobject)
787                 return false;
788         qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
789         qglCompileShaderARB(shaderobject);CHECKGLERROR
790         qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
791         qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
792         if (compilelog[0])
793                 Con_DPrintf("%s shader compile log:\n%s\n", shadertype, compilelog);
794         if (!shadercompiled)
795         {
796                 qglDeleteObjectARB(shaderobject);CHECKGLERROR
797                 return false;
798         }
799         qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
800         qglDeleteObjectARB(shaderobject);CHECKGLERROR
801         return true;
802 }
803
804 unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int geometrystrings_count, const char **geometrystrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
805 {
806         GLint programlinked;
807         GLuint programobject = 0;
808         char linklog[MAX_INPUTLINE];
809         CHECKGLERROR
810
811         programobject = qglCreateProgramObjectARB();CHECKGLERROR
812         if (!programobject)
813                 return 0;
814
815         if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
816                 goto cleanup;
817
818 #ifdef GL_GEOMETRY_SHADER_ARB
819         if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
820                 goto cleanup;
821 #endif
822
823         if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
824                 goto cleanup;
825
826         qglLinkProgramARB(programobject);CHECKGLERROR
827         qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
828         qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
829         if (linklog[0])
830         {
831                 Con_DPrintf("program link log:\n%s\n", linklog);
832                 // software vertex shader is ok but software fragment shader is WAY
833                 // too slow, fail program if so.
834                 // NOTE: this string might be ATI specific, but that's ok because the
835                 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
836                 // software fragment shader due to low instruction and dependent
837                 // texture limits.
838                 if (strstr(linklog, "fragment shader will run in software"))
839                         programlinked = false;
840         }
841         if (!programlinked)
842                 goto cleanup;
843         return programobject;
844 cleanup:
845         qglDeleteObjectARB(programobject);CHECKGLERROR
846         return 0;
847 }
848
849 void GL_Backend_FreeProgram(unsigned int prog)
850 {
851         CHECKGLERROR
852         qglDeleteObjectARB(prog);
853         CHECKGLERROR
854 }
855
856 int gl_backend_rebindtextures;
857
858 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
859 {
860         int i;
861         if (offset)
862         {
863                 for (i = 0;i < count;i++)
864                         *out++ = *in++ + offset;
865         }
866         else
867                 memcpy(out, in, sizeof(*out) * count);
868 }
869
870 // renders triangles using vertices from the active arrays
871 int paranoidblah = 0;
872 void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements, int bufferobject, size_t bufferoffset)
873 {
874         unsigned int numelements = numtriangles * 3;
875         if (numvertices < 3 || numtriangles < 1)
876         {
877                 Con_Printf("R_Mesh_Draw(%d, %d, %d, %8p, %i, %p);\n", firstvertex, numvertices, numtriangles, elements, bufferobject, (void *)bufferoffset);
878                 return;
879         }
880         if (!gl_vbo.integer)
881                 bufferobject = 0;
882         CHECKGLERROR
883         r_refdef.stats.meshes++;
884         r_refdef.stats.meshes_elements += numelements;
885         if (gl_paranoid.integer)
886         {
887                 unsigned int i, j, size;
888                 const int *p;
889                 // note: there's no validation done here on buffer objects because it
890                 // is somewhat difficult to get at the data, and gl_paranoid can be
891                 // used without buffer objects if the need arises
892                 // (the data could be gotten using glMapBuffer but it would be very
893                 //  slow due to uncachable video memory reads)
894                 if (!qglIsEnabled(GL_VERTEX_ARRAY))
895                         Con_Print("R_Mesh_Draw: vertex array not enabled\n");
896                 CHECKGLERROR
897                 if (gl_state.pointer_vertex)
898                         for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
899                                 paranoidblah += *p;
900                 if (gl_state.pointer_color_enabled)
901                 {
902                         if (!qglIsEnabled(GL_COLOR_ARRAY))
903                                 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
904                         CHECKGLERROR
905                         if (gl_state.pointer_color && gl_state.pointer_color_enabled)
906                                 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
907                                         paranoidblah += *p;
908                 }
909                 for (i = 0;i < backendarrayunits;i++)
910                 {
911                         if (gl_state.units[i].arrayenabled)
912                         {
913                                 GL_ClientActiveTexture(i);
914                                 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
915                                         Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
916                                 CHECKGLERROR
917                                 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
918                                         for (j = 0, size = numvertices * gl_state.units[i].arraycomponents, p = (int *)((float *)gl_state.units[i].pointer_texcoord + firstvertex * gl_state.units[i].arraycomponents);j < size;j++, p++)
919                                                 paranoidblah += *p;
920                         }
921                 }
922                 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
923                 {
924                         if (elements[i] < firstvertex || elements[i] >= firstvertex + numvertices)
925                         {
926                                 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in elements list\n", elements[i], firstvertex, firstvertex + numvertices);
927                                 return;
928                         }
929                 }
930                 CHECKGLERROR
931         }
932         if (r_render.integer)
933         {
934                 CHECKGLERROR
935                 if (gl_mesh_testmanualfeeding.integer)
936                 {
937                         unsigned int i, j;
938                         const GLfloat *p;
939                         qglBegin(GL_TRIANGLES);
940                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
941                         {
942                                 for (j = 0;j < backendarrayunits;j++)
943                                 {
944                                         if (gl_state.units[j].pointer_texcoord && gl_state.units[j].arrayenabled)
945                                         {
946                                                 if (backendarrayunits > 1)
947                                                 {
948                                                         if (gl_state.units[j].arraycomponents == 4)
949                                                         {
950                                                                 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
951                                                                 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
952                                                         }
953                                                         else if (gl_state.units[j].arraycomponents == 3)
954                                                         {
955                                                                 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
956                                                                 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
957                                                         }
958                                                         else if (gl_state.units[j].arraycomponents == 2)
959                                                         {
960                                                                 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
961                                                                 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
962                                                         }
963                                                         else
964                                                         {
965                                                                 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
966                                                                 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
967                                                         }
968                                                 }
969                                                 else
970                                                 {
971                                                         if (gl_state.units[j].arraycomponents == 4)
972                                                         {
973                                                                 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
974                                                                 qglTexCoord4f(p[0], p[1], p[2], p[3]);
975                                                         }
976                                                         else if (gl_state.units[j].arraycomponents == 3)
977                                                         {
978                                                                 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
979                                                                 qglTexCoord3f(p[0], p[1], p[2]);
980                                                         }
981                                                         else if (gl_state.units[j].arraycomponents == 2)
982                                                         {
983                                                                 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
984                                                                 qglTexCoord2f(p[0], p[1]);
985                                                         }
986                                                         else
987                                                         {
988                                                                 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
989                                                                 qglTexCoord1f(p[0]);
990                                                         }
991                                                 }
992                                         }
993                                 }
994                                 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
995                                 {
996                                         p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4;
997                                         qglColor4f(p[0], p[1], p[2], p[3]);
998                                 }
999                                 p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3;
1000                                 qglVertex3f(p[0], p[1], p[2]);
1001                         }
1002                         qglEnd();
1003                         CHECKGLERROR
1004                 }
1005                 else if (gl_mesh_testarrayelement.integer)
1006                 {
1007                         int i;
1008                         qglBegin(GL_TRIANGLES);
1009                         for (i = 0;i < numtriangles * 3;i++)
1010                         {
1011                                 qglArrayElement(elements[i]);
1012                         }
1013                         qglEnd();
1014                         CHECKGLERROR
1015                 }
1016                 else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
1017                 {
1018                         GL_BindEBO(bufferobject);
1019                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, bufferobject ? (void *)bufferoffset : elements);
1020                         CHECKGLERROR
1021                 }
1022                 else
1023                 {
1024                         GL_BindEBO(bufferobject);
1025                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, bufferobject ? (void *)bufferoffset : elements);
1026                         CHECKGLERROR
1027                 }
1028         }
1029 }
1030
1031 // restores backend state, used when done with 3D rendering
1032 void R_Mesh_Finish(void)
1033 {
1034         unsigned int i;
1035         BACKENDACTIVECHECK
1036         CHECKGLERROR
1037         GL_LockArrays(0, 0);
1038         CHECKGLERROR
1039
1040         for (i = 0;i < backendimageunits;i++)
1041         {
1042                 GL_ActiveTexture(i);
1043                 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
1044                 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1045                 if (gl_texture3d)
1046                 {
1047                         qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1048                 }
1049                 if (gl_texturecubemap)
1050                 {
1051                         qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1052                 }
1053         }
1054         for (i = 0;i < backendarrayunits;i++)
1055         {
1056                 GL_ActiveTexture(backendarrayunits - 1 - i);
1057                 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1058         }
1059         for (i = 0;i < backendunits;i++)
1060         {
1061                 GL_ActiveTexture(backendunits - 1 - i);
1062                 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1063                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1064                 if (gl_texture3d)
1065                 {
1066                         qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1067                 }
1068                 if (gl_texturecubemap)
1069                 {
1070                         qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1071                 }
1072                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1073                 if (gl_combine.integer)
1074                 {
1075                         qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
1076                         qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
1077                 }
1078         }
1079         qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1080         qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1081
1082         qglDisable(GL_BLEND);CHECKGLERROR
1083         qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1084         qglDepthMask(GL_TRUE);CHECKGLERROR
1085         qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
1086 }
1087
1088 int R_Mesh_CreateStaticEBO(void *data, size_t size)
1089 {
1090         GLuint bufferobject;
1091         if (!gl_vbo.integer)
1092                 return 0;
1093         qglGenBuffersARB(1, &bufferobject);
1094         GL_BindEBO(bufferobject);
1095         qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, data, GL_STATIC_DRAW_ARB);
1096         return (int)bufferobject;
1097 }
1098
1099 void R_Mesh_DestroyEBO(int bufferobject)
1100 {
1101         qglDeleteBuffersARB(1, (GLuint *)&bufferobject);
1102 }
1103
1104 int R_Mesh_CreateStaticVBO(void *data, size_t size)
1105 {
1106         GLuint bufferobject;
1107         if (!gl_vbo.integer)
1108                 return 0;
1109         qglGenBuffersARB(1, &bufferobject);
1110         GL_BindVBO(bufferobject);
1111         qglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, data, GL_STATIC_DRAW_ARB);
1112         return (int)bufferobject;
1113 }
1114
1115 void R_Mesh_DestroyVBO(int bufferobject)
1116 {
1117         qglDeleteBuffersARB(1, (GLuint *)&bufferobject);
1118 }
1119
1120 void R_Mesh_Matrix(const matrix4x4_t *matrix)
1121 {
1122         if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
1123         {
1124                 double glmatrix[16];
1125                 backend_modelmatrix = *matrix;
1126                 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
1127                 Matrix4x4_ToArrayDoubleGL(&backend_modelviewmatrix, glmatrix);
1128                 CHECKGLERROR
1129                 qglLoadMatrixd(glmatrix);CHECKGLERROR
1130         }
1131 }
1132
1133 void R_Mesh_VertexPointer(const float *vertex3f, int bufferobject, size_t bufferoffset)
1134 {
1135         if (!gl_vbo.integer)
1136                 bufferobject = 0;
1137         if (gl_state.pointer_vertex != vertex3f || gl_state.pointer_vertex_buffer != bufferobject || gl_state.pointer_vertex_offset != bufferoffset)
1138         {
1139                 gl_state.pointer_vertex = vertex3f;
1140                 gl_state.pointer_vertex_buffer = bufferobject;
1141                 gl_state.pointer_vertex_offset = bufferoffset;
1142                 CHECKGLERROR
1143                 GL_BindVBO(bufferobject);
1144                 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), bufferobject ? (void *)bufferoffset : vertex3f);CHECKGLERROR
1145         }
1146 }
1147
1148 void R_Mesh_ColorPointer(const float *color4f, int bufferobject, size_t bufferoffset)
1149 {
1150         // note: this can not rely on bufferobject to decide whether a color array
1151         // is supplied, because surfmesh_t shares one vbo for all arrays, which
1152         // means that a valid vbo may be supplied even if there is no color array.
1153         if (color4f)
1154         {
1155                 if (!gl_vbo.integer)
1156                         bufferobject = 0;
1157                 // caller wants color array enabled
1158                 if (!gl_state.pointer_color_enabled)
1159                 {
1160                         gl_state.pointer_color_enabled = true;
1161                         CHECKGLERROR
1162                         qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1163                 }
1164                 if (gl_state.pointer_color != color4f || gl_state.pointer_color_buffer != bufferobject || gl_state.pointer_color_offset != bufferoffset)
1165                 {
1166                         gl_state.pointer_color = color4f;
1167                         gl_state.pointer_color_buffer = bufferobject;
1168                         gl_state.pointer_color_offset = bufferoffset;
1169                         CHECKGLERROR
1170                         GL_BindVBO(bufferobject);
1171                         qglColorPointer(4, GL_FLOAT, sizeof(float[4]), bufferobject ? (void *)bufferoffset : color4f);CHECKGLERROR
1172                 }
1173         }
1174         else
1175         {
1176                 // caller wants color array disabled
1177                 if (gl_state.pointer_color_enabled)
1178                 {
1179                         gl_state.pointer_color_enabled = false;
1180                         CHECKGLERROR
1181                         qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1182                         // when color array is on the glColor gets trashed, set it again
1183                         qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
1184                 }
1185         }
1186 }
1187
1188 void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord, int bufferobject, size_t bufferoffset)
1189 {
1190         gltextureunit_t *unit = gl_state.units + unitnum;
1191         // update array settings
1192         CHECKGLERROR
1193         // note: there is no need to check bufferobject here because all cases
1194         // that involve a valid bufferobject also supply a texcoord array
1195         if (texcoord)
1196         {
1197                 if (!gl_vbo.integer)
1198                         bufferobject = 0;
1199                 // texture array unit is enabled, enable the array
1200                 if (!unit->arrayenabled)
1201                 {
1202                         unit->arrayenabled = true;
1203                         GL_ClientActiveTexture(unitnum);
1204                         qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1205                 }
1206                 // texcoord array
1207                 if (unit->pointer_texcoord != texcoord || unit->pointer_texcoord_buffer != bufferobject || unit->pointer_texcoord_offset != bufferoffset || unit->arraycomponents != numcomponents)
1208                 {
1209                         unit->pointer_texcoord = texcoord;
1210                         unit->pointer_texcoord_buffer = bufferobject;
1211                         unit->pointer_texcoord_offset = bufferoffset;
1212                         unit->arraycomponents = numcomponents;
1213                         GL_ClientActiveTexture(unitnum);
1214                         GL_BindVBO(bufferobject);
1215                         qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, bufferobject ? (void *)bufferoffset : texcoord);CHECKGLERROR
1216                 }
1217         }
1218         else
1219         {
1220                 // texture array unit is disabled, disable the array
1221                 if (unit->arrayenabled)
1222                 {
1223                         unit->arrayenabled = false;
1224                         GL_ClientActiveTexture(unitnum);
1225                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1226                 }
1227         }
1228 }
1229
1230 void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap)
1231 {
1232         gltextureunit_t *unit = gl_state.units + unitnum;
1233         if (unitnum >= backendimageunits)
1234                 return;
1235         // update 1d texture binding
1236         if (unit->t1d != tex1d)
1237         {
1238                 GL_ActiveTexture(unitnum);
1239                 if (unitnum < backendunits)
1240                 {
1241                         if (tex1d)
1242                         {
1243                                 if (unit->t1d == 0)
1244                                 {
1245                                         qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1246                                 }
1247                         }
1248                         else
1249                         {
1250                                 if (unit->t1d)
1251                                 {
1252                                         qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1253                                 }
1254                         }
1255                 }
1256                 unit->t1d = tex1d;
1257                 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1258         }
1259         // update 2d texture binding
1260         if (unit->t2d != tex2d)
1261         {
1262                 GL_ActiveTexture(unitnum);
1263                 if (unitnum < backendunits)
1264                 {
1265                         if (tex2d)
1266                         {
1267                                 if (unit->t2d == 0)
1268                                 {
1269                                         qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1270                                 }
1271                         }
1272                         else
1273                         {
1274                                 if (unit->t2d)
1275                                 {
1276                                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1277                                 }
1278                         }
1279                 }
1280                 unit->t2d = tex2d;
1281                 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1282         }
1283         // update 3d texture binding
1284         if (unit->t3d != tex3d)
1285         {
1286                 GL_ActiveTexture(unitnum);
1287                 if (unitnum < backendunits)
1288                 {
1289                         if (tex3d)
1290                         {
1291                                 if (unit->t3d == 0)
1292                                 {
1293                                         qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1294                                 }
1295                         }
1296                         else
1297                         {
1298                                 if (unit->t3d)
1299                                 {
1300                                         qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1301                                 }
1302                         }
1303                 }
1304                 unit->t3d = tex3d;
1305                 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1306         }
1307         // update cubemap texture binding
1308         if (unit->tcubemap != texcubemap)
1309         {
1310                 GL_ActiveTexture(unitnum);
1311                 if (unitnum < backendunits)
1312                 {
1313                         if (texcubemap)
1314                         {
1315                                 if (unit->tcubemap == 0)
1316                                 {
1317                                         qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1318                                 }
1319                         }
1320                         else
1321                         {
1322                                 if (unit->tcubemap)
1323                                 {
1324                                         qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1325                                 }
1326                         }
1327                 }
1328                 unit->tcubemap = texcubemap;
1329                 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1330         }
1331 }
1332
1333 void R_Mesh_TexBind1D(unsigned int unitnum, int texnum)
1334 {
1335         gltextureunit_t *unit = gl_state.units + unitnum;
1336         if (unitnum >= backendimageunits)
1337                 return;
1338         // update 1d texture binding
1339         if (unit->t1d != texnum)
1340         {
1341                 GL_ActiveTexture(unitnum);
1342                 if (unitnum < backendunits)
1343                 {
1344                         if (texnum)
1345                         {
1346                                 if (unit->t1d == 0)
1347                                 {
1348                                         qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1349                                 }
1350                         }
1351                         else
1352                         {
1353                                 if (unit->t1d)
1354                                 {
1355                                         qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1356                                 }
1357                         }
1358                 }
1359                 unit->t1d = texnum;
1360                 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1361         }
1362         // update 2d texture binding
1363         if (unit->t2d)
1364         {
1365                 GL_ActiveTexture(unitnum);
1366                 if (unitnum < backendunits)
1367                 {
1368                         if (unit->t2d)
1369                         {
1370                                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1371                         }
1372                 }
1373                 unit->t2d = 0;
1374                 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1375         }
1376         // update 3d texture binding
1377         if (unit->t3d)
1378         {
1379                 GL_ActiveTexture(unitnum);
1380                 if (unitnum < backendunits)
1381                 {
1382                         if (unit->t3d)
1383                         {
1384                                 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1385                         }
1386                 }
1387                 unit->t3d = 0;
1388                 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1389         }
1390         // update cubemap texture binding
1391         if (unit->tcubemap)
1392         {
1393                 GL_ActiveTexture(unitnum);
1394                 if (unitnum < backendunits)
1395                 {
1396                         if (unit->tcubemap)
1397                         {
1398                                 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1399                         }
1400                 }
1401                 unit->tcubemap = 0;
1402                 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1403         }
1404 }
1405
1406 void R_Mesh_TexBind(unsigned int unitnum, int texnum)
1407 {
1408         gltextureunit_t *unit = gl_state.units + unitnum;
1409         if (unitnum >= backendimageunits)
1410                 return;
1411         // update 1d texture binding
1412         if (unit->t1d)
1413         {
1414                 GL_ActiveTexture(unitnum);
1415                 if (unitnum < backendunits)
1416                 {
1417                         if (unit->t1d)
1418                         {
1419                                 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1420                         }
1421                 }
1422                 unit->t1d = 0;
1423                 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1424         }
1425         // update 2d texture binding
1426         if (unit->t2d != texnum)
1427         {
1428                 GL_ActiveTexture(unitnum);
1429                 if (unitnum < backendunits)
1430                 {
1431                         if (texnum)
1432                         {
1433                                 if (unit->t2d == 0)
1434                                 {
1435                                         qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1436                                 }
1437                         }
1438                         else
1439                         {
1440                                 if (unit->t2d)
1441                                 {
1442                                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1443                                 }
1444                         }
1445                 }
1446                 unit->t2d = texnum;
1447                 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1448         }
1449         // update 3d texture binding
1450         if (unit->t3d)
1451         {
1452                 GL_ActiveTexture(unitnum);
1453                 if (unitnum < backendunits)
1454                 {
1455                         if (unit->t3d)
1456                         {
1457                                 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1458                         }
1459                 }
1460                 unit->t3d = 0;
1461                 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1462         }
1463         // update cubemap texture binding
1464         if (unit->tcubemap != 0)
1465         {
1466                 GL_ActiveTexture(unitnum);
1467                 if (unitnum < backendunits)
1468                 {
1469                         if (unit->tcubemap)
1470                         {
1471                                 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1472                         }
1473                 }
1474                 unit->tcubemap = 0;
1475                 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1476         }
1477 }
1478
1479 void R_Mesh_TexBind3D(unsigned int unitnum, int texnum)
1480 {
1481         gltextureunit_t *unit = gl_state.units + unitnum;
1482         if (unitnum >= backendimageunits)
1483                 return;
1484         // update 1d texture binding
1485         if (unit->t1d)
1486         {
1487                 GL_ActiveTexture(unitnum);
1488                 if (unitnum < backendunits)
1489                 {
1490                         if (unit->t1d)
1491                         {
1492                                 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1493                         }
1494                 }
1495                 unit->t1d = 0;
1496                 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1497         }
1498         // update 2d texture binding
1499         if (unit->t2d)
1500         {
1501                 GL_ActiveTexture(unitnum);
1502                 if (unitnum < backendunits)
1503                 {
1504                         if (unit->t2d)
1505                         {
1506                                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1507                         }
1508                 }
1509                 unit->t2d = 0;
1510                 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1511         }
1512         // update 3d texture binding
1513         if (unit->t3d != texnum)
1514         {
1515                 GL_ActiveTexture(unitnum);
1516                 if (unitnum < backendunits)
1517                 {
1518                         if (texnum)
1519                         {
1520                                 if (unit->t3d == 0)
1521                                 {
1522                                         qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1523                                 }
1524                         }
1525                         else
1526                         {
1527                                 if (unit->t3d)
1528                                 {
1529                                         qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1530                                 }
1531                         }
1532                 }
1533                 unit->t3d = texnum;
1534                 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1535         }
1536         // update cubemap texture binding
1537         if (unit->tcubemap != 0)
1538         {
1539                 GL_ActiveTexture(unitnum);
1540                 if (unitnum < backendunits)
1541                 {
1542                         if (unit->tcubemap)
1543                         {
1544                                 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1545                         }
1546                 }
1547                 unit->tcubemap = 0;
1548                 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1549         }
1550 }
1551
1552 void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum)
1553 {
1554         gltextureunit_t *unit = gl_state.units + unitnum;
1555         if (unitnum >= backendimageunits)
1556                 return;
1557         // update 1d texture binding
1558         if (unit->t1d)
1559         {
1560                 GL_ActiveTexture(unitnum);
1561                 if (unitnum < backendunits)
1562                 {
1563                         if (unit->t1d)
1564                         {
1565                                 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1566                         }
1567                 }
1568                 unit->t1d = 0;
1569                 qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1570         }
1571         // update 2d texture binding
1572         if (unit->t2d)
1573         {
1574                 GL_ActiveTexture(unitnum);
1575                 if (unitnum < backendunits)
1576                 {
1577                         if (unit->t2d)
1578                         {
1579                                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1580                         }
1581                 }
1582                 unit->t2d = 0;
1583                 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1584         }
1585         // update 3d texture binding
1586         if (unit->t3d)
1587         {
1588                 GL_ActiveTexture(unitnum);
1589                 if (unitnum < backendunits)
1590                 {
1591                         if (unit->t3d)
1592                         {
1593                                 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1594                         }
1595                 }
1596                 unit->t3d = 0;
1597                 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1598         }
1599         // update cubemap texture binding
1600         if (unit->tcubemap != texnum)
1601         {
1602                 GL_ActiveTexture(unitnum);
1603                 if (unitnum < backendunits)
1604                 {
1605                         if (texnum)
1606                         {
1607                                 if (unit->tcubemap == 0)
1608                                 {
1609                                         qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1610                                 }
1611                         }
1612                         else
1613                         {
1614                                 if (unit->tcubemap)
1615                                 {
1616                                         qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1617                                 }
1618                         }
1619                 }
1620                 unit->tcubemap = texnum;
1621                 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1622         }
1623 }
1624
1625 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
1626 {
1627         gltextureunit_t *unit = gl_state.units + unitnum;
1628         if (matrix->m[3][3])
1629         {
1630                 // texmatrix specified, check if it is different
1631                 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
1632                 {
1633                         double glmatrix[16];
1634                         unit->texmatrixenabled = true;
1635                         unit->matrix = *matrix;
1636                         CHECKGLERROR
1637                         Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix);
1638                         qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1639                         GL_ActiveTexture(unitnum);
1640                         qglLoadMatrixd(glmatrix);CHECKGLERROR
1641                         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1642                 }
1643         }
1644         else
1645         {
1646                 // no texmatrix specified, revert to identity
1647                 if (unit->texmatrixenabled)
1648                 {
1649                         unit->texmatrixenabled = false;
1650                         CHECKGLERROR
1651                         qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1652                         GL_ActiveTexture(unitnum);
1653                         qglLoadIdentity();CHECKGLERROR
1654                         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1655                 }
1656         }
1657 }
1658
1659 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
1660 {
1661         gltextureunit_t *unit = gl_state.units + unitnum;
1662         CHECKGLERROR
1663         if (gl_combine.integer)
1664         {
1665                 // GL_ARB_texture_env_combine
1666                 if (!combinergb)
1667                         combinergb = GL_MODULATE;
1668                 if (!combinealpha)
1669                         combinealpha = GL_MODULATE;
1670                 if (!rgbscale)
1671                         rgbscale = 1;
1672                 if (!alphascale)
1673                         alphascale = 1;
1674                 if (unit->combinergb != combinergb)
1675                 {
1676                         unit->combinergb = combinergb;
1677                         GL_ActiveTexture(unitnum);
1678                         qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1679                 }
1680                 if (unit->combinealpha != combinealpha)
1681                 {
1682                         unit->combinealpha = combinealpha;
1683                         GL_ActiveTexture(unitnum);
1684                         qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1685                 }
1686                 if (unit->rgbscale != rgbscale)
1687                 {
1688                         GL_ActiveTexture(unitnum);
1689                         qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = rgbscale));CHECKGLERROR
1690                 }
1691                 if (unit->alphascale != alphascale)
1692                 {
1693                         GL_ActiveTexture(unitnum);
1694                         qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = alphascale));CHECKGLERROR
1695                 }
1696         }
1697         else
1698         {
1699                 // normal GL texenv
1700                 if (!combinergb)
1701                         combinergb = GL_MODULATE;
1702                 if (unit->combinergb != combinergb)
1703                 {
1704                         unit->combinergb = combinergb;
1705                         GL_ActiveTexture(unitnum);
1706                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1707                 }
1708         }
1709 }
1710
1711 void R_Mesh_TextureState(const rmeshstate_t *m)
1712 {
1713         unsigned int i;
1714
1715         BACKENDACTIVECHECK
1716
1717         CHECKGLERROR
1718         if (gl_backend_rebindtextures)
1719         {
1720                 gl_backend_rebindtextures = false;
1721                 GL_SetupTextureState();
1722                 CHECKGLERROR
1723         }
1724
1725         for (i = 0;i < backendimageunits;i++)
1726                 R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]);
1727         for (i = 0;i < backendarrayunits;i++)
1728         {
1729                 if (m->pointer_texcoord3f[i])
1730                         R_Mesh_TexCoordPointer(i, 3, m->pointer_texcoord3f[i], m->pointer_texcoord_bufferobject[i], m->pointer_texcoord_bufferoffset[i]);
1731                 else
1732                         R_Mesh_TexCoordPointer(i, 2, m->pointer_texcoord[i], m->pointer_texcoord_bufferobject[i], m->pointer_texcoord_bufferoffset[i]);
1733         }
1734         for (i = 0;i < backendunits;i++)
1735         {
1736                 R_Mesh_TexMatrix(i, &m->texmatrix[i]);
1737                 R_Mesh_TexCombine(i, m->texcombinergb[i], m->texcombinealpha[i], m->texrgbscale[i], m->texalphascale[i]);
1738         }
1739         CHECKGLERROR
1740 }
1741
1742 void R_Mesh_ResetTextureState(void)
1743 {
1744         unsigned int unitnum;
1745
1746         BACKENDACTIVECHECK
1747
1748         CHECKGLERROR
1749         if (gl_backend_rebindtextures)
1750         {
1751                 gl_backend_rebindtextures = false;
1752                 GL_SetupTextureState();
1753                 CHECKGLERROR
1754         }
1755
1756         for (unitnum = 0;unitnum < backendimageunits;unitnum++)
1757         {
1758                 gltextureunit_t *unit = gl_state.units + unitnum;
1759                 // update 1d texture binding
1760                 if (unit->t1d)
1761                 {
1762                         GL_ActiveTexture(unitnum);
1763                         if (unitnum < backendunits)
1764                         {
1765                                 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1766                         }
1767                         unit->t1d = 0;
1768                         qglBindTexture(GL_TEXTURE_1D, unit->t1d);CHECKGLERROR
1769                 }
1770                 // update 2d texture binding
1771                 if (unit->t2d)
1772                 {
1773                         GL_ActiveTexture(unitnum);
1774                         if (unitnum < backendunits)
1775                         {
1776                                 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1777                         }
1778                         unit->t2d = 0;
1779                         qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1780                 }
1781                 // update 3d texture binding
1782                 if (unit->t3d)
1783                 {
1784                         GL_ActiveTexture(unitnum);
1785                         if (unitnum < backendunits)
1786                         {
1787                                 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1788                         }
1789                         unit->t3d = 0;
1790                         qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1791                 }
1792                 // update cubemap texture binding
1793                 if (unit->tcubemap)
1794                 {
1795                         GL_ActiveTexture(unitnum);
1796                         if (unitnum < backendunits)
1797                         {
1798                                 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1799                         }
1800                         unit->tcubemap = 0;
1801                         qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1802                 }
1803         }
1804         for (unitnum = 0;unitnum < backendarrayunits;unitnum++)
1805         {
1806                 gltextureunit_t *unit = gl_state.units + unitnum;
1807                 // texture array unit is disabled, disable the array
1808                 if (unit->arrayenabled)
1809                 {
1810                         unit->arrayenabled = false;
1811                         GL_ClientActiveTexture(unitnum);
1812                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1813                 }
1814         }
1815         for (unitnum = 0;unitnum < backendunits;unitnum++)
1816         {
1817                 gltextureunit_t *unit = gl_state.units + unitnum;
1818                 // no texmatrix specified, revert to identity
1819                 if (unit->texmatrixenabled)
1820                 {
1821                         unit->texmatrixenabled = false;
1822                         CHECKGLERROR
1823                         qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1824                         GL_ActiveTexture(unitnum);
1825                         qglLoadIdentity();CHECKGLERROR
1826                         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1827                 }
1828                 if (gl_combine.integer)
1829                 {
1830                         // GL_ARB_texture_env_combine
1831                         if (unit->combinergb != GL_MODULATE)
1832                         {
1833                                 unit->combinergb = GL_MODULATE;
1834                                 GL_ActiveTexture(unitnum);
1835                                 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1836                         }
1837                         if (unit->combinealpha != GL_MODULATE)
1838                         {
1839                                 unit->combinealpha = GL_MODULATE;
1840                                 GL_ActiveTexture(unitnum);
1841                                 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1842                         }
1843                         if (unit->rgbscale != 1)
1844                         {
1845                                 GL_ActiveTexture(unitnum);
1846                                 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = 1));CHECKGLERROR
1847                         }
1848                         if (unit->alphascale != 1)
1849                         {
1850                                 GL_ActiveTexture(unitnum);
1851                                 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = 1));CHECKGLERROR
1852                         }
1853                 }
1854                 else
1855                 {
1856                         // normal GL texenv
1857                         if (unit->combinergb != GL_MODULATE)
1858                         {
1859                                 unit->combinergb = GL_MODULATE;
1860                                 GL_ActiveTexture(unitnum);
1861                                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1862                         }
1863                 }
1864         }
1865 }
1866
1867 void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
1868 {
1869         CHECKGLERROR
1870         qglBegin(GL_LINES);
1871         for (;numtriangles;numtriangles--, elements += 3)
1872         {
1873                 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
1874                 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
1875                 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
1876         }
1877         qglEnd();
1878         CHECKGLERROR
1879 }