]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_backend.c
b99d654aad7a4e9a695993a646bf4c58f16108b6
[xonotic/darkplaces.git] / gl_backend.c
1
2 #include "quakedef.h"
3 #include "cl_collision.h"
4
5 #define MAX_RENDERTARGETS 4
6
7 cvar_t gl_debug = {0, "gl_debug", "0", "enables OpenGL debug output, 0 = off, 1 = HIGH severity only, 2 = also MEDIUM severity, 3 = also LOW severity messages.  (note: enabling may not take effect until vid_restart on some drivers)"};
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 3D views (you want this on!)"};
12 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
13 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
14 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
15
16 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
17 qboolean v_flipped_state = false;
18
19 r_viewport_t gl_viewport;
20 matrix4x4_t gl_modelmatrix;
21 matrix4x4_t gl_viewmatrix;
22 matrix4x4_t gl_modelviewmatrix;
23 matrix4x4_t gl_projectionmatrix;
24 matrix4x4_t gl_modelviewprojectionmatrix;
25 float gl_modelview16f[16];
26 float gl_modelviewprojection16f[16];
27 qboolean gl_modelmatrixchanged;
28
29 #ifdef DEBUGGL
30 int gl_errornumber = 0;
31
32 void GL_PrintError(int errornumber, const char *filename, int linenumber)
33 {
34         switch(errornumber)
35         {
36 #ifdef GL_INVALID_ENUM
37         case GL_INVALID_ENUM:
38                 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
39                 break;
40 #endif
41 #ifdef GL_INVALID_VALUE
42         case GL_INVALID_VALUE:
43                 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
44                 break;
45 #endif
46 #ifdef GL_INVALID_OPERATION
47         case GL_INVALID_OPERATION:
48                 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
49                 break;
50 #endif
51 #ifdef GL_STACK_OVERFLOW
52         case GL_STACK_OVERFLOW:
53                 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
54                 break;
55 #endif
56 #ifdef GL_STACK_UNDERFLOW
57         case GL_STACK_UNDERFLOW:
58                 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
59                 break;
60 #endif
61 #ifdef GL_OUT_OF_MEMORY
62         case GL_OUT_OF_MEMORY:
63                 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
64                 break;
65 #endif
66 #ifdef GL_TABLE_TOO_LARGE
67         case GL_TABLE_TOO_LARGE:
68                 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
69                 break;
70 #endif
71 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION
72         case GL_INVALID_FRAMEBUFFER_OPERATION:
73                 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
74                 break;
75 #endif
76         default:
77                 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
78                 break;
79         }
80 }
81
82 static void GLAPIENTRY GL_DebugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const GLvoid* userParam)
83 {
84         const char *sev = "ENUM?", *typ = "ENUM?", *src = "ENUM?";
85         switch (severity)
86         {
87         case GL_DEBUG_SEVERITY_LOW_ARB: sev = "LOW"; break;
88         case GL_DEBUG_SEVERITY_MEDIUM_ARB: sev = "MED"; break;
89         case GL_DEBUG_SEVERITY_HIGH_ARB: sev = "HIGH"; break;
90         }
91         switch (type)
92         {
93         case GL_DEBUG_TYPE_ERROR_ARB: typ = "ERROR"; break;
94         case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: typ = "DEPRECATED"; break;
95         case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: typ = "UNDEFINED"; break;
96         case GL_DEBUG_TYPE_PORTABILITY_ARB: typ = "PORTABILITY"; break;
97         case GL_DEBUG_TYPE_PERFORMANCE_ARB: typ = "PERFORMANCE"; break;
98         case GL_DEBUG_TYPE_OTHER_ARB: typ = "OTHER"; break;
99         }
100         switch (source)
101         {
102         case GL_DEBUG_SOURCE_API_ARB: src = "API"; break;
103         case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: src = "SHADER"; break;
104         case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: src = "WIN"; break;
105         case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: src = "THIRDPARTY"; break;
106         case GL_DEBUG_SOURCE_APPLICATION_ARB: src = "APP"; break;
107         case GL_DEBUG_SOURCE_OTHER_ARB: src = "OTHER"; break;
108         }
109         Con_Printf("GLDEBUG: %s %s %s: %u: %s\n", sev, typ, src, (unsigned int)id, message);
110 }
111 #endif
112
113 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
114
115 void SCR_ScreenShot_f (void);
116
117 typedef struct gltextureunit_s
118 {
119         int pointer_texcoord_components;
120         int pointer_texcoord_gltype;
121         size_t pointer_texcoord_stride;
122         const void *pointer_texcoord_pointer;
123         const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
124         size_t pointer_texcoord_offset;
125
126         rtexture_t *texture;
127         int t2d, t3d, tcubemap;
128         int arrayenabled;
129 }
130 gltextureunit_t;
131
132 typedef struct gl_state_s
133 {
134         int cullface;
135         int cullfaceenable;
136         int blendfunc1;
137         int blendfunc2;
138         qboolean blend;
139         GLboolean depthmask;
140         int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
141         int depthtest;
142         int depthfunc;
143         float depthrange[2];
144         float polygonoffset[2];
145         qboolean alphatocoverage;
146         int scissortest;
147         unsigned int unit;
148         gltextureunit_t units[MAX_TEXTUREUNITS];
149         float color4f[4];
150         int lockrange_first;
151         int lockrange_count;
152         int vertexbufferobject;
153         int elementbufferobject;
154         int uniformbufferobject;
155         int framebufferobject;
156         int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
157         qboolean pointer_color_enabled;
158
159         int pointer_vertex_components;
160         int pointer_vertex_gltype;
161         size_t pointer_vertex_stride;
162         const void *pointer_vertex_pointer;
163         const r_meshbuffer_t *pointer_vertex_vertexbuffer;
164         size_t pointer_vertex_offset;
165
166         int pointer_color_components;
167         int pointer_color_gltype;
168         size_t pointer_color_stride;
169         const void *pointer_color_pointer;
170         const r_meshbuffer_t *pointer_color_vertexbuffer;
171         size_t pointer_color_offset;
172
173         void *preparevertices_tempdata;
174         size_t preparevertices_tempdatamaxsize;
175         int preparevertices_numvertices;
176
177         memexpandablearray_t meshbufferarray;
178
179         qboolean active;
180 }
181 gl_state_t;
182
183 static gl_state_t gl_state;
184
185
186 /*
187 note: here's strip order for a terrain row:
188 0--1--2--3--4
189 |\ |\ |\ |\ |
190 | \| \| \| \|
191 A--B--C--D--E
192 clockwise
193
194 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
195
196 *elements++ = i + row;
197 *elements++ = i;
198 *elements++ = i + row + 1;
199 *elements++ = i;
200 *elements++ = i + 1;
201 *elements++ = i + row + 1;
202
203
204 for (y = 0;y < rows - 1;y++)
205 {
206         for (x = 0;x < columns - 1;x++)
207         {
208                 i = y * rows + x;
209                 *elements++ = i + columns;
210                 *elements++ = i;
211                 *elements++ = i + columns + 1;
212                 *elements++ = i;
213                 *elements++ = i + 1;
214                 *elements++ = i + columns + 1;
215         }
216 }
217
218 alternative:
219 0--1--2--3--4
220 | /| /|\ | /|
221 |/ |/ | \|/ |
222 A--B--C--D--E
223 counterclockwise
224
225 for (y = 0;y < rows - 1;y++)
226 {
227         for (x = 0;x < columns - 1;x++)
228         {
229                 i = y * rows + x;
230                 *elements++ = i;
231                 *elements++ = i + columns;
232                 *elements++ = i + columns + 1;
233                 *elements++ = i + columns;
234                 *elements++ = i + columns + 1;
235                 *elements++ = i + 1;
236         }
237 }
238 */
239
240 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
241 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
242 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
243 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
244
245 static void GL_VBOStats_f(void)
246 {
247         GL_Mesh_ListVBOs(true);
248 }
249
250 static void GL_Backend_ResetState(void);
251
252 static void gl_backend_start(void)
253 {
254         memset(&gl_state, 0, sizeof(gl_state));
255
256         Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
257
258         Con_DPrintf("OpenGL backend started.\n");
259
260         CHECKGLERROR
261
262         GL_Backend_ResetState();
263
264         switch(vid.renderpath)
265         {
266         case RENDERPATH_GL32:
267         case RENDERPATH_GLES2:
268                 // fetch current fbo here (default fbo is not 0 on some GLES devices)
269                 CHECKGLERROR
270                 qglGetIntegerv(GL_FRAMEBUFFER_BINDING, &gl_state.defaultframebufferobject);CHECKGLERROR
271                 break;
272         }
273 }
274
275 static void gl_backend_shutdown(void)
276 {
277         Con_DPrint("OpenGL Backend shutting down\n");
278
279         switch(vid.renderpath)
280         {
281         case RENDERPATH_GL32:
282         case RENDERPATH_GLES2:
283                 break;
284         }
285
286         if (gl_state.preparevertices_tempdata)
287                 Mem_Free(gl_state.preparevertices_tempdata);
288
289         Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
290
291         memset(&gl_state, 0, sizeof(gl_state));
292 }
293
294 static void gl_backend_newmap(void)
295 {
296 }
297
298 static void gl_backend_devicelost(void)
299 {
300         int i, endindex;
301         r_meshbuffer_t *buffer;
302         switch(vid.renderpath)
303         {
304         case RENDERPATH_GL32:
305         case RENDERPATH_GLES2:
306                 break;
307         }
308         endindex = (int)Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
309         for (i = 0;i < endindex;i++)
310         {
311                 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
312                 if (!buffer || !buffer->isdynamic)
313                         continue;
314                 switch(vid.renderpath)
315                 {
316                 case RENDERPATH_GL32:
317                 case RENDERPATH_GLES2:
318                         break;
319                 }
320         }
321 }
322
323 static void gl_backend_devicerestored(void)
324 {
325         switch(vid.renderpath)
326         {
327         case RENDERPATH_GL32:
328         case RENDERPATH_GLES2:
329                 break;
330         }
331 }
332
333 void gl_backend_init(void)
334 {
335         int i;
336
337         for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
338         {
339                 polygonelement3s[i * 3 + 0] = 0;
340                 polygonelement3s[i * 3 + 1] = i + 1;
341                 polygonelement3s[i * 3 + 2] = i + 2;
342         }
343         // elements for rendering a series of quads as triangles
344         for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
345         {
346                 quadelement3s[i * 6 + 0] = i * 4;
347                 quadelement3s[i * 6 + 1] = i * 4 + 1;
348                 quadelement3s[i * 6 + 2] = i * 4 + 2;
349                 quadelement3s[i * 6 + 3] = i * 4;
350                 quadelement3s[i * 6 + 4] = i * 4 + 2;
351                 quadelement3s[i * 6 + 5] = i * 4 + 3;
352         }
353
354         for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
355                 polygonelement3i[i] = polygonelement3s[i];
356         for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
357                 quadelement3i[i] = quadelement3s[i];
358
359         Cvar_RegisterVariable(&r_render);
360         Cvar_RegisterVariable(&r_renderview);
361         Cvar_RegisterVariable(&r_waterwarp);
362         Cvar_RegisterVariable(&gl_polyblend);
363         Cvar_RegisterVariable(&v_flipped);
364         Cvar_RegisterVariable(&gl_debug);
365         Cvar_RegisterVariable(&gl_paranoid);
366         Cvar_RegisterVariable(&gl_printcheckerror);
367
368         Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
369
370         R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
371 }
372
373 void GL_SetMirrorState(qboolean state);
374
375 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
376 {
377         vec4_t temp;
378         float iw;
379         Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
380         Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
381         iw = 1.0f / out[3];
382         out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
383
384         // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
385         //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
386         out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
387
388         out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
389 }
390
391 void GL_Finish(void)
392 {
393         switch(vid.renderpath)
394         {
395         case RENDERPATH_GL32:
396         case RENDERPATH_GLES2:
397                 CHECKGLERROR
398                 qglFinish();CHECKGLERROR
399                 break;
400         }
401 }
402
403 static int bboxedges[12][2] =
404 {
405         // top
406         {0, 1}, // +X
407         {0, 2}, // +Y
408         {1, 3}, // Y, +X
409         {2, 3}, // X, +Y
410         // bottom
411         {4, 5}, // +X
412         {4, 6}, // +Y
413         {5, 7}, // Y, +X
414         {6, 7}, // X, +Y
415         // verticals
416         {0, 4}, // +Z
417         {1, 5}, // X, +Z
418         {2, 6}, // Y, +Z
419         {3, 7}, // XY, +Z
420 };
421
422 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
423 {
424         int i, ix1, iy1, ix2, iy2;
425         float x1, y1, x2, y2;
426         vec4_t v, v2;
427         float vertex[20][3];
428         int j, k;
429         vec4_t plane4f;
430         int numvertices;
431         float corner[8][4];
432         float dist[8];
433         int sign[8];
434         float f;
435
436         scissor[0] = r_refdef.view.viewport.x;
437         scissor[1] = r_refdef.view.viewport.y;
438         scissor[2] = r_refdef.view.viewport.width;
439         scissor[3] = r_refdef.view.viewport.height;
440
441         // if view is inside the box, just say yes it's visible
442         if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
443                 return false;
444
445         // transform all corners that are infront of the nearclip plane
446         VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
447         plane4f[3] = r_refdef.view.frustum[4].dist;
448         numvertices = 0;
449         for (i = 0;i < 8;i++)
450         {
451                 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
452                 dist[i] = DotProduct4(corner[i], plane4f);
453                 sign[i] = dist[i] > 0;
454                 if (!sign[i])
455                 {
456                         VectorCopy(corner[i], vertex[numvertices]);
457                         numvertices++;
458                 }
459         }
460         // if some points are behind the nearclip, add clipped edge points to make
461         // sure that the scissor boundary is complete
462         if (numvertices > 0 && numvertices < 8)
463         {
464                 // add clipped edge points
465                 for (i = 0;i < 12;i++)
466                 {
467                         j = bboxedges[i][0];
468                         k = bboxedges[i][1];
469                         if (sign[j] != sign[k])
470                         {
471                                 f = dist[j] / (dist[j] - dist[k]);
472                                 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
473                                 numvertices++;
474                         }
475                 }
476         }
477
478         // if we have no points to check, it is behind the view plane
479         if (!numvertices)
480                 return true;
481
482         // if we have some points to transform, check what screen area is covered
483         x1 = y1 = x2 = y2 = 0;
484         v[3] = 1.0f;
485         //Con_Printf("%i vertices to transform...\n", numvertices);
486         for (i = 0;i < numvertices;i++)
487         {
488                 VectorCopy(vertex[i], v);
489                 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
490                 //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
491                 if (i)
492                 {
493                         if (x1 > v2[0]) x1 = v2[0];
494                         if (x2 < v2[0]) x2 = v2[0];
495                         if (y1 > v2[1]) y1 = v2[1];
496                         if (y2 < v2[1]) y2 = v2[1];
497                 }
498                 else
499                 {
500                         x1 = x2 = v2[0];
501                         y1 = y2 = v2[1];
502                 }
503         }
504
505         // now convert the scissor rectangle to integer screen coordinates
506         ix1 = (int)(x1 - 1.0f);
507         //iy1 = vid.height - (int)(y2 - 1.0f);
508         //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
509         iy1 = (int)(y1 - 1.0f);
510         ix2 = (int)(x2 + 1.0f);
511         //iy2 = vid.height - (int)(y1 + 1.0f);
512         //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
513         iy2 = (int)(y2 + 1.0f);
514         //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
515
516         // clamp it to the screen
517         if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
518         if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
519         if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
520         if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
521
522         // if it is inside out, it's not visible
523         if (ix2 <= ix1 || iy2 <= iy1)
524                 return true;
525
526         // the light area is visible, set up the scissor rectangle
527         scissor[0] = ix1;
528         scissor[1] = iy1;
529         scissor[2] = ix2 - ix1;
530         scissor[3] = iy2 - iy1;
531
532         // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
533         switch(vid.renderpath)
534         {
535         case RENDERPATH_GL32:
536         case RENDERPATH_GLES2:
537                 break;
538         }
539
540         return false;
541 }
542
543
544 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
545 {
546         float q[4];
547         float d;
548         float clipPlane[4], v3[3], v4[3];
549         float normal[3];
550
551         // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
552
553         VectorSet(normal, normalx, normaly, normalz);
554         Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
555         VectorScale(normal, -dist, v3);
556         Matrix4x4_Transform(&v->viewmatrix, v3, v4);
557         // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
558         clipPlane[3] = -DotProduct(v4, clipPlane);
559
560         // Calculate the clip-space corner point opposite the clipping plane
561         // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
562         // transform it into camera space by multiplying it
563         // by the inverse of the projection matrix
564         q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
565         q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
566         q[2] = -1.0f;
567         q[3] = (1.0f + m[10]) / m[14];
568
569         // Calculate the scaled plane vector
570         d = 2.0f / DotProduct4(clipPlane, q);
571
572         // Replace the third row of the projection matrix
573         m[2] = clipPlane[0] * d;
574         m[6] = clipPlane[1] * d;
575         m[10] = clipPlane[2] * d + 1.0f;
576         m[14] = clipPlane[3] * d;
577 }
578
579 void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float x1, float y1, float x2, float y2, float nearclip, float farclip, const float *nearplane)
580 {
581         float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
582         float m[16];
583         memset(v, 0, sizeof(*v));
584         v->type = R_VIEWPORTTYPE_ORTHO;
585         v->cameramatrix = *cameramatrix;
586         v->x = x;
587         v->y = y;
588         v->z = 0;
589         v->width = width;
590         v->height = height;
591         v->depth = 1;
592         memset(m, 0, sizeof(m));
593         m[0]  = 2/(right - left);
594         m[5]  = 2/(top - bottom);
595         m[10] = -2/(zFar - zNear);
596         m[12] = - (right + left)/(right - left);
597         m[13] = - (top + bottom)/(top - bottom);
598         m[14] = - (zFar + zNear)/(zFar - zNear);
599         m[15] = 1;
600         switch(vid.renderpath)
601         {
602         case RENDERPATH_GL32:
603         case RENDERPATH_GLES2:
604                 break;
605         }
606         v->screentodepth[0] = -farclip / (farclip - nearclip);
607         v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
608
609         Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
610
611         if (nearplane)
612                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
613
614         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
615
616 #if 0
617         {
618                 vec4_t test1;
619                 vec4_t test2;
620                 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
621                 R_Viewport_TransformToScreen(v, test1, test2);
622                 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
623         }
624 #endif
625 }
626
627 void R_Viewport_InitOrtho3D(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane)
628 {
629         matrix4x4_t tempmatrix, basematrix;
630         float m[16];
631         memset(v, 0, sizeof(*v));
632
633         v->type = R_VIEWPORTTYPE_PERSPECTIVE;
634         v->cameramatrix = *cameramatrix;
635         v->x = x;
636         v->y = y;
637         v->z = 0;
638         v->width = width;
639         v->height = height;
640         v->depth = 1;
641         memset(m, 0, sizeof(m));
642         m[0]  = 1.0 / frustumx;
643         m[5]  = 1.0 / frustumy;
644         m[10] = -2 / (farclip - nearclip);
645         m[14] = -(farclip + nearclip) / (farclip - nearclip);
646         m[15] = 1;
647         v->screentodepth[0] = -farclip / (farclip - nearclip);
648         v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
649
650         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
651         Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
652         Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
653         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
654
655         if (nearplane)
656                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
657
658         if(v_flipped.integer)
659         {
660                 m[0] = -m[0];
661                 m[4] = -m[4];
662                 m[8] = -m[8];
663                 m[12] = -m[12];
664         }
665
666         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
667 }
668
669 void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane)
670 {
671         matrix4x4_t tempmatrix, basematrix;
672         float m[16];
673         memset(v, 0, sizeof(*v));
674
675         v->type = R_VIEWPORTTYPE_PERSPECTIVE;
676         v->cameramatrix = *cameramatrix;
677         v->x = x;
678         v->y = y;
679         v->z = 0;
680         v->width = width;
681         v->height = height;
682         v->depth = 1;
683         memset(m, 0, sizeof(m));
684         m[0]  = 1.0 / frustumx;
685         m[5]  = 1.0 / frustumy;
686         m[10] = -(farclip + nearclip) / (farclip - nearclip);
687         m[11] = -1;
688         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
689         v->screentodepth[0] = -farclip / (farclip - nearclip);
690         v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
691
692         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
693         Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
694         Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
695         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
696
697         if (nearplane)
698                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
699
700         if(v_flipped.integer)
701         {
702                 m[0] = -m[0];
703                 m[4] = -m[4];
704                 m[8] = -m[8];
705                 m[12] = -m[12];
706         }
707
708         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
709 }
710
711 void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, const float *nearplane)
712 {
713         matrix4x4_t tempmatrix, basematrix;
714         const float nudge = 1.0 - 1.0 / (1<<23);
715         float m[16];
716         memset(v, 0, sizeof(*v));
717
718         v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
719         v->cameramatrix = *cameramatrix;
720         v->x = x;
721         v->y = y;
722         v->z = 0;
723         v->width = width;
724         v->height = height;
725         v->depth = 1;
726         memset(m, 0, sizeof(m));
727         m[ 0] = 1.0 / frustumx;
728         m[ 5] = 1.0 / frustumy;
729         m[10] = -nudge;
730         m[11] = -1;
731         m[14] = -2 * nearclip * nudge;
732         v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
733         v->screentodepth[1] = m[14] * -0.5;
734
735         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
736         Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
737         Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
738         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
739
740         if (nearplane)
741                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
742
743         if(v_flipped.integer)
744         {
745                 m[0] = -m[0];
746                 m[4] = -m[4];
747                 m[8] = -m[8];
748                 m[12] = -m[12];
749         }
750
751         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
752 }
753
754 float cubeviewmatrix[6][16] =
755 {
756     // standard cubemap projections
757     { // +X
758          0, 0,-1, 0,
759          0,-1, 0, 0,
760         -1, 0, 0, 0,
761          0, 0, 0, 1,
762     },
763     { // -X
764          0, 0, 1, 0,
765          0,-1, 0, 0,
766          1, 0, 0, 0,
767          0, 0, 0, 1,
768     },
769     { // +Y
770          1, 0, 0, 0,
771          0, 0,-1, 0,
772          0, 1, 0, 0,
773          0, 0, 0, 1,
774     },
775     { // -Y
776          1, 0, 0, 0,
777          0, 0, 1, 0,
778          0,-1, 0, 0,
779          0, 0, 0, 1,
780     },
781     { // +Z
782          1, 0, 0, 0,
783          0,-1, 0, 0,
784          0, 0,-1, 0,
785          0, 0, 0, 1,
786     },
787     { // -Z
788         -1, 0, 0, 0,
789          0,-1, 0, 0,
790          0, 0, 1, 0,
791          0, 0, 0, 1,
792     },
793 };
794 float rectviewmatrix[6][16] =
795 {
796     // sign-preserving cubemap projections
797     { // +X
798          0, 0,-1, 0,
799          0, 1, 0, 0,
800          1, 0, 0, 0,
801          0, 0, 0, 1,
802     },
803     { // -X
804          0, 0, 1, 0,
805          0, 1, 0, 0,
806          1, 0, 0, 0,
807          0, 0, 0, 1,
808     },
809     { // +Y
810          1, 0, 0, 0,
811          0, 0,-1, 0,
812          0, 1, 0, 0,
813          0, 0, 0, 1,
814     },
815     { // -Y
816          1, 0, 0, 0,
817          0, 0, 1, 0,
818          0, 1, 0, 0,
819          0, 0, 0, 1,
820     },
821     { // +Z
822          1, 0, 0, 0,
823          0, 1, 0, 0,
824          0, 0,-1, 0,
825          0, 0, 0, 1,
826     },
827     { // -Z
828          1, 0, 0, 0,
829          0, 1, 0, 0,
830          0, 0, 1, 0,
831          0, 0, 0, 1,
832     },
833 };
834
835 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
836 {
837         matrix4x4_t tempmatrix, basematrix;
838         float m[16];
839         memset(v, 0, sizeof(*v));
840         v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
841         v->cameramatrix = *cameramatrix;
842         v->width = size;
843         v->height = size;
844         v->depth = 1;
845         memset(m, 0, sizeof(m));
846         m[0] = m[5] = 1.0f;
847         m[10] = -(farclip + nearclip) / (farclip - nearclip);
848         m[11] = -1;
849         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
850
851         Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
852         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
853         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
854
855         if (nearplane)
856                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
857
858         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
859 }
860
861 void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane, int offsetx, int offsety)
862 {
863         matrix4x4_t tempmatrix, basematrix;
864         float m[16];
865         memset(v, 0, sizeof(*v));
866         v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
867         v->cameramatrix = *cameramatrix;
868         v->x = offsetx + (side & 1) * size;
869         v->y = offsety + (side >> 1) * size;
870         v->width = size;
871         v->height = size;
872         v->depth = 1;
873         memset(m, 0, sizeof(m));
874         m[0] = m[5] = 1.0f * ((float)size - border) / size;
875         m[10] = -(farclip + nearclip) / (farclip - nearclip);
876         m[11] = -1;
877         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
878
879         Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
880         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
881         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
882
883         if (nearplane)
884                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
885
886         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
887 }
888
889 void R_SetViewport(const r_viewport_t *v)
890 {
891         gl_viewport = *v;
892
893         // FIXME: v_flipped_state is evil, this probably breaks somewhere
894         GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
895
896         // copy over the matrices to our state
897         gl_viewmatrix = v->viewmatrix;
898         gl_projectionmatrix = v->projectmatrix;
899
900         switch(vid.renderpath)
901         {
902         case RENDERPATH_GL32:
903         case RENDERPATH_GLES2:
904                 CHECKGLERROR
905                 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
906                 break;
907         }
908
909         // force an update of the derived matrices
910         gl_modelmatrixchanged = true;
911         R_EntityMatrix(&gl_modelmatrix);
912 }
913
914 void R_GetViewport(r_viewport_t *v)
915 {
916         *v = gl_viewport;
917 }
918
919 static void GL_BindVBO(int bufferobject)
920 {
921         if (gl_state.vertexbufferobject != bufferobject)
922         {
923                 gl_state.vertexbufferobject = bufferobject;
924                 CHECKGLERROR
925                 qglBindBuffer(GL_ARRAY_BUFFER, bufferobject);CHECKGLERROR
926         }
927 }
928
929 static void GL_BindEBO(int bufferobject)
930 {
931         if (gl_state.elementbufferobject != bufferobject)
932         {
933                 gl_state.elementbufferobject = bufferobject;
934                 CHECKGLERROR
935                 qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferobject);CHECKGLERROR
936         }
937 }
938
939 static void GL_BindUBO(int bufferobject)
940 {
941         if (gl_state.uniformbufferobject != bufferobject)
942         {
943                 gl_state.uniformbufferobject = bufferobject;
944 #ifdef GL_UNIFORM_BUFFER
945                 CHECKGLERROR
946                 qglBindBuffer(GL_UNIFORM_BUFFER, bufferobject);CHECKGLERROR
947 #endif
948         }
949 }
950
951 static const GLuint drawbuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
952 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
953 {
954         int temp;
955         GLuint status;
956         switch(vid.renderpath)
957         {
958         case RENDERPATH_GL32:
959         case RENDERPATH_GLES2:
960                 CHECKGLERROR
961                 qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
962                 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
963                 // GL_ARB_framebuffer_object (GL3-class hardware) - depth stencil attachment
964 #ifdef USE_GLES2
965                 // FIXME: separate stencil attachment on GLES
966                 if (depthtexture  && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT  , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
967                 if (depthtexture  && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT  , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
968 #else
969                 if (depthtexture  && depthtexture->texnum )
970                 {
971                         qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT  , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
972                         if (depthtexture->glisdepthstencil) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT  , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
973                 }
974                 if (depthtexture  && depthtexture->renderbuffernum )
975                 {
976                         qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT  , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
977                         if (depthtexture->glisdepthstencil) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT  , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
978                 }
979 #endif
980                 if (colortexture  && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
981                 if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
982                 if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR
983                 if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR
984                 if (colortexture  && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR
985                 if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR
986                 if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
987                 if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
988
989 #ifndef USE_GLES2
990                 if (colortexture4)
991                 {
992                         qglDrawBuffers(4, drawbuffers);CHECKGLERROR
993                         qglReadBuffer(GL_NONE);CHECKGLERROR
994                 }
995                 else if (colortexture3)
996                 {
997                         qglDrawBuffers(3, drawbuffers);CHECKGLERROR
998                         qglReadBuffer(GL_NONE);CHECKGLERROR
999                 }
1000                 else if (colortexture2)
1001                 {
1002                         qglDrawBuffers(2, drawbuffers);CHECKGLERROR
1003                         qglReadBuffer(GL_NONE);CHECKGLERROR
1004                 }
1005                 else if (colortexture)
1006                 {
1007                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1008                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1009                 }
1010                 else
1011                 {
1012                         qglDrawBuffer(GL_NONE);CHECKGLERROR
1013                         qglReadBuffer(GL_NONE);CHECKGLERROR
1014                 }
1015 #endif
1016                 status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
1017                 if (status != GL_FRAMEBUFFER_COMPLETE)
1018                 {
1019                         Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
1020                         gl_state.framebufferobject = 0; // GL unbinds it for us
1021                         qglDeleteFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
1022                         temp = 0;
1023                 }
1024                 return temp;
1025         }
1026         return 0;
1027 }
1028
1029 void R_Mesh_DestroyFramebufferObject(int fbo)
1030 {
1031         switch(vid.renderpath)
1032         {
1033         case RENDERPATH_GL32:
1034         case RENDERPATH_GLES2:
1035                 if (fbo)
1036                 {
1037                         // GL clears the binding if we delete something bound
1038                         if (gl_state.framebufferobject == fbo)
1039                                 gl_state.framebufferobject = 0;
1040                         qglDeleteFramebuffers(1, (GLuint*)&fbo);CHECKGLERROR
1041                 }
1042                 break;
1043         }
1044 }
1045
1046 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1047 {
1048         unsigned int i;
1049         unsigned int j;
1050         rtexture_t *textures[5];
1051         Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1052         textures[4] = depthtexture;
1053         // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1054         for (j = 0;j < 5;j++)
1055                 if (textures[j])
1056                         for (i = 0;i < MAX_TEXTUREUNITS;i++)
1057                                 if (gl_state.units[i].texture == textures[j])
1058                                         R_Mesh_TexBind(i, NULL);
1059         // set up framebuffer object or render targets for the active rendering API
1060         switch (vid.renderpath)
1061         {
1062         case RENDERPATH_GL32:
1063         case RENDERPATH_GLES2:
1064                 if (gl_state.framebufferobject != fbo)
1065                 {
1066                         gl_state.framebufferobject = fbo;
1067                         qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);CHECKGLERROR
1068                 }
1069                 break;
1070         }
1071 }
1072
1073 static void GL_Backend_ResetState(void)
1074 {
1075         gl_state.active = true;
1076         gl_state.depthtest = true;
1077         gl_state.alphatocoverage = false;
1078         gl_state.blendfunc1 = GL_ONE;
1079         gl_state.blendfunc2 = GL_ZERO;
1080         gl_state.blend = false;
1081         gl_state.depthmask = GL_TRUE;
1082         gl_state.colormask = 15;
1083         gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1084         gl_state.lockrange_first = 0;
1085         gl_state.lockrange_count = 0;
1086         gl_state.cullface = GL_FRONT;
1087         gl_state.cullfaceenable = false;
1088         gl_state.polygonoffset[0] = 0;
1089         gl_state.polygonoffset[1] = 0;
1090         gl_state.framebufferobject = 0;
1091         gl_state.depthfunc = GL_LEQUAL;
1092
1093         switch(vid.renderpath)
1094         {
1095         case RENDERPATH_GL32:
1096         case RENDERPATH_GLES2:
1097                 // set up debug output early
1098                 if (vid.support.arb_debug_output)
1099                 {
1100                         GLuint unused = 0;
1101                         CHECKGLERROR
1102                         if (gl_debug.integer >= 1)
1103                                 qglEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1104                         if (gl_debug.integer >= 3)
1105                                 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, &unused, gl_debug.integer >= 3 ? GL_TRUE : GL_FALSE);
1106                         else if (gl_debug.integer >= 1)
1107                         {
1108                                 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, &unused, gl_debug.integer >= 3 ? GL_TRUE : GL_FALSE);
1109                                 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM_ARB, 0, &unused, gl_debug.integer >= 2 ? GL_TRUE : GL_FALSE);
1110                                 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH_ARB, 0, &unused, gl_debug.integer >= 1 ? GL_TRUE : GL_FALSE);
1111                         }
1112                         else
1113                                 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, &unused, GL_FALSE);
1114                         qglDebugMessageCallbackARB(GL_DebugOutputCallback, NULL);
1115                 }
1116                 CHECKGLERROR
1117                 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1118                 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1119                 qglDisable(GL_BLEND);CHECKGLERROR
1120                 qglCullFace(gl_state.cullface);CHECKGLERROR
1121                 qglDisable(GL_CULL_FACE);CHECKGLERROR
1122                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1123                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1124                 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1125                 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1126                 qglBindBuffer(GL_ARRAY_BUFFER, 0);
1127                 qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1128                 qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.defaultframebufferobject);
1129                 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1130                 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1131                 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1132                 gl_state.unit = MAX_TEXTUREUNITS;
1133                 CHECKGLERROR
1134                 break;
1135         }
1136 }
1137
1138 void GL_ActiveTexture(unsigned int num)
1139 {
1140         if (gl_state.unit != num)
1141         {
1142                 gl_state.unit = num;
1143                 switch(vid.renderpath)
1144                 {
1145                 case RENDERPATH_GL32:
1146                 case RENDERPATH_GLES2:
1147                         CHECKGLERROR
1148                         qglActiveTexture(GL_TEXTURE0 + gl_state.unit);CHECKGLERROR
1149                         break;
1150                 }
1151         }
1152 }
1153
1154 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1155 {
1156         if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1157         {
1158                 qboolean blendenable;
1159                 gl_state.blendfunc1 = blendfunc1;
1160                 gl_state.blendfunc2 = blendfunc2;
1161                 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1162                 switch(vid.renderpath)
1163                 {
1164                 case RENDERPATH_GL32:
1165                 case RENDERPATH_GLES2:
1166                         CHECKGLERROR
1167                         if (qglBlendFuncSeparate)
1168                         {
1169                                 qglBlendFuncSeparate(gl_state.blendfunc1, gl_state.blendfunc2, GL_ZERO, GL_ONE);CHECKGLERROR // ELUAN: Adreno 225 (and others) compositing workaround
1170                         }
1171                         else
1172                         {
1173                                 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1174                         }
1175                         if (gl_state.blend != blendenable)
1176                         {
1177                                 gl_state.blend = blendenable;
1178                                 if (!gl_state.blend)
1179                                 {
1180                                         qglDisable(GL_BLEND);CHECKGLERROR
1181                                 }
1182                                 else
1183                                 {
1184                                         qglEnable(GL_BLEND);CHECKGLERROR
1185                                 }
1186                         }
1187                         break;
1188                 }
1189         }
1190 }
1191
1192 void GL_DepthMask(int state)
1193 {
1194         if (gl_state.depthmask != state)
1195         {
1196                 gl_state.depthmask = state;
1197                 switch(vid.renderpath)
1198                 {
1199                 case RENDERPATH_GL32:
1200                 case RENDERPATH_GLES2:
1201                         CHECKGLERROR
1202                         qglDepthMask(gl_state.depthmask);CHECKGLERROR
1203                         break;
1204                 }
1205         }
1206 }
1207
1208 void GL_DepthTest(int state)
1209 {
1210         if (gl_state.depthtest != state)
1211         {
1212                 gl_state.depthtest = state;
1213                 switch(vid.renderpath)
1214                 {
1215                 case RENDERPATH_GL32:
1216                 case RENDERPATH_GLES2:
1217                         CHECKGLERROR
1218                         if (gl_state.depthtest)
1219                         {
1220                                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1221                         }
1222                         else
1223                         {
1224                                 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1225                         }
1226                         break;
1227                 }
1228         }
1229 }
1230
1231 void GL_DepthFunc(int state)
1232 {
1233         if (gl_state.depthfunc != state)
1234         {
1235                 gl_state.depthfunc = state;
1236                 switch(vid.renderpath)
1237                 {
1238                 case RENDERPATH_GL32:
1239                 case RENDERPATH_GLES2:
1240                         CHECKGLERROR
1241                         qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1242                         break;
1243                 }
1244         }
1245 }
1246
1247 void GL_DepthRange(float nearfrac, float farfrac)
1248 {
1249         if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1250         {
1251                 gl_state.depthrange[0] = nearfrac;
1252                 gl_state.depthrange[1] = farfrac;
1253                 switch(vid.renderpath)
1254                 {
1255                 case RENDERPATH_GL32:
1256                 case RENDERPATH_GLES2:
1257                         CHECKGLERROR
1258 #ifdef USE_GLES2
1259                         qglDepthRangef(gl_state.depthrange[0], gl_state.depthrange[1]);CHECKGLERROR
1260 #else
1261                         qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);CHECKGLERROR
1262 #endif
1263                         break;
1264                 }
1265         }
1266 }
1267
1268 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1269 {
1270         switch (vid.renderpath)
1271         {
1272         case RENDERPATH_GL32:
1273         case RENDERPATH_GLES2:
1274                 CHECKGLERROR
1275                 if (enable)
1276                 {
1277                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1278                 }
1279                 else
1280                 {
1281                         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1282                 }
1283                 qglStencilMask(writemask);CHECKGLERROR
1284                 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1285                 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1286                 CHECKGLERROR
1287                 break;
1288         }
1289 }
1290
1291 void GL_PolygonOffset(float planeoffset, float depthoffset)
1292 {
1293         if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1294         {
1295                 gl_state.polygonoffset[0] = planeoffset;
1296                 gl_state.polygonoffset[1] = depthoffset;
1297                 switch(vid.renderpath)
1298                 {
1299                 case RENDERPATH_GL32:
1300                 case RENDERPATH_GLES2:
1301                         CHECKGLERROR
1302                         qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);CHECKGLERROR
1303                         break;
1304                 }
1305         }
1306 }
1307
1308 void GL_SetMirrorState(qboolean state)
1309 {
1310         if (v_flipped_state != state)
1311         {
1312                 v_flipped_state = state;
1313                 if (gl_state.cullface == GL_BACK)
1314                         gl_state.cullface = GL_FRONT;
1315                 else if (gl_state.cullface == GL_FRONT)
1316                         gl_state.cullface = GL_BACK;
1317                 else
1318                         return;
1319                 switch(vid.renderpath)
1320                 {
1321                 case RENDERPATH_GL32:
1322                 case RENDERPATH_GLES2:
1323                         CHECKGLERROR
1324                         qglCullFace(gl_state.cullface);CHECKGLERROR
1325                         break;
1326                 }
1327         }
1328 }
1329
1330 void GL_CullFace(int state)
1331 {
1332         if(v_flipped_state)
1333         {
1334                 if(state == GL_FRONT)
1335                         state = GL_BACK;
1336                 else if(state == GL_BACK)
1337                         state = GL_FRONT;
1338         }
1339
1340         switch(vid.renderpath)
1341         {
1342         case RENDERPATH_GL32:
1343         case RENDERPATH_GLES2:
1344                 CHECKGLERROR
1345
1346                 if (state != GL_NONE)
1347                 {
1348                         if (!gl_state.cullfaceenable)
1349                         {
1350                                 gl_state.cullfaceenable = true;
1351                                 qglEnable(GL_CULL_FACE);CHECKGLERROR
1352                         }
1353                         if (gl_state.cullface != state)
1354                         {
1355                                 gl_state.cullface = state;
1356                                 qglCullFace(gl_state.cullface);CHECKGLERROR
1357                         }
1358                 }
1359                 else
1360                 {
1361                         if (gl_state.cullfaceenable)
1362                         {
1363                                 gl_state.cullfaceenable = false;
1364                                 qglDisable(GL_CULL_FACE);CHECKGLERROR
1365                         }
1366                 }
1367                 break;
1368         }
1369 }
1370
1371 void GL_AlphaToCoverage(qboolean state)
1372 {
1373         if (gl_state.alphatocoverage != state)
1374         {
1375                 gl_state.alphatocoverage = state;
1376                 switch(vid.renderpath)
1377                 {
1378                 case RENDERPATH_GLES2:
1379                         break;
1380                 case RENDERPATH_GL32:
1381 #ifndef USE_GLES2
1382                         // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
1383                         CHECKGLERROR
1384                         if (gl_state.alphatocoverage)
1385                         {
1386                                 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);CHECKGLERROR
1387 //                              qglEnable(GL_MULTISAMPLE);CHECKGLERROR
1388                         }
1389                         else
1390                         {
1391                                 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);CHECKGLERROR
1392 //                              qglDisable(GL_MULTISAMPLE);CHECKGLERROR
1393                         }
1394 #endif
1395                         break;
1396                 }
1397         }
1398 }
1399
1400 void GL_ColorMask(int r, int g, int b, int a)
1401 {
1402         // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
1403         int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
1404         if (gl_state.colormask != state)
1405         {
1406                 gl_state.colormask = state;
1407                 switch(vid.renderpath)
1408                 {
1409                 case RENDERPATH_GL32:
1410                 case RENDERPATH_GLES2:
1411                         CHECKGLERROR
1412                         qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
1413                         break;
1414                 }
1415         }
1416 }
1417
1418 void GL_Color(float cr, float cg, float cb, float ca)
1419 {
1420         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)
1421         {
1422                 gl_state.color4f[0] = cr;
1423                 gl_state.color4f[1] = cg;
1424                 gl_state.color4f[2] = cb;
1425                 gl_state.color4f[3] = ca;
1426                 switch(vid.renderpath)
1427                 {
1428                 case RENDERPATH_GL32:
1429                 case RENDERPATH_GLES2:
1430                         qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);CHECKGLERROR
1431                         break;
1432                 }
1433         }
1434 }
1435
1436 void GL_Scissor (int x, int y, int width, int height)
1437 {
1438         switch(vid.renderpath)
1439         {
1440         case RENDERPATH_GL32:
1441         case RENDERPATH_GLES2:
1442                 CHECKGLERROR
1443                 qglScissor(x, y,width,height);CHECKGLERROR
1444                 break;
1445         }
1446 }
1447
1448 void GL_ScissorTest(int state)
1449 {
1450         if (gl_state.scissortest != state)
1451         {
1452                 gl_state.scissortest = state;
1453                 switch(vid.renderpath)
1454                 {
1455                 case RENDERPATH_GL32:
1456                 case RENDERPATH_GLES2:
1457                         CHECKGLERROR
1458                         if(gl_state.scissortest)
1459                                 qglEnable(GL_SCISSOR_TEST);
1460                         else
1461                                 qglDisable(GL_SCISSOR_TEST);
1462                         CHECKGLERROR
1463                         break;
1464                 }
1465         }
1466 }
1467
1468 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
1469 {
1470         // opaque black - if you want transparent black, you'll need to pass in a colorvalue
1471         static const float blackcolor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
1472         // prevent warnings when trying to clear a buffer that does not exist
1473         if (!colorvalue)
1474                 colorvalue = blackcolor;
1475         if (!vid.stencil)
1476         {
1477                 mask &= ~GL_STENCIL_BUFFER_BIT;
1478                 stencilvalue = 0;
1479         }
1480         switch(vid.renderpath)
1481         {
1482         case RENDERPATH_GL32:
1483         case RENDERPATH_GLES2:
1484                 CHECKGLERROR
1485                 if (mask & GL_COLOR_BUFFER_BIT)
1486                 {
1487                         qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
1488                 }
1489                 if (mask & GL_DEPTH_BUFFER_BIT)
1490                 {
1491 #ifdef USE_GLES2
1492                         qglClearDepthf(depthvalue);CHECKGLERROR
1493 #else
1494                         qglClearDepth(depthvalue);CHECKGLERROR
1495 #endif
1496                 }
1497                 if (mask & GL_STENCIL_BUFFER_BIT)
1498                 {
1499                         qglClearStencil(stencilvalue);CHECKGLERROR
1500                 }
1501                 qglClear(mask);CHECKGLERROR
1502                 break;
1503         }
1504 }
1505
1506 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
1507 {
1508         switch(vid.renderpath)
1509         {
1510         case RENDERPATH_GL32:
1511         case RENDERPATH_GLES2:
1512                 CHECKGLERROR
1513 #ifndef GL_BGRA
1514                 {
1515                         int i;
1516                         int r;
1517                 //      int g;
1518                         int b;
1519                 //      int a;
1520                         qglReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
1521                         for (i = 0;i < width * height * 4;i += 4)
1522                         {
1523                                 r = outpixels[i+0];
1524                 //              g = outpixels[i+1];
1525                                 b = outpixels[i+2];
1526                 //              a = outpixels[i+3];
1527                                 outpixels[i+0] = b;
1528                 //              outpixels[i+1] = g;
1529                                 outpixels[i+2] = r;
1530                 //              outpixels[i+3] = a;
1531                         }
1532                 }
1533 #else
1534                 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
1535 #endif
1536                         break;
1537         }
1538 }
1539
1540 // called at beginning of frame
1541 void R_Mesh_Start(void)
1542 {
1543         BACKENDACTIVECHECK
1544         R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
1545         if (gl_printcheckerror.integer && !gl_paranoid.integer)
1546         {
1547                 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
1548                 Cvar_SetValueQuick(&gl_paranoid, 1);
1549         }
1550 }
1551
1552 static qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
1553 {
1554         int shaderobject;
1555         int shadercompiled;
1556         char compilelog[MAX_INPUTLINE];
1557         shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
1558         if (!shaderobject)
1559                 return false;
1560         qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
1561         qglCompileShader(shaderobject);CHECKGLERROR
1562         qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
1563         qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
1564         if (compilelog[0] && ((strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error")) || ((strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")) && developer.integer) || developer_extra.integer))
1565         {
1566                 int i, j, pretextlines = 0;
1567                 for (i = 0;i < numstrings - 1;i++)
1568                         for (j = 0;strings[i][j];j++)
1569                                 if (strings[i][j] == '\n')
1570                                         pretextlines++;
1571                 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
1572         }
1573         if (!shadercompiled)
1574         {
1575                 qglDeleteShader(shaderobject);CHECKGLERROR
1576                 return false;
1577         }
1578         qglAttachShader(programobject, shaderobject);CHECKGLERROR
1579         qglDeleteShader(shaderobject);CHECKGLERROR
1580         return true;
1581 }
1582
1583 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)
1584 {
1585         GLint programlinked;
1586         GLuint programobject = 0;
1587         char linklog[MAX_INPUTLINE];
1588         CHECKGLERROR
1589
1590         programobject = qglCreateProgram();CHECKGLERROR
1591         if (!programobject)
1592                 return 0;
1593
1594         qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
1595         qglBindAttribLocation(programobject, GLSLATTRIB_COLOR    , "Attrib_Color"    );
1596         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
1597         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
1598         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
1599         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
1600         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
1601         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
1602         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_SkeletalIndex");
1603         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_SkeletalWeight");
1604 #ifndef USE_GLES2
1605         qglBindFragDataLocation(programobject, 0, "dp_FragColor");
1606 #endif
1607         CHECKGLERROR
1608
1609         if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
1610                 goto cleanup;
1611
1612 #if defined(GL_GEOMETRY_SHADER) && !defined(USE_GLES2)
1613         if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
1614                 goto cleanup;
1615 #endif
1616
1617         if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
1618                 goto cleanup;
1619
1620         qglLinkProgram(programobject);CHECKGLERROR
1621         qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
1622         qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
1623
1624         if (linklog[0])
1625         {
1626
1627                 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer)
1628                         Con_DPrintf("program link log:\n%s\n", linklog);
1629
1630                 // software vertex shader is ok but software fragment shader is WAY
1631                 // too slow, fail program if so.
1632                 // NOTE: this string might be ATI specific, but that's ok because the
1633                 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
1634                 // software fragment shader due to low instruction and dependent
1635                 // texture limits.
1636                 if (strstr(linklog, "fragment shader will run in software"))
1637                         programlinked = false;
1638         }
1639
1640         if (!programlinked)
1641                 goto cleanup;
1642
1643         return programobject;
1644 cleanup:
1645         qglDeleteProgram(programobject);CHECKGLERROR
1646         return 0;
1647 }
1648
1649 void GL_Backend_FreeProgram(unsigned int prog)
1650 {
1651         CHECKGLERROR
1652         qglDeleteProgram(prog);
1653         CHECKGLERROR
1654 }
1655
1656 // renders triangles using vertices from the active arrays
1657 void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, int element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, int element3s_bufferoffset)
1658 {
1659         unsigned int numelements = numtriangles * 3;
1660         int bufferobject3i;
1661         size_t bufferoffset3i;
1662         int bufferobject3s;
1663         size_t bufferoffset3s;
1664         if (numvertices < 3 || numtriangles < 1)
1665         {
1666                 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
1667                         Con_DPrintf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %8x, %8p, %8p, %8x);\n", firstvertex, numvertices, firsttriangle, numtriangles, (void *)element3i, (void *)element3i_indexbuffer, (int)element3i_bufferoffset, (void *)element3s, (void *)element3s_indexbuffer, (int)element3s_bufferoffset);
1668                 return;
1669         }
1670         // adjust the pointers for firsttriangle
1671         if (element3i)
1672                 element3i += firsttriangle * 3;
1673         if (element3i_indexbuffer)
1674                 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
1675         if (element3s)
1676                 element3s += firsttriangle * 3;
1677         if (element3s_indexbuffer)
1678                 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
1679         // upload a dynamic index buffer if needed
1680         if (element3s)
1681         {
1682                 if (!element3s_indexbuffer)
1683                         element3s_indexbuffer = R_BufferData_Store(numelements * sizeof(*element3s), (void *)element3s, R_BUFFERDATA_INDEX16, &element3s_bufferoffset);
1684         }
1685         else if (element3i)
1686         {
1687                 if (!element3i_indexbuffer)
1688                         element3i_indexbuffer = R_BufferData_Store(numelements * sizeof(*element3i), (void *)element3i, R_BUFFERDATA_INDEX32, &element3i_bufferoffset);
1689         }
1690         bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
1691         bufferoffset3i = element3i_bufferoffset;
1692         bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
1693         bufferoffset3s = element3s_bufferoffset;
1694         r_refdef.stats[r_stat_draws]++;
1695         r_refdef.stats[r_stat_draws_vertices] += numvertices;
1696         r_refdef.stats[r_stat_draws_elements] += numelements;
1697         if (gl_paranoid.integer)
1698         {
1699                 unsigned int i;
1700                 if (element3i)
1701                 {
1702                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1703                         {
1704                                 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
1705                                 {
1706                                         Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
1707                                         return;
1708                                 }
1709                         }
1710                 }
1711                 if (element3s)
1712                 {
1713                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1714                         {
1715                                 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
1716                                 {
1717                                         Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
1718                                         return;
1719                                 }
1720                         }
1721                 }
1722         }
1723         if (r_render.integer || r_refdef.draw2dstage)
1724         {
1725                 switch(vid.renderpath)
1726                 {
1727                 case RENDERPATH_GL32:
1728                 case RENDERPATH_GLES2:
1729                         CHECKGLERROR
1730                         if (bufferobject3s)
1731                         {
1732                                 GL_BindEBO(bufferobject3s);
1733                                 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);CHECKGLERROR
1734                         }
1735                         else if (bufferobject3i)
1736                         {
1737                                 GL_BindEBO(bufferobject3i);
1738                                 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);CHECKGLERROR
1739                         }
1740                         else
1741                         {
1742                                 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);CHECKGLERROR
1743                         }
1744                         break;
1745                 }
1746         }
1747 }
1748
1749 // restores backend state, used when done with 3D rendering
1750 void R_Mesh_Finish(void)
1751 {
1752         R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
1753 }
1754
1755 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isuniformbuffer, qboolean isdynamic, qboolean isindex16)
1756 {
1757         r_meshbuffer_t *buffer;
1758         buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
1759         memset(buffer, 0, sizeof(*buffer));
1760         buffer->bufferobject = 0;
1761         buffer->devicebuffer = NULL;
1762         buffer->size = size;
1763         buffer->isindexbuffer = isindexbuffer;
1764         buffer->isuniformbuffer = isuniformbuffer;
1765         buffer->isdynamic = isdynamic;
1766         buffer->isindex16 = isindex16;
1767         strlcpy(buffer->name, name, sizeof(buffer->name));
1768         R_Mesh_UpdateMeshBuffer(buffer, data, size, false, 0);
1769         return buffer;
1770 }
1771
1772 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size, qboolean subdata, size_t offset)
1773 {
1774         if (!buffer)
1775                 return;
1776         if (buffer->isindexbuffer)
1777         {
1778                 r_refdef.stats[r_stat_indexbufferuploadcount]++;
1779                 r_refdef.stats[r_stat_indexbufferuploadsize] += (int)size;
1780         }
1781         else
1782         {
1783                 r_refdef.stats[r_stat_vertexbufferuploadcount]++;
1784                 r_refdef.stats[r_stat_vertexbufferuploadsize] += (int)size;
1785         }
1786         if (!subdata)
1787                 buffer->size = size;
1788         switch(vid.renderpath)
1789         {
1790         case RENDERPATH_GL32:
1791         case RENDERPATH_GLES2:
1792                 if (!buffer->bufferobject)
1793                         qglGenBuffers(1, (GLuint *)&buffer->bufferobject);
1794                 CHECKGLERROR
1795                 if (buffer->isuniformbuffer)
1796                         GL_BindUBO(buffer->bufferobject);
1797                 else if (buffer->isindexbuffer)
1798                         GL_BindEBO(buffer->bufferobject);
1799                 else
1800                         GL_BindVBO(buffer->bufferobject);
1801
1802                 {
1803                         int buffertype;
1804                         buffertype = buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
1805 #ifdef GL_UNIFORM_BUFFER
1806                         if (buffer->isuniformbuffer)
1807                                 buffertype = GL_UNIFORM_BUFFER;
1808 #endif
1809                         CHECKGLERROR
1810                         if (subdata)
1811                                 qglBufferSubData(buffertype, offset, size, data);
1812                         else
1813                                 qglBufferData(buffertype, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW);
1814                         CHECKGLERROR
1815                 }
1816                 if (buffer->isuniformbuffer)
1817                         GL_BindUBO(0);
1818                 break;
1819         }
1820 }
1821
1822 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
1823 {
1824         if (!buffer)
1825                 return;
1826         switch(vid.renderpath)
1827         {
1828         case RENDERPATH_GL32:
1829         case RENDERPATH_GLES2:
1830                 // GL clears the binding if we delete something bound
1831                 if (gl_state.uniformbufferobject == buffer->bufferobject)
1832                         gl_state.uniformbufferobject = 0;
1833                 if (gl_state.vertexbufferobject == buffer->bufferobject)
1834                         gl_state.vertexbufferobject = 0;
1835                 if (gl_state.elementbufferobject == buffer->bufferobject)
1836                         gl_state.elementbufferobject = 0;
1837                 CHECKGLERROR
1838                 qglDeleteBuffers(1, (GLuint *)&buffer->bufferobject);CHECKGLERROR
1839                 break;
1840         }
1841         Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
1842 }
1843
1844 static const char *buffertypename[R_BUFFERDATA_COUNT] = {"vertex", "index16", "index32", "uniform"};
1845 void GL_Mesh_ListVBOs(qboolean printeach)
1846 {
1847         int i, endindex;
1848         int type;
1849         int isdynamic;
1850         int index16count, index16mem;
1851         int index32count, index32mem;
1852         int vertexcount, vertexmem;
1853         int uniformcount, uniformmem;
1854         int totalcount, totalmem;
1855         size_t bufferstat[R_BUFFERDATA_COUNT][2][2];
1856         r_meshbuffer_t *buffer;
1857         memset(bufferstat, 0, sizeof(bufferstat));
1858         endindex = (int)Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
1859         for (i = 0;i < endindex;i++)
1860         {
1861                 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
1862                 if (!buffer)
1863                         continue;
1864                 if (buffer->isuniformbuffer)
1865                         type = R_BUFFERDATA_UNIFORM;
1866                 else if (buffer->isindexbuffer && buffer->isindex16)
1867                         type = R_BUFFERDATA_INDEX16;
1868                 else if (buffer->isindexbuffer)
1869                         type = R_BUFFERDATA_INDEX32;
1870                 else
1871                         type = R_BUFFERDATA_VERTEX;
1872                 isdynamic = buffer->isdynamic;
1873                 bufferstat[type][isdynamic][0]++;
1874                 bufferstat[type][isdynamic][1] += buffer->size;
1875                 if (printeach)
1876                         Con_Printf("buffer #%i %s = %i bytes (%s %s)\n", i, buffer->name, (int)buffer->size, isdynamic ? "dynamic" : "static", buffertypename[type]);
1877         }
1878         index16count   = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][0] + bufferstat[R_BUFFERDATA_INDEX16][1][0]);
1879         index16mem     = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][1] + bufferstat[R_BUFFERDATA_INDEX16][1][1]);
1880         index32count   = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][0] + bufferstat[R_BUFFERDATA_INDEX32][1][0]);
1881         index32mem     = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][1] + bufferstat[R_BUFFERDATA_INDEX32][1][1]);
1882         vertexcount  = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][0] + bufferstat[R_BUFFERDATA_VERTEX ][1][0]);
1883         vertexmem    = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][1] + bufferstat[R_BUFFERDATA_VERTEX ][1][1]);
1884         uniformcount = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][0] + bufferstat[R_BUFFERDATA_UNIFORM][1][0]);
1885         uniformmem   = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][1] + bufferstat[R_BUFFERDATA_UNIFORM][1][1]);
1886         totalcount = index16count + index32count + vertexcount + uniformcount;
1887         totalmem = index16mem + index32mem + vertexmem + uniformmem;
1888         Con_Printf("%i 16bit indexbuffers totalling %i bytes (%.3f MB)\n%i 32bit indexbuffers totalling %i bytes (%.3f MB)\n%i vertexbuffers totalling %i bytes (%.3f MB)\n%i uniformbuffers totalling %i bytes (%.3f MB)\ncombined %i buffers totalling %i bytes (%.3fMB)\n", index16count, index16mem, index16mem / 10248576.0, index32count, index32mem, index32mem / 10248576.0, vertexcount, vertexmem, vertexmem / 10248576.0, uniformcount, uniformmem, uniformmem / 10248576.0, totalcount, totalmem, totalmem / 10248576.0);
1889 }
1890
1891
1892
1893 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
1894 {
1895         switch(vid.renderpath)
1896         {
1897         case RENDERPATH_GL32:
1898         case RENDERPATH_GLES2:
1899                 if (gl_state.pointer_vertex_components != components || gl_state.pointer_vertex_gltype != gltype || gl_state.pointer_vertex_stride != stride || gl_state.pointer_vertex_pointer != pointer || gl_state.pointer_vertex_vertexbuffer != vertexbuffer || gl_state.pointer_vertex_offset != bufferoffset)
1900                 {
1901                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
1902                         if (!bufferobject && gl_paranoid.integer)
1903                                 Con_DPrintf("Warning: no bufferobject in R_Mesh_VertexPointer(%i, %i, %i, %p, %p, %08x)", components, gltype, (int)stride, pointer, vertexbuffer, (unsigned int)bufferoffset);
1904                         gl_state.pointer_vertex_components = components;
1905                         gl_state.pointer_vertex_gltype = gltype;
1906                         gl_state.pointer_vertex_stride = stride;
1907                         gl_state.pointer_vertex_pointer = pointer;
1908                         gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
1909                         gl_state.pointer_vertex_offset = bufferoffset;
1910                         CHECKGLERROR
1911                         GL_BindVBO(bufferobject);
1912                         // LordHavoc: special flag added to gltype for unnormalized types
1913                         qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
1914                 }
1915                 break;
1916         }
1917 }
1918
1919 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
1920 {
1921         // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
1922         // the pointer only.
1923         switch(vid.renderpath)
1924         {
1925         case RENDERPATH_GL32:
1926         case RENDERPATH_GLES2:
1927                 CHECKGLERROR
1928                 if (pointer)
1929                 {
1930                         // caller wants color array enabled
1931                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
1932                         if (!gl_state.pointer_color_enabled)
1933                         {
1934                                 gl_state.pointer_color_enabled = true;
1935                                 CHECKGLERROR
1936                                 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
1937                         }
1938                         if (gl_state.pointer_color_components != components || gl_state.pointer_color_gltype != gltype || gl_state.pointer_color_stride != stride || gl_state.pointer_color_pointer != pointer || gl_state.pointer_color_vertexbuffer != vertexbuffer || gl_state.pointer_color_offset != bufferoffset)
1939                         {
1940                                 gl_state.pointer_color_components = components;
1941                                 gl_state.pointer_color_gltype = gltype;
1942                                 gl_state.pointer_color_stride = stride;
1943                                 gl_state.pointer_color_pointer = pointer;
1944                                 gl_state.pointer_color_vertexbuffer = vertexbuffer;
1945                                 gl_state.pointer_color_offset = bufferoffset;
1946                                 CHECKGLERROR
1947                                 GL_BindVBO(bufferobject);
1948                                 // LordHavoc: special flag added to gltype for unnormalized types
1949                                 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
1950                         }
1951                 }
1952                 else
1953                 {
1954                         // caller wants color array disabled
1955                         if (gl_state.pointer_color_enabled)
1956                         {
1957                                 gl_state.pointer_color_enabled = false;
1958                                 CHECKGLERROR
1959                                 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
1960                                 // when color array is on the current color gets trashed, set it again
1961                                 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
1962                         }
1963                 }
1964                 break;
1965         }
1966 }
1967
1968 void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
1969 {
1970         gltextureunit_t *unit = gl_state.units + unitnum;
1971         if (unitnum >= MAX_TEXTUREUNITS)
1972                 Sys_Error("R_Mesh_TexCoordPointer: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
1973         // update array settings
1974         // note: there is no need to check bufferobject here because all cases
1975         // that involve a valid bufferobject also supply a texcoord array
1976         switch(vid.renderpath)
1977         {
1978         case RENDERPATH_GL32:
1979         case RENDERPATH_GLES2:
1980                 CHECKGLERROR
1981                 if (pointer)
1982                 {
1983                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
1984                         // texture array unit is enabled, enable the array
1985                         if (!unit->arrayenabled)
1986                         {
1987                                 unit->arrayenabled = true;
1988                                 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1989                         }
1990                         // texcoord array
1991                         if (unit->pointer_texcoord_components != components || unit->pointer_texcoord_gltype != gltype || unit->pointer_texcoord_stride != stride || unit->pointer_texcoord_pointer != pointer || unit->pointer_texcoord_vertexbuffer != vertexbuffer || unit->pointer_texcoord_offset != bufferoffset)
1992                         {
1993                                 unit->pointer_texcoord_components = components;
1994                                 unit->pointer_texcoord_gltype = gltype;
1995                                 unit->pointer_texcoord_stride = stride;
1996                                 unit->pointer_texcoord_pointer = pointer;
1997                                 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
1998                                 unit->pointer_texcoord_offset = bufferoffset;
1999                                 GL_BindVBO(bufferobject);
2000                                 // LordHavoc: special flag added to gltype for unnormalized types
2001                                 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2002                         }
2003                 }
2004                 else
2005                 {
2006                         // texture array unit is disabled, disable the array
2007                         if (unit->arrayenabled)
2008                         {
2009                                 unit->arrayenabled = false;
2010                                 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
2011                         }
2012                 }
2013                 break;
2014         }
2015 }
2016
2017 int R_Mesh_TexBound(unsigned int unitnum, int id)
2018 {
2019         gltextureunit_t *unit = gl_state.units + unitnum;
2020         if (unitnum >= MAX_TEXTUREUNITS)
2021                 Sys_Error("R_Mesh_TexCoordPointer: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
2022         if (id == GL_TEXTURE_2D)
2023                 return unit->t2d;
2024         if (id == GL_TEXTURE_3D)
2025                 return unit->t3d;
2026         if (id == GL_TEXTURE_CUBE_MAP)
2027                 return unit->tcubemap;
2028         return 0;
2029 }
2030
2031 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
2032 {
2033         switch(vid.renderpath)
2034         {
2035         case RENDERPATH_GL32:
2036         case RENDERPATH_GLES2:
2037                 R_Mesh_TexBind(0, tex);
2038                 GL_ActiveTexture(0);CHECKGLERROR
2039                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
2040                 break;
2041         }
2042 }
2043
2044 void R_Mesh_ClearBindingsForTexture(int texnum)
2045 {
2046         gltextureunit_t *unit;
2047         unsigned int unitnum;
2048         // unbind the texture from any units it is bound on - this prevents accidental reuse of certain textures whose bindings can linger far too long otherwise (e.g. bouncegrid which is a 3D texture) and confuse the driver later.
2049         for (unitnum = 0; unitnum < MAX_TEXTUREUNITS; unitnum++)
2050         {
2051                 unit = gl_state.units + unitnum;
2052                 if (unit->texture && unit->texture->texnum == texnum)
2053                         R_Mesh_TexBind(unitnum, NULL);
2054         }
2055 }
2056
2057 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
2058 {
2059         gltextureunit_t *unit = gl_state.units + unitnum;
2060         int texnum;
2061         if (unitnum >= MAX_TEXTUREUNITS)
2062                 Sys_Error("R_Mesh_TexBind: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
2063         if (unit->texture == tex)
2064                 return;
2065         switch(vid.renderpath)
2066         {
2067         case RENDERPATH_GL32:
2068         case RENDERPATH_GLES2:
2069                 if (!tex)
2070                 {
2071                         tex = r_texture_white;
2072                         // not initialized enough yet...
2073                         if (!tex)
2074                                 return;
2075                 }
2076                 unit->texture = tex;
2077                 texnum = R_GetTexture(tex);
2078                 switch(tex->gltexturetypeenum)
2079                 {
2080                 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
2081                 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
2082                 case GL_TEXTURE_CUBE_MAP: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR}break;
2083                 }
2084                 break;
2085         }
2086 }
2087
2088 void R_Mesh_ResetTextureState(void)
2089 {
2090         unsigned int unitnum;
2091
2092         BACKENDACTIVECHECK
2093
2094         for (unitnum = 0;unitnum < MAX_TEXTUREUNITS;unitnum++)
2095                 R_Mesh_TexBind(unitnum, NULL);
2096 }
2097
2098 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
2099 {
2100         // upload temporary vertexbuffer for this rendering
2101         if (!vertexbuffer)
2102                 vertexbuffer = R_BufferData_Store(numvertices * sizeof(float[3]), (void *)vertex3f, R_BUFFERDATA_VERTEX, &bufferoffset);
2103         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(float[3])        , vertex3f  , vertexbuffer     , bufferoffset           );
2104         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(float[4])        , NULL      , NULL             , 0                      );
2105         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(float[2])        , NULL      , NULL             , 0                      );
2106         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(float[3])        , NULL      , NULL             , 0                      );
2107         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(float[3])        , NULL      , NULL             , 0                      );
2108         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(float[3])        , NULL      , NULL             , 0                      );
2109         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(float[2])        , NULL      , NULL             , 0                      );
2110         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT        , sizeof(float[2])        , NULL      , NULL             , 0                      );
2111         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL      , NULL             , 0                      );
2112         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL      , NULL             , 0                      );
2113 }
2114
2115 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
2116 {
2117         r_meshbuffer_t *buffer_vertex3f = NULL;
2118         r_meshbuffer_t *buffer_color4f = NULL;
2119         r_meshbuffer_t *buffer_texcoord2f = NULL;
2120         int bufferoffset_vertex3f = 0;
2121         int bufferoffset_color4f = 0;
2122         int bufferoffset_texcoord2f = 0;
2123         buffer_color4f    = R_BufferData_Store(numvertices * sizeof(float[4]), color4f   , R_BUFFERDATA_VERTEX, &bufferoffset_color4f   );
2124         buffer_vertex3f   = R_BufferData_Store(numvertices * sizeof(float[3]), vertex3f  , R_BUFFERDATA_VERTEX, &bufferoffset_vertex3f  );
2125         buffer_texcoord2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoord2f, R_BUFFERDATA_VERTEX, &bufferoffset_texcoord2f);
2126         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(float[3])        , vertex3f          , buffer_vertex3f          , bufferoffset_vertex3f          );
2127         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(float[4])        , color4f           , buffer_color4f           , bufferoffset_color4f           );
2128         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(float[2])        , texcoord2f        , buffer_texcoord2f        , bufferoffset_texcoord2f        );
2129         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(float[3])        , NULL              , NULL                     , 0                              );
2130         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(float[3])        , NULL              , NULL                     , 0                              );
2131         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(float[3])        , NULL              , NULL                     , 0                              );
2132         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(float[2])        , NULL              , NULL                     , 0                              );
2133         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT        , sizeof(float[2])        , NULL              , NULL                     , 0                              );
2134         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL              , NULL                     , 0                              );
2135         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL              , NULL                     , 0                              );
2136 }
2137
2138 void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *color4f, const float *texcoordtexture2f, const float *texcoordlightmap2f)
2139 {
2140         r_meshbuffer_t *buffer_vertex3f = NULL;
2141         r_meshbuffer_t *buffer_color4f = NULL;
2142         r_meshbuffer_t *buffer_texcoordtexture2f = NULL;
2143         r_meshbuffer_t *buffer_svector3f = NULL;
2144         r_meshbuffer_t *buffer_tvector3f = NULL;
2145         r_meshbuffer_t *buffer_normal3f = NULL;
2146         r_meshbuffer_t *buffer_texcoordlightmap2f = NULL;
2147         int bufferoffset_vertex3f = 0;
2148         int bufferoffset_color4f = 0;
2149         int bufferoffset_texcoordtexture2f = 0;
2150         int bufferoffset_svector3f = 0;
2151         int bufferoffset_tvector3f = 0;
2152         int bufferoffset_normal3f = 0;
2153         int bufferoffset_texcoordlightmap2f = 0;
2154         buffer_color4f            = R_BufferData_Store(numvertices * sizeof(float[4]), color4f           , R_BUFFERDATA_VERTEX, &bufferoffset_color4f           );
2155         buffer_vertex3f           = R_BufferData_Store(numvertices * sizeof(float[3]), vertex3f          , R_BUFFERDATA_VERTEX, &bufferoffset_vertex3f          );
2156         buffer_svector3f          = R_BufferData_Store(numvertices * sizeof(float[3]), svector3f         , R_BUFFERDATA_VERTEX, &bufferoffset_svector3f         );
2157         buffer_tvector3f          = R_BufferData_Store(numvertices * sizeof(float[3]), tvector3f         , R_BUFFERDATA_VERTEX, &bufferoffset_tvector3f         );
2158         buffer_normal3f           = R_BufferData_Store(numvertices * sizeof(float[3]), normal3f          , R_BUFFERDATA_VERTEX, &bufferoffset_normal3f          );
2159         buffer_texcoordtexture2f  = R_BufferData_Store(numvertices * sizeof(float[2]), texcoordtexture2f , R_BUFFERDATA_VERTEX, &bufferoffset_texcoordtexture2f );
2160         buffer_texcoordlightmap2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoordlightmap2f, R_BUFFERDATA_VERTEX, &bufferoffset_texcoordlightmap2f);
2161         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(float[3])        , vertex3f          , buffer_vertex3f          , bufferoffset_vertex3f          );
2162         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(float[4])        , color4f           , buffer_color4f           , bufferoffset_color4f           );
2163         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(float[2])        , texcoordtexture2f , buffer_texcoordtexture2f , bufferoffset_texcoordtexture2f );
2164         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(float[3])        , svector3f         , buffer_svector3f         , bufferoffset_svector3f         );
2165         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(float[3])        , tvector3f         , buffer_tvector3f         , bufferoffset_tvector3f         );
2166         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(float[3])        , normal3f          , buffer_normal3f          , bufferoffset_normal3f          );
2167         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(float[2])        , texcoordlightmap2f, buffer_texcoordlightmap2f, bufferoffset_texcoordlightmap2f);
2168         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT        , sizeof(float[2])        , NULL              , NULL                     , 0                              );
2169         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL              , NULL                     , 0                              );
2170         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL              , NULL                     , 0                              );
2171 }
2172
2173 void GL_BlendEquationSubtract(qboolean negated)
2174 {
2175         CHECKGLERROR
2176         if(negated)
2177         {
2178                 switch(vid.renderpath)
2179                 {
2180                 case RENDERPATH_GL32:
2181                 case RENDERPATH_GLES2:
2182                         qglBlendEquation(GL_FUNC_REVERSE_SUBTRACT);CHECKGLERROR
2183                         break;
2184                 }
2185         }
2186         else
2187         {
2188                 switch(vid.renderpath)
2189                 {
2190                 case RENDERPATH_GL32:
2191                 case RENDERPATH_GLES2:
2192                         qglBlendEquation(GL_FUNC_ADD);CHECKGLERROR
2193                         break;
2194                 }
2195         }
2196 }