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