]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/darkplaces-src/gl_backend.c
Better comment on my last change
[voretournament/voretournament.git] / misc / source / darkplaces-src / gl_backend.c
1
2 #include "quakedef.h"
3 #include "cl_collision.h"
4 #include "dpsoftrast.h"
5 #ifdef SUPPORTD3D
6 #include <d3d9.h>
7 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
8 extern D3DCAPS9 vid_d3d9caps;
9 #endif
10
11 #define MAX_RENDERTARGETS 4
12
13 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
14 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
15 cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
16 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
17 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
18
19 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
20 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
21 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
22 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
23 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
24 cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
25 cvar_t gl_vbo_dynamicvertex = {CVAR_SAVE, "gl_vbo_dynamicvertex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
26 cvar_t gl_vbo_dynamicindex = {CVAR_SAVE, "gl_vbo_dynamicindex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
27 cvar_t gl_fbo = {CVAR_SAVE, "gl_fbo", "1", "make use of GL_ARB_framebuffer_object extension to enable shadowmaps and other features using pixel formats different from the framebuffer"};
28
29 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
30 qboolean v_flipped_state = false;
31
32 r_viewport_t gl_viewport;
33 matrix4x4_t gl_modelmatrix;
34 matrix4x4_t gl_viewmatrix;
35 matrix4x4_t gl_modelviewmatrix;
36 matrix4x4_t gl_projectionmatrix;
37 matrix4x4_t gl_modelviewprojectionmatrix;
38 float gl_modelview16f[16];
39 float gl_modelviewprojection16f[16];
40 qboolean gl_modelmatrixchanged;
41
42 int gl_maxdrawrangeelementsvertices;
43 int gl_maxdrawrangeelementsindices;
44
45 #ifdef DEBUGGL
46 int errornumber = 0;
47
48 void GL_PrintError(int errornumber, const char *filename, int linenumber)
49 {
50         switch(errornumber)
51         {
52 #ifdef GL_INVALID_ENUM
53         case GL_INVALID_ENUM:
54                 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
55                 break;
56 #endif
57 #ifdef GL_INVALID_VALUE
58         case GL_INVALID_VALUE:
59                 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
60                 break;
61 #endif
62 #ifdef GL_INVALID_OPERATION
63         case GL_INVALID_OPERATION:
64                 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
65                 break;
66 #endif
67 #ifdef GL_STACK_OVERFLOW
68         case GL_STACK_OVERFLOW:
69                 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
70                 break;
71 #endif
72 #ifdef GL_STACK_UNDERFLOW
73         case GL_STACK_UNDERFLOW:
74                 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
75                 break;
76 #endif
77 #ifdef GL_OUT_OF_MEMORY
78         case GL_OUT_OF_MEMORY:
79                 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
80                 break;
81 #endif
82 #ifdef GL_TABLE_TOO_LARGE
83         case GL_TABLE_TOO_LARGE:
84                 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
85                 break;
86 #endif
87 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
88         case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
89                 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
90                 break;
91 #endif
92         default:
93                 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
94                 break;
95         }
96 }
97 #endif
98
99 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
100
101 void SCR_ScreenShot_f (void);
102
103 typedef struct gltextureunit_s
104 {
105         int pointer_texcoord_components;
106         int pointer_texcoord_gltype;
107         size_t pointer_texcoord_stride;
108         const void *pointer_texcoord_pointer;
109         const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
110         size_t pointer_texcoord_offset;
111
112         rtexture_t *texture;
113         int t2d, t3d, tcubemap;
114         int arrayenabled;
115         int rgbscale, alphascale;
116         int combine;
117         int combinergb, combinealpha;
118         // texmatrixenabled exists only to avoid unnecessary texmatrix compares
119         int texmatrixenabled;
120         matrix4x4_t matrix;
121 }
122 gltextureunit_t;
123
124 typedef struct gl_state_s
125 {
126         int cullface;
127         int cullfaceenable;
128         int blendfunc1;
129         int blendfunc2;
130         qboolean blend;
131         GLboolean depthmask;
132         int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
133         int depthtest;
134         int depthfunc;
135         float depthrange[2];
136         float polygonoffset[2];
137         int alphatest;
138         int alphafunc;
139         float alphafuncvalue;
140         qboolean alphatocoverage;
141         int scissortest;
142         unsigned int unit;
143         unsigned int clientunit;
144         gltextureunit_t units[MAX_TEXTUREUNITS];
145         float color4f[4];
146         int lockrange_first;
147         int lockrange_count;
148         int vertexbufferobject;
149         int elementbufferobject;
150         int framebufferobject;
151         int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
152         qboolean pointer_color_enabled;
153
154         int pointer_vertex_components;
155         int pointer_vertex_gltype;
156         size_t pointer_vertex_stride;
157         const void *pointer_vertex_pointer;
158         const r_meshbuffer_t *pointer_vertex_vertexbuffer;
159         size_t pointer_vertex_offset;
160
161         int pointer_color_components;
162         int pointer_color_gltype;
163         size_t pointer_color_stride;
164         const void *pointer_color_pointer;
165         const r_meshbuffer_t *pointer_color_vertexbuffer;
166         size_t pointer_color_offset;
167
168         void *preparevertices_tempdata;
169         size_t preparevertices_tempdatamaxsize;
170         r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
171         r_vertexgeneric_t *preparevertices_vertexgeneric;
172         r_vertexmesh_t *preparevertices_vertexmesh;
173         int preparevertices_numvertices;
174
175         r_meshbuffer_t *draw_dynamicindexbuffer;
176
177         qboolean usevbo_staticvertex;
178         qboolean usevbo_staticindex;
179         qboolean usevbo_dynamicvertex;
180         qboolean usevbo_dynamicindex;
181
182         memexpandablearray_t meshbufferarray;
183
184         qboolean active;
185
186 #ifdef SUPPORTD3D
187 //      rtexture_t *d3drt_depthtexture;
188 //      rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
189         IDirect3DSurface9 *d3drt_depthsurface;
190         IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
191         IDirect3DSurface9 *d3drt_backbufferdepthsurface;
192         IDirect3DSurface9 *d3drt_backbuffercolorsurface;
193         void *d3dvertexbuffer;
194         void *d3dvertexdata;
195         size_t d3dvertexsize;
196 #endif
197 }
198 gl_state_t;
199
200 static gl_state_t gl_state;
201
202
203 /*
204 note: here's strip order for a terrain row:
205 0--1--2--3--4
206 |\ |\ |\ |\ |
207 | \| \| \| \|
208 A--B--C--D--E
209 clockwise
210
211 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
212
213 *elements++ = i + row;
214 *elements++ = i;
215 *elements++ = i + row + 1;
216 *elements++ = i;
217 *elements++ = i + 1;
218 *elements++ = i + row + 1;
219
220
221 for (y = 0;y < rows - 1;y++)
222 {
223         for (x = 0;x < columns - 1;x++)
224         {
225                 i = y * rows + x;
226                 *elements++ = i + columns;
227                 *elements++ = i;
228                 *elements++ = i + columns + 1;
229                 *elements++ = i;
230                 *elements++ = i + 1;
231                 *elements++ = i + columns + 1;
232         }
233 }
234
235 alternative:
236 0--1--2--3--4
237 | /| /|\ | /|
238 |/ |/ | \|/ |
239 A--B--C--D--E
240 counterclockwise
241
242 for (y = 0;y < rows - 1;y++)
243 {
244         for (x = 0;x < columns - 1;x++)
245         {
246                 i = y * rows + x;
247                 *elements++ = i;
248                 *elements++ = i + columns;
249                 *elements++ = i + columns + 1;
250                 *elements++ = i + columns;
251                 *elements++ = i + columns + 1;
252                 *elements++ = i + 1;
253         }
254 }
255 */
256
257 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
258 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
259 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
260 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
261
262 void GL_VBOStats_f(void)
263 {
264         GL_Mesh_ListVBOs(true);
265 }
266
267 static void GL_Backend_ResetState(void);
268
269 static void R_Mesh_InitVertexDeclarations(void);
270 static void R_Mesh_DestroyVertexDeclarations(void);
271
272 static void R_Mesh_SetUseVBO(void)
273 {
274         switch(vid.renderpath)
275         {
276         case RENDERPATH_GL11:
277         case RENDERPATH_GL13:
278         case RENDERPATH_GL20:
279         case RENDERPATH_GLES1:
280                 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
281                 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
282                 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
283                 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
284                 break;
285         case RENDERPATH_D3D9:
286                 gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
287                 gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo;
288                 break;
289         case RENDERPATH_D3D10:
290                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
291                 break;
292         case RENDERPATH_D3D11:
293                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
294                 break;
295         case RENDERPATH_SOFT:
296                 gl_state.usevbo_staticvertex = false;
297                 gl_state.usevbo_staticindex = false;
298                 gl_state.usevbo_dynamicvertex = false;
299                 gl_state.usevbo_dynamicindex = false;
300                 break;
301         case RENDERPATH_GLES2:
302                 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
303                 gl_state.usevbo_staticindex = false;
304                 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
305                 gl_state.usevbo_dynamicindex = false;
306                 break;
307         }
308 }
309
310 static void gl_backend_start(void)
311 {
312         memset(&gl_state, 0, sizeof(gl_state));
313
314         R_Mesh_InitVertexDeclarations();
315
316         R_Mesh_SetUseVBO();
317         Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
318
319         Con_DPrintf("OpenGL backend started.\n");
320
321         CHECKGLERROR
322
323         GL_Backend_ResetState();
324
325         switch(vid.renderpath)
326         {
327         case RENDERPATH_GL11:
328         case RENDERPATH_GL13:
329         case RENDERPATH_GL20:
330         case RENDERPATH_GLES1:
331         case RENDERPATH_GLES2:
332                 // fetch current fbo here (default fbo is not 0 on some GLES devices)
333                 if (vid.support.ext_framebuffer_object)
334                         qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
335                 break;
336         case RENDERPATH_D3D9:
337 #ifdef SUPPORTD3D
338                 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
339                 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
340 #endif
341                 break;
342         case RENDERPATH_D3D10:
343                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
344                 break;
345         case RENDERPATH_D3D11:
346                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
347                 break;
348         case RENDERPATH_SOFT:
349                 break;
350         }
351 }
352
353 static void gl_backend_shutdown(void)
354 {
355         Con_DPrint("OpenGL Backend shutting down\n");
356
357         switch(vid.renderpath)
358         {
359         case RENDERPATH_GL11:
360         case RENDERPATH_GL13:
361         case RENDERPATH_GL20:
362         case RENDERPATH_SOFT:
363         case RENDERPATH_GLES1:
364         case RENDERPATH_GLES2:
365                 break;
366         case RENDERPATH_D3D9:
367 #ifdef SUPPORTD3D
368                 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
369                 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
370 #endif
371                 break;
372         case RENDERPATH_D3D10:
373                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
374                 break;
375         case RENDERPATH_D3D11:
376                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
377                 break;
378         }
379
380         if (gl_state.preparevertices_tempdata)
381                 Mem_Free(gl_state.preparevertices_tempdata);
382         if (gl_state.preparevertices_dynamicvertexbuffer)
383                 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
384
385         Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
386
387         R_Mesh_DestroyVertexDeclarations();
388
389         memset(&gl_state, 0, sizeof(gl_state));
390 }
391
392 static void gl_backend_newmap(void)
393 {
394 }
395
396 static void gl_backend_devicelost(void)
397 {
398         int i, endindex;
399         r_meshbuffer_t *buffer;
400 #ifdef SUPPORTD3D
401         gl_state.d3dvertexbuffer = NULL;
402 #endif
403         switch(vid.renderpath)
404         {
405         case RENDERPATH_GL11:
406         case RENDERPATH_GL13:
407         case RENDERPATH_GL20:
408         case RENDERPATH_SOFT:
409         case RENDERPATH_GLES1:
410         case RENDERPATH_GLES2:
411                 break;
412         case RENDERPATH_D3D9:
413 #ifdef SUPPORTD3D
414                 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
415                 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
416 #endif
417                 break;
418         case RENDERPATH_D3D10:
419                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
420                 break;
421         case RENDERPATH_D3D11:
422                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
423                 break;
424         }
425         endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
426         for (i = 0;i < endindex;i++)
427         {
428                 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
429                 if (!buffer || !buffer->isdynamic)
430                         continue;
431                 switch(vid.renderpath)
432                 {
433                 case RENDERPATH_GL11:
434                 case RENDERPATH_GL13:
435                 case RENDERPATH_GL20:
436                 case RENDERPATH_SOFT:
437                 case RENDERPATH_GLES1:
438                 case RENDERPATH_GLES2:
439                         break;
440                 case RENDERPATH_D3D9:
441 #ifdef SUPPORTD3D
442                         if (buffer->devicebuffer)
443                         {
444                                 if (buffer->isindexbuffer)
445                                         IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
446                                 else
447                                         IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
448                                 buffer->devicebuffer = NULL;
449                         }
450 #endif
451                         break;
452                 case RENDERPATH_D3D10:
453                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
454                         break;
455                 case RENDERPATH_D3D11:
456                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
457                         break;
458                 }
459         }
460 }
461
462 static void gl_backend_devicerestored(void)
463 {
464         switch(vid.renderpath)
465         {
466         case RENDERPATH_GL11:
467         case RENDERPATH_GL13:
468         case RENDERPATH_GL20:
469         case RENDERPATH_SOFT:
470         case RENDERPATH_GLES1:
471         case RENDERPATH_GLES2:
472                 break;
473         case RENDERPATH_D3D9:
474 #ifdef SUPPORTD3D
475                 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
476                 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
477 #endif
478                 break;
479         case RENDERPATH_D3D10:
480                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
481                 break;
482         case RENDERPATH_D3D11:
483                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
484                 break;
485         }
486 }
487
488 void gl_backend_init(void)
489 {
490         int i;
491
492         for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
493         {
494                 polygonelement3s[i * 3 + 0] = 0;
495                 polygonelement3s[i * 3 + 1] = i + 1;
496                 polygonelement3s[i * 3 + 2] = i + 2;
497         }
498         // elements for rendering a series of quads as triangles
499         for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
500         {
501                 quadelement3s[i * 6 + 0] = i * 4;
502                 quadelement3s[i * 6 + 1] = i * 4 + 1;
503                 quadelement3s[i * 6 + 2] = i * 4 + 2;
504                 quadelement3s[i * 6 + 3] = i * 4;
505                 quadelement3s[i * 6 + 4] = i * 4 + 2;
506                 quadelement3s[i * 6 + 5] = i * 4 + 3;
507         }
508
509         for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
510                 polygonelement3i[i] = polygonelement3s[i];
511         for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
512                 quadelement3i[i] = quadelement3s[i];
513
514         Cvar_RegisterVariable(&r_render);
515         Cvar_RegisterVariable(&r_renderview);
516         Cvar_RegisterVariable(&r_waterwarp);
517         Cvar_RegisterVariable(&gl_polyblend);
518         Cvar_RegisterVariable(&v_flipped);
519         Cvar_RegisterVariable(&gl_dither);
520         Cvar_RegisterVariable(&gl_vbo);
521         Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
522         Cvar_RegisterVariable(&gl_vbo_dynamicindex);
523         Cvar_RegisterVariable(&gl_paranoid);
524         Cvar_RegisterVariable(&gl_printcheckerror);
525
526         Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
527         Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
528         Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
529
530         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");
531
532         R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
533 }
534
535 void GL_SetMirrorState(qboolean state);
536
537 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
538 {
539         vec4_t temp;
540         float iw;
541         Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
542         Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
543         iw = 1.0f / out[3];
544         out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
545
546         // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
547         //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
548         out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
549
550         out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
551 }
552
553 void GL_Finish(void)
554 {
555         switch(vid.renderpath)
556         {
557         case RENDERPATH_GL11:
558         case RENDERPATH_GL13:
559         case RENDERPATH_GL20:
560         case RENDERPATH_GLES1:
561         case RENDERPATH_GLES2:
562                 qglFinish();
563                 break;
564         case RENDERPATH_D3D9:
565                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
566                 break;
567         case RENDERPATH_D3D10:
568                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
569                 break;
570         case RENDERPATH_D3D11:
571                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
572                 break;
573         case RENDERPATH_SOFT:
574                 DPSOFTRAST_Finish();
575                 break;
576         }
577 }
578
579 static int bboxedges[12][2] =
580 {
581         // top
582         {0, 1}, // +X
583         {0, 2}, // +Y
584         {1, 3}, // Y, +X
585         {2, 3}, // X, +Y
586         // bottom
587         {4, 5}, // +X
588         {4, 6}, // +Y
589         {5, 7}, // Y, +X
590         {6, 7}, // X, +Y
591         // verticals
592         {0, 4}, // +Z
593         {1, 5}, // X, +Z
594         {2, 6}, // Y, +Z
595         {3, 7}, // XY, +Z
596 };
597
598 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
599 {
600         int i, ix1, iy1, ix2, iy2;
601         float x1, y1, x2, y2;
602         vec4_t v, v2;
603         float vertex[20][3];
604         int j, k;
605         vec4_t plane4f;
606         int numvertices;
607         float corner[8][4];
608         float dist[8];
609         int sign[8];
610         float f;
611
612         scissor[0] = r_refdef.view.viewport.x;
613         scissor[1] = r_refdef.view.viewport.y;
614         scissor[2] = r_refdef.view.viewport.width;
615         scissor[3] = r_refdef.view.viewport.height;
616
617         // if view is inside the box, just say yes it's visible
618         if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
619                 return false;
620
621         x1 = y1 = x2 = y2 = 0;
622
623         // transform all corners that are infront of the nearclip plane
624         VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
625         plane4f[3] = r_refdef.view.frustum[4].dist;
626         numvertices = 0;
627         for (i = 0;i < 8;i++)
628         {
629                 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
630                 dist[i] = DotProduct4(corner[i], plane4f);
631                 sign[i] = dist[i] > 0;
632                 if (!sign[i])
633                 {
634                         VectorCopy(corner[i], vertex[numvertices]);
635                         numvertices++;
636                 }
637         }
638         // if some points are behind the nearclip, add clipped edge points to make
639         // sure that the scissor boundary is complete
640         if (numvertices > 0 && numvertices < 8)
641         {
642                 // add clipped edge points
643                 for (i = 0;i < 12;i++)
644                 {
645                         j = bboxedges[i][0];
646                         k = bboxedges[i][1];
647                         if (sign[j] != sign[k])
648                         {
649                                 f = dist[j] / (dist[j] - dist[k]);
650                                 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
651                                 numvertices++;
652                         }
653                 }
654         }
655
656         // if we have no points to check, it is behind the view plane
657         if (!numvertices)
658                 return true;
659
660         // if we have some points to transform, check what screen area is covered
661         x1 = y1 = x2 = y2 = 0;
662         v[3] = 1.0f;
663         //Con_Printf("%i vertices to transform...\n", numvertices);
664         for (i = 0;i < numvertices;i++)
665         {
666                 VectorCopy(vertex[i], v);
667                 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
668                 //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]);
669                 if (i)
670                 {
671                         if (x1 > v2[0]) x1 = v2[0];
672                         if (x2 < v2[0]) x2 = v2[0];
673                         if (y1 > v2[1]) y1 = v2[1];
674                         if (y2 < v2[1]) y2 = v2[1];
675                 }
676                 else
677                 {
678                         x1 = x2 = v2[0];
679                         y1 = y2 = v2[1];
680                 }
681         }
682
683         // now convert the scissor rectangle to integer screen coordinates
684         ix1 = (int)(x1 - 1.0f);
685         //iy1 = vid.height - (int)(y2 - 1.0f);
686         //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
687         iy1 = (int)(y1 - 1.0f);
688         ix2 = (int)(x2 + 1.0f);
689         //iy2 = vid.height - (int)(y1 + 1.0f);
690         //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
691         iy2 = (int)(y2 + 1.0f);
692         //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
693
694         // clamp it to the screen
695         if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
696         if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
697         if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
698         if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
699
700         // if it is inside out, it's not visible
701         if (ix2 <= ix1 || iy2 <= iy1)
702                 return true;
703
704         // the light area is visible, set up the scissor rectangle
705         scissor[0] = ix1;
706         scissor[1] = iy1;
707         scissor[2] = ix2 - ix1;
708         scissor[3] = iy2 - iy1;
709
710         // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
711         switch(vid.renderpath)
712         {
713         case RENDERPATH_D3D9:
714         case RENDERPATH_D3D10:
715         case RENDERPATH_D3D11:
716                 scissor[1] = vid.height - scissor[1] - scissor[3];
717                 break;
718         case RENDERPATH_GL11:
719         case RENDERPATH_GL13:
720         case RENDERPATH_GL20:
721         case RENDERPATH_SOFT:
722         case RENDERPATH_GLES1:
723         case RENDERPATH_GLES2:
724                 break;
725         }
726
727         return false;
728 }
729
730
731 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
732 {
733         float q[4];
734         float d;
735         float clipPlane[4], v3[3], v4[3];
736         float normal[3];
737
738         // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
739
740         VectorSet(normal, normalx, normaly, normalz);
741         Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
742         VectorScale(normal, -dist, v3);
743         Matrix4x4_Transform(&v->viewmatrix, v3, v4);
744         // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
745         clipPlane[3] = -DotProduct(v4, clipPlane);
746
747 #if 0
748 {
749         // testing code for comparing results
750         float clipPlane2[4];
751         VectorCopy4(clipPlane, clipPlane2);
752         R_EntityMatrix(&identitymatrix);
753         VectorSet(q, normal[0], normal[1], normal[2], -dist);
754         qglClipPlane(GL_CLIP_PLANE0, q);
755         qglGetClipPlane(GL_CLIP_PLANE0, q);
756         VectorCopy4(q, clipPlane);
757 }
758 #endif
759
760         // Calculate the clip-space corner point opposite the clipping plane
761         // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
762         // transform it into camera space by multiplying it
763         // by the inverse of the projection matrix
764         q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
765         q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
766         q[2] = -1.0f;
767         q[3] = (1.0f + m[10]) / m[14];
768
769         // Calculate the scaled plane vector
770         d = 2.0f / DotProduct4(clipPlane, q);
771
772         // Replace the third row of the projection matrix
773         m[2] = clipPlane[0] * d;
774         m[6] = clipPlane[1] * d;
775         m[10] = clipPlane[2] * d + 1.0f;
776         m[14] = clipPlane[3] * d;
777 }
778
779 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)
780 {
781         float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
782         float m[16];
783         memset(v, 0, sizeof(*v));
784         v->type = R_VIEWPORTTYPE_ORTHO;
785         v->cameramatrix = *cameramatrix;
786         v->x = x;
787         v->y = y;
788         v->z = 0;
789         v->width = width;
790         v->height = height;
791         v->depth = 1;
792         memset(m, 0, sizeof(m));
793         m[0]  = 2/(right - left);
794         m[5]  = 2/(top - bottom);
795         m[10] = -2/(zFar - zNear);
796         m[12] = - (right + left)/(right - left);
797         m[13] = - (top + bottom)/(top - bottom);
798         m[14] = - (zFar + zNear)/(zFar - zNear);
799         m[15] = 1;
800         switch(vid.renderpath)
801         {
802         case RENDERPATH_GL11:
803         case RENDERPATH_GL13:
804         case RENDERPATH_GL20:
805         case RENDERPATH_SOFT:
806         case RENDERPATH_GLES1:
807         case RENDERPATH_GLES2:
808                 break;
809         case RENDERPATH_D3D9:
810         case RENDERPATH_D3D10:
811         case RENDERPATH_D3D11:
812                 m[10] = -1/(zFar - zNear);
813                 m[14] = -zNear/(zFar-zNear);
814                 break;
815         }
816         v->screentodepth[0] = -farclip / (farclip - nearclip);
817         v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
818
819         Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
820
821         if (nearplane)
822                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
823
824         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
825
826 #if 0
827         {
828                 vec4_t test1;
829                 vec4_t test2;
830                 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
831                 R_Viewport_TransformToScreen(v, test1, test2);
832                 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
833         }
834 #endif
835 }
836
837 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)
838 {
839         matrix4x4_t tempmatrix, basematrix;
840         float m[16];
841         memset(v, 0, sizeof(*v));
842
843         v->type = R_VIEWPORTTYPE_PERSPECTIVE;
844         v->cameramatrix = *cameramatrix;
845         v->x = x;
846         v->y = y;
847         v->z = 0;
848         v->width = width;
849         v->height = height;
850         v->depth = 1;
851         memset(m, 0, sizeof(m));
852         m[0]  = 1.0 / frustumx;
853         m[5]  = 1.0 / frustumy;
854         m[10] = -(farclip + nearclip) / (farclip - nearclip);
855         m[11] = -1;
856         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
857         v->screentodepth[0] = -farclip / (farclip - nearclip);
858         v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
859
860         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
861         Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
862         Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
863         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
864
865         if (nearplane)
866                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
867
868         if(v_flipped.integer)
869         {
870                 m[0] = -m[0];
871                 m[4] = -m[4];
872                 m[8] = -m[8];
873                 m[12] = -m[12];
874         }
875
876         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
877 }
878
879 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)
880 {
881         matrix4x4_t tempmatrix, basematrix;
882         const float nudge = 1.0 - 1.0 / (1<<23);
883         float m[16];
884         memset(v, 0, sizeof(*v));
885
886         v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
887         v->cameramatrix = *cameramatrix;
888         v->x = x;
889         v->y = y;
890         v->z = 0;
891         v->width = width;
892         v->height = height;
893         v->depth = 1;
894         memset(m, 0, sizeof(m));
895         m[ 0] = 1.0 / frustumx;
896         m[ 5] = 1.0 / frustumy;
897         m[10] = -nudge;
898         m[11] = -1;
899         m[14] = -2 * nearclip * nudge;
900         v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
901         v->screentodepth[1] = m[14] * -0.5;
902
903         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
904         Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
905         Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
906         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
907
908         if (nearplane)
909                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
910
911         if(v_flipped.integer)
912         {
913                 m[0] = -m[0];
914                 m[4] = -m[4];
915                 m[8] = -m[8];
916                 m[12] = -m[12];
917         }
918
919         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
920 }
921
922 float cubeviewmatrix[6][16] =
923 {
924     // standard cubemap projections
925     { // +X
926          0, 0,-1, 0,
927          0,-1, 0, 0,
928         -1, 0, 0, 0,
929          0, 0, 0, 1,
930     },
931     { // -X
932          0, 0, 1, 0,
933          0,-1, 0, 0,
934          1, 0, 0, 0,
935          0, 0, 0, 1,
936     },
937     { // +Y
938          1, 0, 0, 0,
939          0, 0,-1, 0,
940          0, 1, 0, 0,
941          0, 0, 0, 1,
942     },
943     { // -Y
944          1, 0, 0, 0,
945          0, 0, 1, 0,
946          0,-1, 0, 0,
947          0, 0, 0, 1,
948     },
949     { // +Z
950          1, 0, 0, 0,
951          0,-1, 0, 0,
952          0, 0,-1, 0,
953          0, 0, 0, 1,
954     },
955     { // -Z
956         -1, 0, 0, 0,
957          0,-1, 0, 0,
958          0, 0, 1, 0,
959          0, 0, 0, 1,
960     },
961 };
962 float rectviewmatrix[6][16] =
963 {
964     // sign-preserving cubemap projections
965     { // +X
966          0, 0,-1, 0,
967          0, 1, 0, 0,
968          1, 0, 0, 0,
969          0, 0, 0, 1,
970     },
971     { // -X
972          0, 0, 1, 0,
973          0, 1, 0, 0,
974          1, 0, 0, 0,
975          0, 0, 0, 1,
976     },
977     { // +Y
978          1, 0, 0, 0,
979          0, 0,-1, 0,
980          0, 1, 0, 0,
981          0, 0, 0, 1,
982     },
983     { // -Y
984          1, 0, 0, 0,
985          0, 0, 1, 0,
986          0, 1, 0, 0,
987          0, 0, 0, 1,
988     },
989     { // +Z
990          1, 0, 0, 0,
991          0, 1, 0, 0,
992          0, 0,-1, 0,
993          0, 0, 0, 1,
994     },
995     { // -Z
996          1, 0, 0, 0,
997          0, 1, 0, 0,
998          0, 0, 1, 0,
999          0, 0, 0, 1,
1000     },
1001 };
1002
1003 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
1004 {
1005         matrix4x4_t tempmatrix, basematrix;
1006         float m[16];
1007         memset(v, 0, sizeof(*v));
1008         v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1009         v->cameramatrix = *cameramatrix;
1010         v->width = size;
1011         v->height = size;
1012         v->depth = 1;
1013         memset(m, 0, sizeof(m));
1014         m[0] = m[5] = 1.0f;
1015         m[10] = -(farclip + nearclip) / (farclip - nearclip);
1016         m[11] = -1;
1017         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1018
1019         Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
1020         Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1021         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1022
1023         if (nearplane)
1024                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1025
1026         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1027 }
1028
1029 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)
1030 {
1031         matrix4x4_t tempmatrix, basematrix;
1032         float m[16];
1033         memset(v, 0, sizeof(*v));
1034         v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1035         v->cameramatrix = *cameramatrix;
1036         v->x = (side & 1) * size;
1037         v->y = (side >> 1) * size;
1038         v->width = size;
1039         v->height = size;
1040         v->depth = 1;
1041         memset(m, 0, sizeof(m));
1042         m[0] = m[5] = 1.0f * ((float)size - border) / size;
1043         m[10] = -(farclip + nearclip) / (farclip - nearclip);
1044         m[11] = -1;
1045         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1046
1047         Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1048         Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1049         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1050
1051         switch(vid.renderpath)
1052         {
1053         case RENDERPATH_GL20:
1054         case RENDERPATH_GL13:
1055         case RENDERPATH_GL11:
1056         case RENDERPATH_SOFT:
1057         case RENDERPATH_GLES1:
1058         case RENDERPATH_GLES2:
1059                 break;
1060         case RENDERPATH_D3D9:
1061                 m[5] *= -1;
1062                 break;
1063         case RENDERPATH_D3D10:
1064                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1065                 break;
1066         case RENDERPATH_D3D11:
1067                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1068                 break;
1069         }
1070
1071         if (nearplane)
1072                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1073
1074         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1075 }
1076
1077 void R_SetViewport(const r_viewport_t *v)
1078 {
1079         float m[16];
1080         gl_viewport = *v;
1081
1082         // FIXME: v_flipped_state is evil, this probably breaks somewhere
1083         GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1084
1085         // copy over the matrices to our state
1086         gl_viewmatrix = v->viewmatrix;
1087         gl_projectionmatrix = v->projectmatrix;
1088
1089         switch(vid.renderpath)
1090         {
1091         case RENDERPATH_GL13:
1092         case RENDERPATH_GL11:
1093         case RENDERPATH_GLES1:
1094                 CHECKGLERROR
1095                 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1096                 // Load the projection matrix into OpenGL
1097                 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1098                 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1099                 qglLoadMatrixf(m);CHECKGLERROR
1100                 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1101                 break;
1102         case RENDERPATH_D3D9:
1103 #ifdef SUPPORTD3D
1104                 {
1105                         D3DVIEWPORT9 d3dviewport;
1106                         d3dviewport.X = gl_viewport.x;
1107                         d3dviewport.Y = gl_viewport.y;
1108                         d3dviewport.Width = gl_viewport.width;
1109                         d3dviewport.Height = gl_viewport.height;
1110                         d3dviewport.MinZ = gl_state.depthrange[0];
1111                         d3dviewport.MaxZ = gl_state.depthrange[1];
1112                         IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1113                 }
1114 #endif
1115                 break;
1116         case RENDERPATH_D3D10:
1117                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1118                 break;
1119         case RENDERPATH_D3D11:
1120                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1121                 break;
1122         case RENDERPATH_SOFT:
1123                 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1124                 break;
1125         case RENDERPATH_GL20:
1126         case RENDERPATH_GLES2:
1127                 CHECKGLERROR
1128                 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1129                 break;
1130         }
1131
1132         // force an update of the derived matrices
1133         gl_modelmatrixchanged = true;
1134         R_EntityMatrix(&gl_modelmatrix);
1135 }
1136
1137 void R_GetViewport(r_viewport_t *v)
1138 {
1139         *v = gl_viewport;
1140 }
1141
1142 static void GL_BindVBO(int bufferobject)
1143 {
1144         if (gl_state.vertexbufferobject != bufferobject)
1145         {
1146                 gl_state.vertexbufferobject = bufferobject;
1147                 CHECKGLERROR
1148                 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1149         }
1150 }
1151
1152 static void GL_BindEBO(int bufferobject)
1153 {
1154         if (gl_state.elementbufferobject != bufferobject)
1155         {
1156                 gl_state.elementbufferobject = bufferobject;
1157                 CHECKGLERROR
1158                 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1159         }
1160 }
1161
1162 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1163 {
1164         int temp;
1165         switch(vid.renderpath)
1166         {
1167         case RENDERPATH_GL11:
1168         case RENDERPATH_GL13:
1169         case RENDERPATH_GL20:
1170         case RENDERPATH_GLES1:
1171         case RENDERPATH_GLES2:
1172                 if (!vid.support.ext_framebuffer_object)
1173                         return 0;
1174                 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1175                 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1176                 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1177                 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1178                 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1179                 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1180                 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1181                 return temp;
1182         case RENDERPATH_D3D9:
1183         case RENDERPATH_D3D10:
1184         case RENDERPATH_D3D11:
1185                 return 1;
1186         case RENDERPATH_SOFT:
1187                 return 1;
1188         }
1189         return 0;
1190 }
1191
1192 void R_Mesh_DestroyFramebufferObject(int fbo)
1193 {
1194         switch(vid.renderpath)
1195         {
1196         case RENDERPATH_GL11:
1197         case RENDERPATH_GL13:
1198         case RENDERPATH_GL20:
1199         case RENDERPATH_GLES1:
1200         case RENDERPATH_GLES2:
1201                 if (fbo)
1202                         qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1203                 break;
1204         case RENDERPATH_D3D9:
1205         case RENDERPATH_D3D10:
1206         case RENDERPATH_D3D11:
1207                 break;
1208         case RENDERPATH_SOFT:
1209                 break;
1210         }
1211 }
1212
1213 #ifdef SUPPORTD3D
1214 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1215 {
1216 // LordHavoc: for some weird reason the redundant SetDepthStencilSurface calls are necessary (otherwise the lights fail depth test, as if they were using the shadowmap depth surface and render target still)
1217         if (gl_state.d3drt_depthsurface == depthsurface && gl_state.d3drt_colorsurfaces[0] == colorsurface0 && gl_state.d3drt_colorsurfaces[1] == colorsurface1 && gl_state.d3drt_colorsurfaces[2] == colorsurface2 && gl_state.d3drt_colorsurfaces[3] == colorsurface3)
1218                 return;
1219
1220         gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1221         if (gl_state.d3drt_depthsurface != depthsurface)
1222         {
1223                 gl_state.d3drt_depthsurface = depthsurface;
1224                 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1225         }
1226         if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1227         {
1228                 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1229                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1230         }
1231         if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1232         {
1233                 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1234                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1235         }
1236         if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1237         {
1238                 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1239                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1240         }
1241         if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1242         {
1243                 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1244                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1245         }
1246 }
1247 #endif
1248
1249 void R_Mesh_ResetRenderTargets(void)
1250 {
1251         switch(vid.renderpath)
1252         {
1253         case RENDERPATH_GL11:
1254         case RENDERPATH_GL13:
1255         case RENDERPATH_GL20:
1256         case RENDERPATH_GLES1:
1257         case RENDERPATH_GLES2:
1258                 if (gl_state.framebufferobject)
1259                 {
1260                         gl_state.framebufferobject = 0;
1261                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1262                 }
1263                 break;
1264         case RENDERPATH_D3D9:
1265 #ifdef SUPPORTD3D
1266                 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1267 #endif
1268                 break;
1269         case RENDERPATH_D3D10:
1270                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1271                 break;
1272         case RENDERPATH_D3D11:
1273                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1274                 break;
1275         case RENDERPATH_SOFT:
1276                 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1277                 break;
1278         }
1279 }
1280
1281 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1282 {
1283         unsigned int i;
1284         unsigned int j;
1285         rtexture_t *textures[5];
1286         Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1287         textures[4] = depthtexture;
1288         // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1289         for (j = 0;j < 5;j++)
1290                 if (textures[j])
1291                         for (i = 0;i < vid.teximageunits;i++)
1292                                 if (gl_state.units[i].texture == textures[j])
1293                                         R_Mesh_TexBind(i, NULL);
1294         // set up framebuffer object or render targets for the active rendering API
1295         switch(vid.renderpath)
1296         {
1297         case RENDERPATH_GL11:
1298         case RENDERPATH_GL13:
1299         case RENDERPATH_GL20:
1300         case RENDERPATH_GLES1:
1301         case RENDERPATH_GLES2:
1302                 if (gl_state.framebufferobject != fbo)
1303                 {
1304                         gl_state.framebufferobject = fbo;
1305                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1306                 }
1307                 break;
1308         case RENDERPATH_D3D9:
1309 #ifdef SUPPORTD3D
1310                 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1311                 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1312                 if (fbo)
1313                 {
1314                         IDirect3DSurface9 *colorsurfaces[4];
1315                         for (i = 0;i < 4;i++)
1316                         {
1317                                 colorsurfaces[i] = NULL;
1318                                 if (textures[i])
1319                                         IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1320                         }
1321                         // set the render targets for real
1322                         R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1323                         // release the texture surface levels (they won't be lost while bound...)
1324                         for (i = 0;i < 4;i++)
1325                                 if (textures[i])
1326                                         IDirect3DSurface9_Release(colorsurfaces[i]);
1327                 }
1328                 else
1329                         R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1330 #endif
1331                 break;
1332         case RENDERPATH_D3D10:
1333                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1334                 break;
1335         case RENDERPATH_D3D11:
1336                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1337                 break;
1338         case RENDERPATH_SOFT:
1339                 if (fbo)
1340                 {
1341                         int width, height;
1342                         unsigned int *pointers[5];
1343                         memset(pointers, 0, sizeof(pointers));
1344                         for (i = 0;i < 5;i++)
1345                                 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1346                         width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1347                         height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1348                         DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1349                 }
1350                 else
1351                         DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1352                 break;
1353         }
1354 }
1355
1356 #ifdef SUPPORTD3D
1357 static int d3dcmpforglfunc(int f)
1358 {
1359         switch(f)
1360         {
1361         case GL_NEVER: return D3DCMP_NEVER;
1362         case GL_LESS: return D3DCMP_LESS;
1363         case GL_EQUAL: return D3DCMP_EQUAL;
1364         case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1365         case GL_GREATER: return D3DCMP_GREATER;
1366         case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1367         case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1368         case GL_ALWAYS: return D3DCMP_ALWAYS;
1369         default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1370         }
1371 }
1372
1373 static int d3dstencilopforglfunc(int f)
1374 {
1375         switch(f)
1376         {
1377         case GL_KEEP: return D3DSTENCILOP_KEEP;
1378         case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1379         case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1380         default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1381         }
1382 }
1383 #endif
1384
1385 extern cvar_t r_transparent_alphatocoverage;
1386
1387 static void GL_Backend_ResetState(void)
1388 {
1389         unsigned int i;
1390         gl_state.active = true;
1391         gl_state.depthtest = true;
1392         gl_state.alphatest = false;
1393         gl_state.alphafunc = GL_GEQUAL;
1394         gl_state.alphafuncvalue = 0.5f;
1395         gl_state.alphatocoverage = false;
1396         gl_state.blendfunc1 = GL_ONE;
1397         gl_state.blendfunc2 = GL_ZERO;
1398         gl_state.blend = false;
1399         gl_state.depthmask = GL_TRUE;
1400         gl_state.colormask = 15;
1401         gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1402         gl_state.lockrange_first = 0;
1403         gl_state.lockrange_count = 0;
1404         gl_state.cullface = GL_FRONT;
1405         gl_state.cullfaceenable = false;
1406         gl_state.polygonoffset[0] = 0;
1407         gl_state.polygonoffset[1] = 0;
1408         gl_state.framebufferobject = 0;
1409         gl_state.depthfunc = GL_LEQUAL;
1410
1411         switch(vid.renderpath)
1412         {
1413         case RENDERPATH_D3D9:
1414 #ifdef SUPPORTD3D
1415                 {
1416                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1417                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1418                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1419                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1420                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1421                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1422                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1423                 }
1424 #endif
1425                 break;
1426         case RENDERPATH_D3D10:
1427                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1428                 break;
1429         case RENDERPATH_D3D11:
1430                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1431                 break;
1432         case RENDERPATH_GL11:
1433         case RENDERPATH_GL13:
1434         case RENDERPATH_GLES1:
1435                 CHECKGLERROR
1436
1437                 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1438                 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1439                 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1440                 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1441                 qglDisable(GL_BLEND);CHECKGLERROR
1442                 qglCullFace(gl_state.cullface);CHECKGLERROR
1443                 qglDisable(GL_CULL_FACE);CHECKGLERROR
1444                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1445                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1446                 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1447                 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1448
1449                 if (vid.support.arb_vertex_buffer_object)
1450                 {
1451                         qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1452                         qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1453                 }
1454
1455                 if (vid.support.ext_framebuffer_object)
1456                 {
1457                         //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1458                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1459                 }
1460
1461                 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1462                 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1463
1464                 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1465                 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1466                 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1467
1468                 if (vid.support.ext_framebuffer_object)
1469                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1470
1471                 gl_state.unit = MAX_TEXTUREUNITS;
1472                 gl_state.clientunit = MAX_TEXTUREUNITS;
1473                 for (i = 0;i < vid.texunits;i++)
1474                 {
1475                         GL_ActiveTexture(i);
1476                         GL_ClientActiveTexture(i);
1477                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1478                         qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1479                         if (vid.support.ext_texture_3d)
1480                         {
1481                                 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1482                                 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1483                         }
1484                         if (vid.support.arb_texture_cube_map)
1485                         {
1486                                 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1487                                 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1488                         }
1489                         GL_BindVBO(0);
1490                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1491                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1492                         qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1493                         qglLoadIdentity();CHECKGLERROR
1494                         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1495                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1496                 }
1497                 CHECKGLERROR
1498                 break;
1499         case RENDERPATH_SOFT:
1500                 DPSOFTRAST_ColorMask(1,1,1,1);
1501                 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1502                 DPSOFTRAST_CullFace(gl_state.cullface);
1503                 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1504                 DPSOFTRAST_DepthMask(gl_state.depthmask);
1505                 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1506                 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1507                 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1508                 break;
1509         case RENDERPATH_GL20:
1510         case RENDERPATH_GLES2:
1511                 CHECKGLERROR
1512                 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1513                 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1514                 qglDisable(GL_BLEND);CHECKGLERROR
1515                 qglCullFace(gl_state.cullface);CHECKGLERROR
1516                 qglDisable(GL_CULL_FACE);CHECKGLERROR
1517                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1518                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1519                 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1520                 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1521                 if (vid.support.arb_vertex_buffer_object)
1522                 {
1523                         qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1524                         qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1525                 }
1526                 if (vid.support.ext_framebuffer_object)
1527                         qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1528                 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1529                 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1530                 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1531                 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1532                 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1533                 gl_state.unit = MAX_TEXTUREUNITS;
1534                 gl_state.clientunit = MAX_TEXTUREUNITS;
1535                 for (i = 0;i < vid.teximageunits;i++)
1536                 {
1537                         GL_ActiveTexture(i);
1538                         qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1539                         if (vid.support.ext_texture_3d)
1540                         {
1541                                 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1542                         }
1543                         if (vid.support.arb_texture_cube_map)
1544                         {
1545                                 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1546                         }
1547                 }
1548                 for (i = 0;i < vid.texarrayunits;i++)
1549                 {
1550                         GL_BindVBO(0);
1551                         qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1552                         qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1553                 }
1554                 CHECKGLERROR
1555                 break;
1556         }
1557 }
1558
1559 void GL_ActiveTexture(unsigned int num)
1560 {
1561         if (gl_state.unit != num)
1562         {
1563                 gl_state.unit = num;
1564                 switch(vid.renderpath)
1565                 {
1566                 case RENDERPATH_GL11:
1567                 case RENDERPATH_GL13:
1568                 case RENDERPATH_GL20:
1569                 case RENDERPATH_GLES1:
1570                 case RENDERPATH_GLES2:
1571                         if (qglActiveTexture)
1572                         {
1573                                 CHECKGLERROR
1574                                 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1575                                 CHECKGLERROR
1576                         }
1577                         break;
1578                 case RENDERPATH_D3D9:
1579                 case RENDERPATH_D3D10:
1580                 case RENDERPATH_D3D11:
1581                         break;
1582                 case RENDERPATH_SOFT:
1583                         break;
1584                 }
1585         }
1586 }
1587
1588 void GL_ClientActiveTexture(unsigned int num)
1589 {
1590         if (gl_state.clientunit != num)
1591         {
1592                 gl_state.clientunit = num;
1593                 switch(vid.renderpath)
1594                 {
1595                 case RENDERPATH_GL11:
1596                 case RENDERPATH_GL13:
1597                 case RENDERPATH_GLES1:
1598                         if (qglActiveTexture)
1599                         {
1600                                 CHECKGLERROR
1601                                 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1602                                 CHECKGLERROR
1603                         }
1604                         break;
1605                 case RENDERPATH_D3D9:
1606                 case RENDERPATH_D3D10:
1607                 case RENDERPATH_D3D11:
1608                         break;
1609                 case RENDERPATH_SOFT:
1610                         break;
1611                 case RENDERPATH_GL20:
1612                 case RENDERPATH_GLES2:
1613                         break;
1614                 }
1615         }
1616 }
1617
1618 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1619 {
1620         if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1621         {
1622                 qboolean blendenable;
1623                 gl_state.blendfunc1 = blendfunc1;
1624                 gl_state.blendfunc2 = blendfunc2;
1625                 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1626                 switch(vid.renderpath)
1627                 {
1628                 case RENDERPATH_GL11:
1629                 case RENDERPATH_GL13:
1630                 case RENDERPATH_GL20:
1631                 case RENDERPATH_GLES1:
1632                 case RENDERPATH_GLES2:
1633                         CHECKGLERROR
1634                         qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1635                         if (gl_state.blend != blendenable)
1636                         {
1637                                 gl_state.blend = blendenable;
1638                                 if (!gl_state.blend)
1639                                 {
1640                                         qglDisable(GL_BLEND);CHECKGLERROR
1641                                 }
1642                                 else
1643                                 {
1644                                         qglEnable(GL_BLEND);CHECKGLERROR
1645                                 }
1646                         }
1647                         break;
1648                 case RENDERPATH_D3D9:
1649 #ifdef SUPPORTD3D
1650                         {
1651                                 int i;
1652                                 int glblendfunc[2];
1653                                 D3DBLEND d3dblendfunc[2];
1654                                 glblendfunc[0] = gl_state.blendfunc1;
1655                                 glblendfunc[1] = gl_state.blendfunc2;
1656                                 for (i = 0;i < 2;i++)
1657                                 {
1658                                         switch(glblendfunc[i])
1659                                         {
1660                                         case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1661                                         case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1662                                         case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1663                                         case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1664                                         case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1665                                         case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1666                                         case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1667                                         case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1668                                         case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1669                                         case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1670                                         }
1671                                 }
1672                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1673                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1674                                 if (gl_state.blend != blendenable)
1675                                 {
1676                                         gl_state.blend = blendenable;
1677                                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1678                                 }
1679                         }
1680 #endif
1681                         break;
1682                 case RENDERPATH_D3D10:
1683                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1684                         break;
1685                 case RENDERPATH_D3D11:
1686                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1687                         break;
1688                 case RENDERPATH_SOFT:
1689                         DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1690                         break;
1691                 }
1692         }
1693 }
1694
1695 void GL_DepthMask(int state)
1696 {
1697         if (gl_state.depthmask != state)
1698         {
1699                 gl_state.depthmask = state;
1700                 switch(vid.renderpath)
1701                 {
1702                 case RENDERPATH_GL11:
1703                 case RENDERPATH_GL13:
1704                 case RENDERPATH_GL20:
1705                 case RENDERPATH_GLES1:
1706                 case RENDERPATH_GLES2:
1707                         CHECKGLERROR
1708                         qglDepthMask(gl_state.depthmask);CHECKGLERROR
1709                         break;
1710                 case RENDERPATH_D3D9:
1711 #ifdef SUPPORTD3D
1712                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1713 #endif
1714                         break;
1715                 case RENDERPATH_D3D10:
1716                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1717                         break;
1718                 case RENDERPATH_D3D11:
1719                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1720                         break;
1721                 case RENDERPATH_SOFT:
1722                         DPSOFTRAST_DepthMask(gl_state.depthmask);
1723                         break;
1724                 }
1725         }
1726 }
1727
1728 void GL_DepthTest(int state)
1729 {
1730         if (gl_state.depthtest != state)
1731         {
1732                 gl_state.depthtest = state;
1733                 switch(vid.renderpath)
1734                 {
1735                 case RENDERPATH_GL11:
1736                 case RENDERPATH_GL13:
1737                 case RENDERPATH_GL20:
1738                 case RENDERPATH_GLES1:
1739                 case RENDERPATH_GLES2:
1740                         CHECKGLERROR
1741                         if (gl_state.depthtest)
1742                         {
1743                                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1744                         }
1745                         else
1746                         {
1747                                 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1748                         }
1749                         break;
1750                 case RENDERPATH_D3D9:
1751 #ifdef SUPPORTD3D
1752                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1753 #endif
1754                         break;
1755                 case RENDERPATH_D3D10:
1756                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1757                         break;
1758                 case RENDERPATH_D3D11:
1759                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1760                         break;
1761                 case RENDERPATH_SOFT:
1762                         DPSOFTRAST_DepthTest(gl_state.depthtest);
1763                         break;
1764                 }
1765         }
1766 }
1767
1768 void GL_DepthFunc(int state)
1769 {
1770         if (gl_state.depthfunc != state)
1771         {
1772                 gl_state.depthfunc = state;
1773                 switch(vid.renderpath)
1774                 {
1775                 case RENDERPATH_GL11:
1776                 case RENDERPATH_GL13:
1777                 case RENDERPATH_GL20:
1778                 case RENDERPATH_GLES1:
1779                 case RENDERPATH_GLES2:
1780                         CHECKGLERROR
1781                         qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1782                         break;
1783                 case RENDERPATH_D3D9:
1784 #ifdef SUPPORTD3D
1785                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1786 #endif
1787                         break;
1788                 case RENDERPATH_D3D10:
1789                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1790                         break;
1791                 case RENDERPATH_D3D11:
1792                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1793                         break;
1794                 case RENDERPATH_SOFT:
1795                         DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1796                         break;
1797                 }
1798         }
1799 }
1800
1801 void GL_DepthRange(float nearfrac, float farfrac)
1802 {
1803         if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1804         {
1805                 gl_state.depthrange[0] = nearfrac;
1806                 gl_state.depthrange[1] = farfrac;
1807                 switch(vid.renderpath)
1808                 {
1809                 case RENDERPATH_GL11:
1810                 case RENDERPATH_GL13:
1811                 case RENDERPATH_GL20:
1812                 case RENDERPATH_GLES1:
1813                 case RENDERPATH_GLES2:
1814                         qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1815                         break;
1816                 case RENDERPATH_D3D9:
1817 #ifdef SUPPORTD3D
1818                         {
1819                                 D3DVIEWPORT9 d3dviewport;
1820                                 d3dviewport.X = gl_viewport.x;
1821                                 d3dviewport.Y = gl_viewport.y;
1822                                 d3dviewport.Width = gl_viewport.width;
1823                                 d3dviewport.Height = gl_viewport.height;
1824                                 d3dviewport.MinZ = gl_state.depthrange[0];
1825                                 d3dviewport.MaxZ = gl_state.depthrange[1];
1826                                 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1827                         }
1828 #endif
1829                         break;
1830                 case RENDERPATH_D3D10:
1831                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832                         break;
1833                 case RENDERPATH_D3D11:
1834                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835                         break;
1836                 case RENDERPATH_SOFT:
1837                         DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1838                         break;
1839                 }
1840         }
1841 }
1842
1843 void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int frontzfail, int frontzpass, int backfail, int backzfail, int backzpass, int frontcompare, int backcompare, int comparereference, int comparemask)
1844 {
1845         switch (vid.renderpath)
1846         {
1847         case RENDERPATH_GL11:
1848         case RENDERPATH_GL13:
1849         case RENDERPATH_GL20:
1850         case RENDERPATH_GLES1:
1851         case RENDERPATH_GLES2:
1852                 CHECKGLERROR
1853                 if (enable)
1854                 {
1855                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1856                 }
1857                 else
1858                 {
1859                         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1860                 }
1861                 if (vid.support.ati_separate_stencil)
1862                 {
1863                         qglStencilMask(writemask);CHECKGLERROR
1864                         qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1865                         qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1866                         qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1867                 }
1868                 else if (vid.support.ext_stencil_two_side)
1869                 {
1870                         qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1871                         qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1872                         qglStencilMask(writemask);CHECKGLERROR
1873                         qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1874                         qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1875                         qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1876                         qglStencilMask(writemask);CHECKGLERROR
1877                         qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1878                         qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1879                 }
1880                 break;
1881         case RENDERPATH_D3D9:
1882 #ifdef SUPPORTD3D
1883                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1884                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1885                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1886                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1887                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1888                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1889                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1890                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1891                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1892                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1893                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1894                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1895                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1896 #endif
1897                 break;
1898         case RENDERPATH_D3D10:
1899                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1900                 break;
1901         case RENDERPATH_D3D11:
1902                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1903                 break;
1904         case RENDERPATH_SOFT:
1905                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1906                 break;
1907         }
1908 }
1909
1910 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1911 {
1912         switch (vid.renderpath)
1913         {
1914         case RENDERPATH_GL11:
1915         case RENDERPATH_GL13:
1916         case RENDERPATH_GL20:
1917         case RENDERPATH_GLES1:
1918         case RENDERPATH_GLES2:
1919                 CHECKGLERROR
1920                 if (enable)
1921                 {
1922                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1923                 }
1924                 else
1925                 {
1926                         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1927                 }
1928                 if (vid.support.ext_stencil_two_side)
1929                 {
1930                         qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1931                 }
1932                 qglStencilMask(writemask);CHECKGLERROR
1933                 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1934                 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1935                 CHECKGLERROR
1936                 break;
1937         case RENDERPATH_D3D9:
1938 #ifdef SUPPORTD3D
1939                 if (vid.support.ati_separate_stencil)
1940                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1941                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1942                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1943                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1944                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1945                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1946                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1947                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1948                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1949 #endif
1950                 break;
1951         case RENDERPATH_D3D10:
1952                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953                 break;
1954         case RENDERPATH_D3D11:
1955                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_SOFT:
1958                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         }
1961 }
1962
1963 void GL_PolygonOffset(float planeoffset, float depthoffset)
1964 {
1965         if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1966         {
1967                 gl_state.polygonoffset[0] = planeoffset;
1968                 gl_state.polygonoffset[1] = depthoffset;
1969                 switch(vid.renderpath)
1970                 {
1971                 case RENDERPATH_GL11:
1972                 case RENDERPATH_GL13:
1973                 case RENDERPATH_GL20:
1974                 case RENDERPATH_GLES1:
1975                 case RENDERPATH_GLES2:
1976                         qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1977                         break;
1978                 case RENDERPATH_D3D9:
1979 #ifdef SUPPORTD3D
1980                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1981                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1982 #endif
1983                         break;
1984                 case RENDERPATH_D3D10:
1985                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                         break;
1987                 case RENDERPATH_D3D11:
1988                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989                         break;
1990                 case RENDERPATH_SOFT:
1991                         DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1992                         break;
1993                 }
1994         }
1995 }
1996
1997 void GL_SetMirrorState(qboolean state)
1998 {
1999         if (v_flipped_state != state)
2000         {
2001                 v_flipped_state = state;
2002                 if (gl_state.cullface == GL_BACK)
2003                         gl_state.cullface = GL_FRONT;
2004                 else if (gl_state.cullface == GL_FRONT)
2005                         gl_state.cullface = GL_BACK;
2006                 else
2007                         return;
2008                 switch(vid.renderpath)
2009                 {
2010                 case RENDERPATH_GL11:
2011                 case RENDERPATH_GL13:
2012                 case RENDERPATH_GL20:
2013                 case RENDERPATH_GLES1:
2014                 case RENDERPATH_GLES2:
2015                         qglCullFace(gl_state.cullface);CHECKGLERROR
2016                         break;
2017                 case RENDERPATH_D3D9:
2018 #ifdef SUPPORTD3D
2019                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2020 #endif
2021                         break;
2022                 case RENDERPATH_D3D10:
2023                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2024                         break;
2025                 case RENDERPATH_D3D11:
2026                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027                         break;
2028                 case RENDERPATH_SOFT:
2029                         DPSOFTRAST_CullFace(gl_state.cullface);
2030                         break;
2031                 }
2032         }
2033 }
2034
2035 void GL_CullFace(int state)
2036 {
2037         if(v_flipped_state)
2038         {
2039                 if(state == GL_FRONT)
2040                         state = GL_BACK;
2041                 else if(state == GL_BACK)
2042                         state = GL_FRONT;
2043         }
2044
2045         switch(vid.renderpath)
2046         {
2047         case RENDERPATH_GL11:
2048         case RENDERPATH_GL13:
2049         case RENDERPATH_GL20:
2050         case RENDERPATH_GLES1:
2051         case RENDERPATH_GLES2:
2052                 CHECKGLERROR
2053
2054                 if (state != GL_NONE)
2055                 {
2056                         if (!gl_state.cullfaceenable)
2057                         {
2058                                 gl_state.cullfaceenable = true;
2059                                 qglEnable(GL_CULL_FACE);CHECKGLERROR
2060                         }
2061                         if (gl_state.cullface != state)
2062                         {
2063                                 gl_state.cullface = state;
2064                                 qglCullFace(gl_state.cullface);CHECKGLERROR
2065                         }
2066                 }
2067                 else
2068                 {
2069                         if (gl_state.cullfaceenable)
2070                         {
2071                                 gl_state.cullfaceenable = false;
2072                                 qglDisable(GL_CULL_FACE);CHECKGLERROR
2073                         }
2074                 }
2075                 break;
2076         case RENDERPATH_D3D9:
2077 #ifdef SUPPORTD3D
2078                 if (gl_state.cullface != state)
2079                 {
2080                         gl_state.cullface = state;
2081                         switch(gl_state.cullface)
2082                         {
2083                         case GL_NONE:
2084                                 gl_state.cullfaceenable = false;
2085                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2086                                 break;
2087                         case GL_FRONT:
2088                                 gl_state.cullfaceenable = true;
2089                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2090                                 break;
2091                         case GL_BACK:
2092                                 gl_state.cullfaceenable = true;
2093                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2094                                 break;
2095                         }
2096                 }
2097 #endif
2098                 break;
2099         case RENDERPATH_D3D10:
2100                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2101                 break;
2102         case RENDERPATH_D3D11:
2103                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2104                 break;
2105         case RENDERPATH_SOFT:
2106                 if (gl_state.cullface != state)
2107                 {
2108                         gl_state.cullface = state;
2109                         gl_state.cullfaceenable = state != GL_NONE ? true : false;
2110                         DPSOFTRAST_CullFace(gl_state.cullface);
2111                 }
2112                 break;
2113         }
2114 }
2115
2116 void GL_AlphaTest(int state)
2117 {
2118         if (gl_state.alphatest != state)
2119         {
2120                 gl_state.alphatest = state;
2121                 switch(vid.renderpath)
2122                 {
2123                 case RENDERPATH_GL11:
2124                 case RENDERPATH_GL13:
2125                 case RENDERPATH_GLES1:
2126                         // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2127                         CHECKGLERROR
2128                         if (gl_state.alphatest)
2129                         {
2130                                 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2131                         }
2132                         else
2133                         {
2134                                 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2135                         }
2136                         break;
2137                 case RENDERPATH_D3D9:
2138                 case RENDERPATH_D3D10:
2139                 case RENDERPATH_D3D11:
2140                 case RENDERPATH_SOFT:
2141                 case RENDERPATH_GL20:
2142                 case RENDERPATH_GLES2:
2143                         break;
2144                 }
2145         }
2146 }
2147
2148 void GL_AlphaToCoverage(qboolean state)
2149 {
2150         if (gl_state.alphatocoverage != state)
2151         {
2152                 gl_state.alphatocoverage = state;
2153                 switch(vid.renderpath)
2154                 {
2155                 case RENDERPATH_GL11:
2156                 case RENDERPATH_GL13:
2157                 case RENDERPATH_GLES1:
2158                 case RENDERPATH_GLES2:
2159                 case RENDERPATH_D3D9:
2160                 case RENDERPATH_D3D10:
2161                 case RENDERPATH_D3D11:
2162                 case RENDERPATH_SOFT:
2163                         break;
2164                 case RENDERPATH_GL20:
2165                         // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
2166                         CHECKGLERROR
2167                         if (gl_state.alphatocoverage)
2168                         {
2169                                 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2170 //                              qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2171                         }
2172                         else
2173                         {
2174                                 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2175 //                              qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2176                         }
2177                         break;
2178                 }
2179         }
2180 }
2181
2182 void GL_ColorMask(int r, int g, int b, int a)
2183 {
2184         // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2185         int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2186         if (gl_state.colormask != state)
2187         {
2188                 gl_state.colormask = state;
2189                 switch(vid.renderpath)
2190                 {
2191                 case RENDERPATH_GL11:
2192                 case RENDERPATH_GL13:
2193                 case RENDERPATH_GL20:
2194                 case RENDERPATH_GLES1:
2195                 case RENDERPATH_GLES2:
2196                         CHECKGLERROR
2197                         qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2198                         break;
2199                 case RENDERPATH_D3D9:
2200 #ifdef SUPPORTD3D
2201                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2202 #endif
2203                         break;
2204                 case RENDERPATH_D3D10:
2205                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2206                         break;
2207                 case RENDERPATH_D3D11:
2208                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2209                         break;
2210                 case RENDERPATH_SOFT:
2211                         DPSOFTRAST_ColorMask(r, g, b, a);
2212                         break;
2213                 }
2214         }
2215 }
2216
2217 void GL_Color(float cr, float cg, float cb, float ca)
2218 {
2219         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)
2220         {
2221                 gl_state.color4f[0] = cr;
2222                 gl_state.color4f[1] = cg;
2223                 gl_state.color4f[2] = cb;
2224                 gl_state.color4f[3] = ca;
2225                 switch(vid.renderpath)
2226                 {
2227                 case RENDERPATH_GL11:
2228                 case RENDERPATH_GL13:
2229                 case RENDERPATH_GLES1:
2230                         CHECKGLERROR
2231                         qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2232                         CHECKGLERROR
2233                         break;
2234                 case RENDERPATH_D3D9:
2235                 case RENDERPATH_D3D10:
2236                 case RENDERPATH_D3D11:
2237                         // no equivalent in D3D
2238                         break;
2239                 case RENDERPATH_SOFT:
2240                         DPSOFTRAST_Color4f(cr, cg, cb, ca);
2241                         break;
2242                 case RENDERPATH_GL20:
2243                 case RENDERPATH_GLES2:
2244                         qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2245                         break;
2246                 }
2247         }
2248 }
2249
2250 void GL_Scissor (int x, int y, int width, int height)
2251 {
2252         switch(vid.renderpath)
2253         {
2254         case RENDERPATH_GL11:
2255         case RENDERPATH_GL13:
2256         case RENDERPATH_GL20:
2257         case RENDERPATH_GLES1:
2258         case RENDERPATH_GLES2:
2259                 CHECKGLERROR
2260                 qglScissor(x, y,width,height);
2261                 CHECKGLERROR
2262                 break;
2263         case RENDERPATH_D3D9:
2264 #ifdef SUPPORTD3D
2265                 {
2266                         RECT d3drect;
2267                         d3drect.left = x;
2268                         d3drect.top = y;
2269                         d3drect.right = x + width;
2270                         d3drect.bottom = y + height;
2271                         IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2272                 }
2273 #endif
2274                 break;
2275         case RENDERPATH_D3D10:
2276                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2277                 break;
2278         case RENDERPATH_D3D11:
2279                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2280                 break;
2281         case RENDERPATH_SOFT:
2282                 DPSOFTRAST_Scissor(x, y, width, height);
2283                 break;
2284         }
2285 }
2286
2287 void GL_ScissorTest(int state)
2288 {
2289         if (gl_state.scissortest != state)
2290         {
2291                 gl_state.scissortest = state;
2292                 switch(vid.renderpath)
2293                 {
2294                 case RENDERPATH_GL11:
2295                 case RENDERPATH_GL13:
2296                 case RENDERPATH_GL20:
2297                 case RENDERPATH_GLES1:
2298                 case RENDERPATH_GLES2:
2299                         CHECKGLERROR
2300                         if(gl_state.scissortest)
2301                                 qglEnable(GL_SCISSOR_TEST);
2302                         else
2303                                 qglDisable(GL_SCISSOR_TEST);
2304                         CHECKGLERROR
2305                         break;
2306                 case RENDERPATH_D3D9:
2307 #ifdef SUPPORTD3D
2308                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2309 #endif
2310                         break;
2311                 case RENDERPATH_D3D10:
2312                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2313                         break;
2314                 case RENDERPATH_D3D11:
2315                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2316                         break;
2317                 case RENDERPATH_SOFT:
2318                         DPSOFTRAST_ScissorTest(gl_state.scissortest);
2319                         break;
2320                 }
2321         }
2322 }
2323
2324 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2325 {
2326         static const float blackcolor[4] = {0, 0, 0, 0};
2327         // prevent warnings when trying to clear a buffer that does not exist
2328         if (!colorvalue)
2329                 colorvalue = blackcolor;
2330         if (!vid.stencil)
2331         {
2332                 mask &= ~GL_STENCIL_BUFFER_BIT;
2333                 stencilvalue = 0;
2334         }
2335         switch(vid.renderpath)
2336         {
2337         case RENDERPATH_GL11:
2338         case RENDERPATH_GL13:
2339         case RENDERPATH_GL20:
2340         case RENDERPATH_GLES1:
2341         case RENDERPATH_GLES2:
2342                 CHECKGLERROR
2343                 if (mask & GL_COLOR_BUFFER_BIT)
2344                 {
2345                         qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2346                 }
2347                 if (mask & GL_DEPTH_BUFFER_BIT)
2348                 {
2349                         qglClearDepth(depthvalue);CHECKGLERROR
2350                 }
2351                 if (mask & GL_STENCIL_BUFFER_BIT)
2352                 {
2353                         qglClearStencil(stencilvalue);CHECKGLERROR
2354                 }
2355                 qglClear(mask);CHECKGLERROR
2356                 break;
2357         case RENDERPATH_D3D9:
2358 #ifdef SUPPORTD3D
2359                 IDirect3DDevice9_Clear(vid_d3d9dev, 0, NULL, ((mask & GL_COLOR_BUFFER_BIT) ? D3DCLEAR_TARGET : 0) | ((mask & GL_STENCIL_BUFFER_BIT) ? D3DCLEAR_STENCIL : 0) | ((mask & GL_DEPTH_BUFFER_BIT) ? D3DCLEAR_ZBUFFER : 0), D3DCOLOR_COLORVALUE(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]), depthvalue, stencilvalue);
2360 #endif
2361                 break;
2362         case RENDERPATH_D3D10:
2363                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2364                 break;
2365         case RENDERPATH_D3D11:
2366                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2367                 break;
2368         case RENDERPATH_SOFT:
2369                 if (mask & GL_COLOR_BUFFER_BIT)
2370                         DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2371                 if (mask & GL_DEPTH_BUFFER_BIT)
2372                         DPSOFTRAST_ClearDepth(depthvalue);
2373                 break;
2374         }
2375 }
2376
2377 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2378 {
2379         switch(vid.renderpath)
2380         {
2381         case RENDERPATH_GL11:
2382         case RENDERPATH_GL13:
2383         case RENDERPATH_GL20:
2384         case RENDERPATH_GLES1:
2385         case RENDERPATH_GLES2:
2386                 CHECKGLERROR
2387                 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2388                 break;
2389         case RENDERPATH_D3D9:
2390 #ifdef SUPPORTD3D
2391                 {
2392                         // LordHavoc: we can't directly download the backbuffer because it may be
2393                         // multisampled, and it may not be lockable, so we blit it to a lockable
2394                         // surface of the same dimensions (but without multisample) to resolve the
2395                         // multisample buffer to a normal image, and then lock that...
2396                         IDirect3DSurface9 *stretchsurface = NULL;
2397                         if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2398                         {
2399                                 D3DLOCKED_RECT lockedrect;
2400                                 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2401                                 {
2402                                         if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2403                                         {
2404                                                 int line;
2405                                                 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2406                                                 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2407                                                         memcpy(outpixels + line * width * 4, row, width * 4);
2408                                                 IDirect3DSurface9_UnlockRect(stretchsurface);
2409                                         }
2410                                 }
2411                                 IDirect3DSurface9_Release(stretchsurface);
2412                         }
2413                         // code scraps
2414                         //IDirect3DSurface9 *syssurface = NULL;
2415                         //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2416                         //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2417                         //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2418                         //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2419                         //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2420                         //IDirect3DSurface9_UnlockRect(syssurface);
2421                         //IDirect3DSurface9_Release(syssurface);
2422                 }
2423 #endif
2424                 break;
2425         case RENDERPATH_D3D10:
2426                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2427                 break;
2428         case RENDERPATH_D3D11:
2429                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2430                 break;
2431         case RENDERPATH_SOFT:
2432                 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2433                 break;
2434         }
2435 }
2436
2437 // called at beginning of frame
2438 void R_Mesh_Start(void)
2439 {
2440         BACKENDACTIVECHECK
2441         R_Mesh_ResetRenderTargets();
2442         R_Mesh_SetUseVBO();
2443         if (gl_printcheckerror.integer && !gl_paranoid.integer)
2444         {
2445                 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2446                 Cvar_SetValueQuick(&gl_paranoid, 1);
2447         }
2448 }
2449
2450 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2451 {
2452         int shaderobject;
2453         int shadercompiled;
2454         char compilelog[MAX_INPUTLINE];
2455         shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2456         if (!shaderobject)
2457                 return false;
2458         qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2459         qglCompileShader(shaderobject);CHECKGLERROR
2460         qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2461         qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2462         if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2463         {
2464                 int i, j, pretextlines = 0;
2465                 for (i = 0;i < numstrings - 1;i++)
2466                         for (j = 0;strings[i][j];j++)
2467                                 if (strings[i][j] == '\n')
2468                                         pretextlines++;
2469                 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2470         }
2471         if (!shadercompiled)
2472         {
2473                 qglDeleteShader(shaderobject);CHECKGLERROR
2474                 return false;
2475         }
2476         qglAttachShader(programobject, shaderobject);CHECKGLERROR
2477         qglDeleteShader(shaderobject);CHECKGLERROR
2478         return true;
2479 }
2480
2481 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)
2482 {
2483         GLint programlinked;
2484         GLuint programobject = 0;
2485         char linklog[MAX_INPUTLINE];
2486         CHECKGLERROR
2487
2488         programobject = qglCreateProgram();CHECKGLERROR
2489         if (!programobject)
2490                 return 0;
2491
2492         qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2493         qglBindAttribLocation(programobject, GLSLATTRIB_COLOR    , "Attrib_Color"    );
2494         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2495         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2496         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2497         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2498         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2499         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2500         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2501         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2502         if(vid.support.gl20shaders130)
2503                 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2504
2505         if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2506                 goto cleanup;
2507
2508 #ifdef GL_GEOMETRY_SHADER
2509         if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2510                 goto cleanup;
2511 #endif
2512
2513         if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2514                 goto cleanup;
2515
2516         qglLinkProgram(programobject);CHECKGLERROR
2517         qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2518         qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2519         if (linklog[0])
2520         {
2521                 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2522                         Con_DPrintf("program link log:\n%s\n", linklog);
2523                 // software vertex shader is ok but software fragment shader is WAY
2524                 // too slow, fail program if so.
2525                 // NOTE: this string might be ATI specific, but that's ok because the
2526                 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2527                 // software fragment shader due to low instruction and dependent
2528                 // texture limits.
2529                 if (strstr(linklog, "fragment shader will run in software"))
2530                         programlinked = false;
2531         }
2532         if (!programlinked)
2533                 goto cleanup;
2534         return programobject;
2535 cleanup:
2536         qglDeleteProgram(programobject);CHECKGLERROR
2537         return 0;
2538 }
2539
2540 void GL_Backend_FreeProgram(unsigned int prog)
2541 {
2542         CHECKGLERROR
2543         qglDeleteProgram(prog);
2544         CHECKGLERROR
2545 }
2546
2547 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2548 {
2549         int i;
2550         if (offset)
2551         {
2552                 for (i = 0;i < count;i++)
2553                         *out++ = *in++ + offset;
2554         }
2555         else
2556                 memcpy(out, in, sizeof(*out) * count);
2557 }
2558
2559 // renders triangles using vertices from the active arrays
2560 int paranoidblah = 0;
2561 void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset)
2562 {
2563         unsigned int numelements = numtriangles * 3;
2564         int bufferobject3i;
2565         size_t bufferoffset3i;
2566         int bufferobject3s;
2567         size_t bufferoffset3s;
2568         if (numvertices < 3 || numtriangles < 1)
2569         {
2570                 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2571                         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);
2572                 return;
2573         }
2574         if (!gl_mesh_prefer_short_elements.integer)
2575         {
2576                 if (element3i)
2577                         element3s = NULL;
2578                 if (element3i_indexbuffer)
2579                         element3i_indexbuffer = NULL;
2580         }
2581         // adjust the pointers for firsttriangle
2582         if (element3i)
2583                 element3i += firsttriangle * 3;
2584         if (element3i_indexbuffer)
2585                 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2586         if (element3s)
2587                 element3s += firsttriangle * 3;
2588         if (element3s_indexbuffer)
2589                 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2590         switch(vid.renderpath)
2591         {
2592         case RENDERPATH_GL11:
2593         case RENDERPATH_GL13:
2594         case RENDERPATH_GL20:
2595         case RENDERPATH_GLES1:
2596         case RENDERPATH_GLES2:
2597                 // check if the user specified to ignore static index buffers
2598                 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2599                 {
2600                         element3i_indexbuffer = NULL;
2601                         element3s_indexbuffer = NULL;
2602                 }
2603                 break;
2604         case RENDERPATH_D3D9:
2605         case RENDERPATH_D3D10:
2606         case RENDERPATH_D3D11:
2607                 break;
2608         case RENDERPATH_SOFT:
2609                 break;
2610         }
2611         // upload a dynamic index buffer if needed
2612         if (element3s)
2613         {
2614                 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2615                 {
2616                         if (gl_state.draw_dynamicindexbuffer)
2617                                 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2618                         else
2619                                 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2620                         element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2621                         element3s_bufferoffset = 0;
2622                 }
2623         }
2624         else if (element3i)
2625         {
2626                 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2627                 {
2628                         if (gl_state.draw_dynamicindexbuffer)
2629                                 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2630                         else
2631                                 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2632                         element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2633                         element3i_bufferoffset = 0;
2634                 }
2635         }
2636         bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2637         bufferoffset3i = element3i_bufferoffset;
2638         bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2639         bufferoffset3s = element3s_bufferoffset;
2640         r_refdef.stats.draws++;
2641         r_refdef.stats.draws_vertices += numvertices;
2642         r_refdef.stats.draws_elements += numelements;
2643         if (gl_paranoid.integer)
2644         {
2645                 unsigned int i;
2646                 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2647 #if 0
2648                 unsigned int j, size;
2649                 const int *p;
2650                 // note: there's no validation done here on buffer objects because it
2651                 // is somewhat difficult to get at the data, and gl_paranoid can be
2652                 // used without buffer objects if the need arises
2653                 // (the data could be gotten using glMapBuffer but it would be very
2654                 //  slow due to uncachable video memory reads)
2655                 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2656                         Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2657                 CHECKGLERROR
2658                 if (gl_state.pointer_vertex_pointer)
2659                         for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2660                                 paranoidblah += *p;
2661                 if (gl_state.pointer_color_enabled)
2662                 {
2663                         if (!qglIsEnabled(GL_COLOR_ARRAY))
2664                                 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2665                         CHECKGLERROR
2666                         if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2667                                 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2668                                         paranoidblah += *p;
2669                 }
2670                 for (i = 0;i < vid.texarrayunits;i++)
2671                 {
2672                         if (gl_state.units[i].arrayenabled)
2673                         {
2674                                 GL_ClientActiveTexture(i);
2675                                 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2676                                         Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2677                                 CHECKGLERROR
2678                                 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2679                                         for (j = 0, size = numvertices * gl_state.units[i].arraycomponents, p = (int *)((float *)gl_state.units[i].pointer_texcoord + firstvertex * gl_state.units[i].arraycomponents);j < size;j++, p++)
2680                                                 paranoidblah += *p;
2681                         }
2682                 }
2683 #endif
2684                 if (element3i)
2685                 {
2686                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2687                         {
2688                                 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2689                                 {
2690                                         Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2691                                         return;
2692                                 }
2693                         }
2694                 }
2695                 if (element3s)
2696                 {
2697                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2698                         {
2699                                 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2700                                 {
2701                                         Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2702                                         return;
2703                                 }
2704                         }
2705                 }
2706         }
2707         if (r_render.integer || r_refdef.draw2dstage)
2708         {
2709                 switch(vid.renderpath)
2710                 {
2711                 case RENDERPATH_GL11:
2712                 case RENDERPATH_GL13:
2713                 case RENDERPATH_GL20:
2714                         CHECKGLERROR
2715                         if (gl_mesh_testmanualfeeding.integer)
2716                         {
2717                                 unsigned int i, j, element;
2718                                 const GLfloat *p;
2719                                 qglBegin(GL_TRIANGLES);
2720                                 if(vid.renderpath == RENDERPATH_GL20)
2721                                 {
2722                                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2723                                         {
2724                                                 if (element3i)
2725                                                         element = element3i[i];
2726                                                 else if (element3s)
2727                                                         element = element3s[i];
2728                                                 else
2729                                                         element = firstvertex + i;
2730                                                 for (j = 0;j < vid.texarrayunits;j++)
2731                                                 {
2732                                                         if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2733                                                         {
2734                                                                 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2735                                                                 {
2736                                                                         p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2737                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2738                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2], p[3]);
2739                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2740                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2]);
2741                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2742                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1]);
2743                                                                         else
2744                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, p[0]);
2745                                                                 }
2746                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2747                                                                 {
2748                                                                         const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2749                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2750                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2], s[3]);
2751                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2752                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2]);
2753                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2754                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1]);
2755                                                                         else if (gl_state.units[j].pointer_texcoord_components == 1)
2756                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, s[0]);
2757                                                                 }
2758                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2759                                                                 {
2760                                                                         const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2761                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2762                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2], sb[3]);
2763                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2764                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2]);
2765                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2766                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1]);
2767                                                                         else if (gl_state.units[j].pointer_texcoord_components == 1)
2768                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0]);
2769                                                                 }
2770                                                         }
2771                                                 }
2772                                                 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2773                                                 {
2774                                                         if (gl_state.pointer_color_gltype == GL_FLOAT)
2775                                                         {
2776                                                                 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2777                                                                 qglVertexAttrib4f(GLSLATTRIB_COLOR, p[0], p[1], p[2], p[3]);
2778                                                         }
2779                                                         else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2780                                                         {
2781                                                                 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2782                                                                 qglVertexAttrib4Nub(GLSLATTRIB_COLOR, ub[0], ub[1], ub[2], ub[3]);
2783                                                         }
2784                                                 }
2785                                                 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2786                                                 {
2787                                                         p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2788                                                         if (gl_state.pointer_vertex_components == 4)
2789                                                                 qglVertexAttrib4f(GLSLATTRIB_POSITION, p[0], p[1], p[2], p[3]);
2790                                                         else if (gl_state.pointer_vertex_components == 3)
2791                                                                 qglVertexAttrib3f(GLSLATTRIB_POSITION, p[0], p[1], p[2]);
2792                                                         else
2793                                                                 qglVertexAttrib2f(GLSLATTRIB_POSITION, p[0], p[1]);
2794                                                 }
2795                                         }
2796                                 }
2797                                 else
2798                                 {
2799                                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2800                                         {
2801                                                 if (element3i)
2802                                                         element = element3i[i];
2803                                                 else if (element3s)
2804                                                         element = element3s[i];
2805                                                 else
2806                                                         element = firstvertex + i;
2807                                                 for (j = 0;j < vid.texarrayunits;j++)
2808                                                 {
2809                                                         if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2810                                                         {
2811                                                                 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2812                                                                 {
2813                                                                         p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2814                                                                         if (vid.texarrayunits > 1)
2815                                                                         {
2816                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2817                                                                                         qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2818                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2819                                                                                         qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2820                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2821                                                                                         qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2822                                                                                 else
2823                                                                                         qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2824                                                                         }
2825                                                                         else
2826                                                                         {
2827                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2828                                                                                         qglTexCoord4f(p[0], p[1], p[2], p[3]);
2829                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2830                                                                                         qglTexCoord3f(p[0], p[1], p[2]);
2831                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2832                                                                                         qglTexCoord2f(p[0], p[1]);
2833                                                                                 else
2834                                                                                         qglTexCoord1f(p[0]);
2835                                                                         }
2836                                                                 }
2837                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2838                                                                 {
2839                                                                         const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2840                                                                         if (vid.texarrayunits > 1)
2841                                                                         {
2842                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2843                                                                                         qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2844                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2845                                                                                         qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2846                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2847                                                                                         qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2848                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
2849                                                                                         qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2850                                                                         }
2851                                                                         else
2852                                                                         {
2853                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2854                                                                                         qglTexCoord4f(s[0], s[1], s[2], s[3]);
2855                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2856                                                                                         qglTexCoord3f(s[0], s[1], s[2]);
2857                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2858                                                                                         qglTexCoord2f(s[0], s[1]);
2859                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
2860                                                                                         qglTexCoord1f(s[0]);
2861                                                                         }
2862                                                                 }
2863                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2864                                                                 {
2865                                                                         const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2866                                                                         if (vid.texarrayunits > 1)
2867                                                                         {
2868                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2869                                                                                         qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2870                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2871                                                                                         qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2872                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2873                                                                                         qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2874                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
2875                                                                                         qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2876                                                                         }
2877                                                                         else
2878                                                                         {
2879                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2880                                                                                         qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2881                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2882                                                                                         qglTexCoord3f(sb[0], sb[1], sb[2]);
2883                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2884                                                                                         qglTexCoord2f(sb[0], sb[1]);
2885                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
2886                                                                                         qglTexCoord1f(sb[0]);
2887                                                                         }
2888                                                                 }
2889                                                         }
2890                                                 }
2891                                                 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2892                                                 {
2893                                                         if (gl_state.pointer_color_gltype == GL_FLOAT)
2894                                                         {
2895                                                                 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2896                                                                 qglColor4f(p[0], p[1], p[2], p[3]);
2897                                                         }
2898                                                         else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2899                                                         {
2900                                                                 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2901                                                                 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2902                                                         }
2903                                                 }
2904                                                 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2905                                                 {
2906                                                         p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2907                                                         if (gl_state.pointer_vertex_components == 4)
2908                                                                 qglVertex4f(p[0], p[1], p[2], p[3]);
2909                                                         else if (gl_state.pointer_vertex_components == 3)
2910                                                                 qglVertex3f(p[0], p[1], p[2]);
2911                                                         else
2912                                                                 qglVertex2f(p[0], p[1]);
2913                                                 }
2914                                         }
2915                                 }
2916                                 qglEnd();
2917                                 CHECKGLERROR
2918                         }
2919                         else if (bufferobject3s)
2920                         {
2921                                 GL_BindEBO(bufferobject3s);
2922                                 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2923                                 {
2924                                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2925                                         CHECKGLERROR
2926                                 }
2927                                 else
2928                                 {
2929                                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2930                                         CHECKGLERROR
2931                                 }
2932                         }
2933                         else if (bufferobject3i)
2934                         {
2935                                 GL_BindEBO(bufferobject3i);
2936                                 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2937                                 {
2938                                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2939                                         CHECKGLERROR
2940                                 }
2941                                 else
2942                                 {
2943                                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2944                                         CHECKGLERROR
2945                                 }
2946                         }
2947                         else if (element3s)
2948                         {
2949                                 GL_BindEBO(0);
2950                                 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2951                                 {
2952                                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2953                                         CHECKGLERROR
2954                                 }
2955                                 else
2956                                 {
2957                                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2958                                         CHECKGLERROR
2959                                 }
2960                         }
2961                         else if (element3i)
2962                         {
2963                                 GL_BindEBO(0);
2964                                 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2965                                 {
2966                                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2967                                         CHECKGLERROR
2968                                 }
2969                                 else
2970                                 {
2971                                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2972                                         CHECKGLERROR
2973                                 }
2974                         }
2975                         else
2976                         {
2977                                 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2978                                 CHECKGLERROR
2979                         }
2980                         break;
2981                 case RENDERPATH_D3D9:
2982 #ifdef SUPPORTD3D
2983                         if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2984                         {
2985                                 if (element3s_indexbuffer)
2986                                 {
2987                                         IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2988                                         IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2989                                 }
2990                                 else if (element3i_indexbuffer)
2991                                 {
2992                                         IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2993                                         IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2994                                 }
2995                                 else
2996                                         IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2997                         }
2998                         else
2999                         {
3000                                 if (element3s)
3001                                         IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
3002                                 else if (element3i)
3003                                         IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
3004                                 else
3005                                         IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
3006                         }
3007 #endif
3008                         break;
3009                 case RENDERPATH_D3D10:
3010                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3011                         break;
3012                 case RENDERPATH_D3D11:
3013                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3014                         break;
3015                 case RENDERPATH_SOFT:
3016                         DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
3017                         break;
3018                 case RENDERPATH_GLES1:
3019                 case RENDERPATH_GLES2:
3020                         // GLES does not have glDrawRangeElements, and generally
3021                         // underperforms with index buffers, so this code path is
3022                         // relatively straightforward...
3023 #if 0
3024                         if (gl_paranoid.integer)
3025                         {
3026                                 int r, prog, enabled, i;
3027                                 GLsizei         attriblength;
3028                                 GLint           attribsize;
3029                                 GLenum          attribtype;
3030                                 GLchar          attribname[1024];
3031                                 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
3032                                 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
3033                                         Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
3034 #ifndef GL_CURRENT_PROGRAM
3035 #define GL_CURRENT_PROGRAM 0x8B8D
3036 #endif
3037                                 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
3038                                 if (r < 0 || r > 10000)
3039                                         Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
3040                                 prog = r;
3041                                 for (i = 0;i < 8;i++)
3042                                 {
3043                                         qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
3044                                         if (!r)
3045                                                 continue;
3046                                         qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
3047                                         Con_DPrintf("prog %i position %i length %i size %04X type %i name \"%s\"\n", prog, i, (int)attriblength, (int)attribsize, (int)attribtype, (char *)attribname);
3048                                 }
3049                         }
3050 #endif
3051                         if (element3s)
3052                         {
3053                                 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
3054                                 CHECKGLERROR
3055                         }
3056                         else if (element3i)
3057                         {
3058                                 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
3059                                 CHECKGLERROR
3060                         }
3061                         else
3062                         {
3063                                 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
3064                                 CHECKGLERROR
3065                         }
3066                         break;
3067                 }
3068         }
3069 }
3070
3071 // restores backend state, used when done with 3D rendering
3072 void R_Mesh_Finish(void)
3073 {
3074         R_Mesh_ResetRenderTargets();
3075 }
3076
3077 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
3078 {
3079         r_meshbuffer_t *buffer;
3080         if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
3081                 return NULL;
3082         buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
3083         memset(buffer, 0, sizeof(*buffer));
3084         buffer->bufferobject = 0;
3085         buffer->devicebuffer = NULL;
3086         buffer->size = 0;
3087         buffer->isindexbuffer = isindexbuffer;
3088         buffer->isdynamic = isdynamic;
3089         buffer->isindex16 = isindex16;
3090         strlcpy(buffer->name, name, sizeof(buffer->name));
3091         R_Mesh_UpdateMeshBuffer(buffer, data, size);
3092         return buffer;
3093 }
3094
3095 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
3096 {
3097         if (!buffer)
3098                 return;
3099         if (buffer->isindexbuffer)
3100         {
3101                 r_refdef.stats.indexbufferuploadcount++;
3102                 r_refdef.stats.indexbufferuploadsize += size;
3103         }
3104         else
3105         {
3106                 r_refdef.stats.vertexbufferuploadcount++;
3107                 r_refdef.stats.vertexbufferuploadsize += size;
3108         }
3109         switch(vid.renderpath)
3110         {
3111         case RENDERPATH_GL11:
3112         case RENDERPATH_GL13:
3113         case RENDERPATH_GL20:
3114         case RENDERPATH_GLES1:
3115         case RENDERPATH_GLES2:
3116                 if (!buffer->bufferobject)
3117                         qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3118                 if (buffer->isindexbuffer)
3119                         GL_BindEBO(buffer->bufferobject);
3120                 else
3121                         GL_BindVBO(buffer->bufferobject);
3122                 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
3123                 break;
3124         case RENDERPATH_D3D9:
3125 #ifdef SUPPORTD3D
3126                 {
3127                         int result;
3128                         void *datapointer = NULL;
3129                         if (buffer->isindexbuffer)
3130                         {
3131                                 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3132                                 if (size > buffer->size || !buffer->devicebuffer)
3133                                 {
3134                                         if (buffer->devicebuffer)
3135                                                 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3136                                         buffer->devicebuffer = NULL;
3137                                         if (FAILED(result = IDirect3DDevice9_CreateIndexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9indexbuffer, NULL)))
3138                                                 Sys_Error("IDirect3DDevice9_CreateIndexBuffer(%p, %d, %x, %x, %x, %p, NULL) returned %x\n", vid_d3d9dev, (int)size, buffer->isdynamic ? (int)D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? (int)D3DFMT_INDEX16 : (int)D3DFMT_INDEX32, buffer->isdynamic ? (int)D3DPOOL_DEFAULT : (int)D3DPOOL_MANAGED, &d3d9indexbuffer, (int)result);
3139                                         buffer->devicebuffer = (void *)d3d9indexbuffer;
3140                                         buffer->size = size;
3141                                 }
3142                                 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3143                                 {
3144                                         if (data)
3145                                                 memcpy(datapointer, data, size);
3146                                         else
3147                                                 memset(datapointer, 0, size);
3148                                         IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3149                                 }
3150                         }
3151                         else
3152                         {
3153                                 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3154                                 if (size > buffer->size || !buffer->devicebuffer)
3155                                 {
3156                                         if (buffer->devicebuffer)
3157                                                 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3158                                         buffer->devicebuffer = NULL;
3159                                         if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3160                                                 Sys_Error("IDirect3DDevice9_CreateVertexBuffer(%p, %d, %x, %x, %x, %p, NULL) returned %x\n", vid_d3d9dev, (int)size, buffer->isdynamic ? (int)D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? (int)D3DPOOL_DEFAULT : (int)D3DPOOL_MANAGED, &d3d9vertexbuffer, (int)result);
3161                                         buffer->devicebuffer = (void *)d3d9vertexbuffer;
3162                                         buffer->size = size;
3163                                 }
3164                                 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3165                                 {
3166                                         if (data)
3167                                                 memcpy(datapointer, data, size);
3168                                         else
3169                                                 memset(datapointer, 0, size);
3170                                         IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3171                                 }
3172                         }
3173                 }
3174 #endif
3175                 break;
3176         case RENDERPATH_D3D10:
3177                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3178                 break;
3179         case RENDERPATH_D3D11:
3180                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3181                 break;
3182         case RENDERPATH_SOFT:
3183                 break;
3184         }
3185 }
3186
3187 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3188 {
3189         if (!buffer)
3190                 return;
3191         switch(vid.renderpath)
3192         {
3193         case RENDERPATH_GL11:
3194         case RENDERPATH_GL13:
3195         case RENDERPATH_GL20:
3196         case RENDERPATH_GLES1:
3197         case RENDERPATH_GLES2:
3198                 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3199                 break;
3200         case RENDERPATH_D3D9:
3201 #ifdef SUPPORTD3D
3202                 if (gl_state.d3dvertexbuffer == (void *)buffer)
3203                         gl_state.d3dvertexbuffer = NULL;
3204                 if (buffer->devicebuffer)
3205                 {
3206                         if (buffer->isindexbuffer)
3207                                 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3208                         else
3209                                 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3210                         buffer->devicebuffer = NULL;
3211                 }
3212 #endif
3213                 break;
3214         case RENDERPATH_D3D10:
3215                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3216                 break;
3217         case RENDERPATH_D3D11:
3218                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3219                 break;
3220         case RENDERPATH_SOFT:
3221                 break;
3222         }
3223         Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3224 }
3225
3226 void GL_Mesh_ListVBOs(qboolean printeach)
3227 {
3228         int i, endindex;
3229         size_t ebocount = 0, ebomemory = 0;
3230         size_t vbocount = 0, vbomemory = 0;
3231         r_meshbuffer_t *buffer;
3232         endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3233         for (i = 0;i < endindex;i++)
3234         {
3235                 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3236                 if (!buffer)
3237                         continue;
3238                 if (buffer->isindexbuffer) {ebocount++;ebomemory += buffer->size;if (printeach) Con_Printf("indexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
3239                 else                       {vbocount++;vbomemory += buffer->size;if (printeach) Con_Printf("vertexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
3240         }
3241         Con_Printf("vertex buffers: %i indexbuffers totalling %i bytes (%.3f MB), %i vertexbuffers totalling %i bytes (%.3f MB), combined %i bytes (%.3fMB)\n", (int)ebocount, (int)ebomemory, ebomemory / 1048576.0, (int)vbocount, (int)vbomemory, vbomemory / 1048576.0, (int)(ebomemory + vbomemory), (ebomemory + vbomemory) / 1048576.0);
3242 }
3243
3244
3245
3246 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3247 {
3248         switch(vid.renderpath)
3249         {
3250         case RENDERPATH_GL11:
3251         case RENDERPATH_GL13:
3252         case RENDERPATH_GLES1:
3253                 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)
3254                 {
3255                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3256                         gl_state.pointer_vertex_components = components;
3257                         gl_state.pointer_vertex_gltype = gltype;
3258                         gl_state.pointer_vertex_stride = stride;
3259                         gl_state.pointer_vertex_pointer = pointer;
3260                         gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3261                         gl_state.pointer_vertex_offset = bufferoffset;
3262                         CHECKGLERROR
3263                         GL_BindVBO(bufferobject);
3264                         qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3265                 }
3266                 break;
3267         case RENDERPATH_GL20:
3268         case RENDERPATH_GLES2:
3269                 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)
3270                 {
3271                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3272                         gl_state.pointer_vertex_components = components;
3273                         gl_state.pointer_vertex_gltype = gltype;
3274                         gl_state.pointer_vertex_stride = stride;
3275                         gl_state.pointer_vertex_pointer = pointer;
3276                         gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3277                         gl_state.pointer_vertex_offset = bufferoffset;
3278                         CHECKGLERROR
3279                         GL_BindVBO(bufferobject);
3280                         qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3281                 }
3282                 break;
3283         case RENDERPATH_D3D9:
3284         case RENDERPATH_D3D10:
3285         case RENDERPATH_D3D11:
3286         case RENDERPATH_SOFT:
3287                 break;
3288         }
3289 }
3290
3291 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3292 {
3293         // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3294         // the pointer only.
3295         switch(vid.renderpath)
3296         {
3297         case RENDERPATH_GL11:
3298         case RENDERPATH_GL13:
3299         case RENDERPATH_GLES1:
3300                 CHECKGLERROR
3301                 if (pointer)
3302                 {
3303                         // caller wants color array enabled
3304                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3305                         if (!gl_state.pointer_color_enabled)
3306                         {
3307                                 gl_state.pointer_color_enabled = true;
3308                                 CHECKGLERROR
3309                                 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3310                         }
3311                         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)
3312                         {
3313                                 gl_state.pointer_color_components = components;
3314                                 gl_state.pointer_color_gltype = gltype;
3315                                 gl_state.pointer_color_stride = stride;
3316                                 gl_state.pointer_color_pointer = pointer;
3317                                 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3318                                 gl_state.pointer_color_offset = bufferoffset;
3319                                 CHECKGLERROR
3320                                 GL_BindVBO(bufferobject);
3321                                 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3322                         }
3323                 }
3324                 else
3325                 {
3326                         // caller wants color array disabled
3327                         if (gl_state.pointer_color_enabled)
3328                         {
3329                                 gl_state.pointer_color_enabled = false;
3330                                 CHECKGLERROR
3331                                 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3332                                 // when color array is on the glColor gets trashed, set it again
3333                                 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3334                         }
3335                 }
3336                 break;
3337         case RENDERPATH_GL20:
3338         case RENDERPATH_GLES2:
3339                 CHECKGLERROR
3340                 if (pointer)
3341                 {
3342                         // caller wants color array enabled
3343                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3344                         if (!gl_state.pointer_color_enabled)
3345                         {
3346                                 gl_state.pointer_color_enabled = true;
3347                                 CHECKGLERROR
3348                                 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3349                         }
3350                         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)
3351                         {
3352                                 gl_state.pointer_color_components = components;
3353                                 gl_state.pointer_color_gltype = gltype;
3354                                 gl_state.pointer_color_stride = stride;
3355                                 gl_state.pointer_color_pointer = pointer;
3356                                 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3357                                 gl_state.pointer_color_offset = bufferoffset;
3358                                 CHECKGLERROR
3359                                 GL_BindVBO(bufferobject);
3360                                 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3361                         }
3362                 }
3363                 else
3364                 {
3365                         // caller wants color array disabled
3366                         if (gl_state.pointer_color_enabled)
3367                         {
3368                                 gl_state.pointer_color_enabled = false;
3369                                 CHECKGLERROR
3370                                 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3371                                 // when color array is on the glColor gets trashed, set it again
3372                                 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3373                         }
3374                 }
3375                 break;
3376         case RENDERPATH_D3D9:
3377         case RENDERPATH_D3D10:
3378         case RENDERPATH_D3D11:
3379         case RENDERPATH_SOFT:
3380                 break;
3381         }
3382 }
3383
3384 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)
3385 {
3386         gltextureunit_t *unit = gl_state.units + unitnum;
3387         // update array settings
3388         // note: there is no need to check bufferobject here because all cases
3389         // that involve a valid bufferobject also supply a texcoord array
3390         switch(vid.renderpath)
3391         {
3392         case RENDERPATH_GL11:
3393         case RENDERPATH_GL13:
3394         case RENDERPATH_GLES1:
3395                 CHECKGLERROR
3396                 if (pointer)
3397                 {
3398                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3399                         // texture array unit is enabled, enable the array
3400                         if (!unit->arrayenabled)
3401                         {
3402                                 unit->arrayenabled = true;
3403                                 GL_ClientActiveTexture(unitnum);
3404                                 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3405                         }
3406                         // texcoord array
3407                         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)
3408                         {
3409                                 unit->pointer_texcoord_components = components;
3410                                 unit->pointer_texcoord_gltype = gltype;
3411                                 unit->pointer_texcoord_stride = stride;
3412                                 unit->pointer_texcoord_pointer = pointer;
3413                                 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3414                                 unit->pointer_texcoord_offset = bufferoffset;
3415                                 GL_ClientActiveTexture(unitnum);
3416                                 GL_BindVBO(bufferobject);
3417                                 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3418                         }
3419                 }
3420                 else
3421                 {
3422                         // texture array unit is disabled, disable the array
3423                         if (unit->arrayenabled)
3424                         {
3425                                 unit->arrayenabled = false;
3426                                 GL_ClientActiveTexture(unitnum);
3427                                 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3428                         }
3429                 }
3430                 break;
3431         case RENDERPATH_GL20:
3432         case RENDERPATH_GLES2:
3433                 CHECKGLERROR
3434                 if (pointer)
3435                 {
3436                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3437                         // texture array unit is enabled, enable the array
3438                         if (!unit->arrayenabled)
3439                         {
3440                                 unit->arrayenabled = true;
3441                                 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3442                         }
3443                         // texcoord array
3444                         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)
3445                         {
3446                                 unit->pointer_texcoord_components = components;
3447                                 unit->pointer_texcoord_gltype = gltype;
3448                                 unit->pointer_texcoord_stride = stride;
3449                                 unit->pointer_texcoord_pointer = pointer;
3450                                 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3451                                 unit->pointer_texcoord_offset = bufferoffset;
3452                                 GL_BindVBO(bufferobject);
3453                                 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3454                         }
3455                 }
3456                 else
3457                 {
3458                         // texture array unit is disabled, disable the array
3459                         if (unit->arrayenabled)
3460                         {
3461                                 unit->arrayenabled = false;
3462                                 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3463                         }
3464                 }
3465                 break;
3466         case RENDERPATH_D3D9:
3467         case RENDERPATH_D3D10:
3468         case RENDERPATH_D3D11:
3469         case RENDERPATH_SOFT:
3470                 break;
3471         }
3472 }
3473
3474 int R_Mesh_TexBound(unsigned int unitnum, int id)
3475 {
3476         gltextureunit_t *unit = gl_state.units + unitnum;
3477         if (unitnum >= vid.teximageunits)
3478                 return 0;
3479         if (id == GL_TEXTURE_2D)
3480                 return unit->t2d;
3481         if (id == GL_TEXTURE_3D)
3482                 return unit->t3d;
3483         if (id == GL_TEXTURE_CUBE_MAP_ARB)
3484                 return unit->tcubemap;
3485         return 0;
3486 }
3487
3488 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3489 {
3490         switch(vid.renderpath)
3491         {
3492         case RENDERPATH_GL11:
3493         case RENDERPATH_GL13:
3494         case RENDERPATH_GL20:
3495         case RENDERPATH_GLES1:
3496         case RENDERPATH_GLES2:
3497                 R_Mesh_TexBind(0, tex);
3498                 GL_ActiveTexture(0);CHECKGLERROR
3499                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3500                 break;
3501         case RENDERPATH_D3D9:
3502 #ifdef SUPPORTD3D
3503                 {
3504                         IDirect3DSurface9 *currentsurface = NULL;
3505                         IDirect3DSurface9 *texturesurface = NULL;
3506                         RECT sourcerect;
3507                         RECT destrect;
3508                         sourcerect.left = sx;
3509                         sourcerect.top = sy;
3510                         sourcerect.right = sx + width;
3511                         sourcerect.bottom = sy + height;
3512                         destrect.left = tx;
3513                         destrect.top = ty;
3514                         destrect.right = tx + width;
3515                         destrect.bottom = ty + height;
3516                         if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3517                         {
3518                                 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &currentsurface)))
3519                                 {
3520                                         IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3521                                         IDirect3DSurface9_Release(currentsurface);
3522                                 }
3523                                 IDirect3DSurface9_Release(texturesurface);
3524                         }
3525                 }
3526 #endif
3527                 break;
3528         case RENDERPATH_D3D10:
3529                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3530                 break;
3531         case RENDERPATH_D3D11:
3532                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3533                 break;
3534         case RENDERPATH_SOFT:
3535                 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3536                 break;
3537         }
3538 }
3539
3540 #ifdef SUPPORTD3D
3541 int d3drswrap[16] = {D3DRS_WRAP0, D3DRS_WRAP1, D3DRS_WRAP2, D3DRS_WRAP3, D3DRS_WRAP4, D3DRS_WRAP5, D3DRS_WRAP6, D3DRS_WRAP7, D3DRS_WRAP8, D3DRS_WRAP9, D3DRS_WRAP10, D3DRS_WRAP11, D3DRS_WRAP12, D3DRS_WRAP13, D3DRS_WRAP14, D3DRS_WRAP15};
3542 #endif
3543
3544 void R_Mesh_ClearBindingsForTexture(int texnum)
3545 {
3546         gltextureunit_t *unit;
3547         unsigned int unitnum;
3548         // this doesn't really unbind the texture, but it does prevent a mistaken "do nothing" behavior on the next time this same texnum is bound on the same unit as the same type (this mainly affects r_shadow_bouncegrid because 3D textures are so rarely used)
3549         for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3550         {
3551                 unit = gl_state.units + unitnum;
3552                 if (unit->t2d == texnum)
3553                         unit->t2d = -1;
3554                 if (unit->t3d == texnum)
3555                         unit->t3d = -1;
3556                 if (unit->tcubemap == texnum)
3557                         unit->tcubemap = -1;
3558         }
3559 }
3560
3561 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3562 {
3563         gltextureunit_t *unit = gl_state.units + unitnum;
3564         int tex2d, tex3d, texcubemap, texnum;
3565         if (unitnum >= vid.teximageunits)
3566                 return;
3567 //      if (unit->texture == tex)
3568 //              return;
3569         switch(vid.renderpath)
3570         {
3571         case RENDERPATH_GL20:
3572         case RENDERPATH_GLES2:
3573                 if (!tex)
3574                 {
3575                         tex = r_texture_white;
3576                         // not initialized enough yet...
3577                         if (!tex)
3578                                 return;
3579                 }
3580                 unit->texture = tex;
3581                 texnum = R_GetTexture(tex);
3582                 switch(tex->gltexturetypeenum)
3583                 {
3584                 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3585                 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3586                 case GL_TEXTURE_CUBE_MAP_ARB: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR}break;
3587                 }
3588                 break;
3589         case RENDERPATH_GL11:
3590         case RENDERPATH_GL13:
3591         case RENDERPATH_GLES1:
3592                 unit->texture = tex;
3593                 tex2d = 0;
3594                 tex3d = 0;
3595                 texcubemap = 0;
3596                 if (tex)
3597                 {
3598                         texnum = R_GetTexture(tex);
3599                         switch(tex->gltexturetypeenum)
3600                         {
3601                         case GL_TEXTURE_2D:
3602                                 tex2d = texnum;
3603                                 break;
3604                         case GL_TEXTURE_3D:
3605                                 tex3d = texnum;
3606                                 break;
3607                         case GL_TEXTURE_CUBE_MAP_ARB:
3608                                 texcubemap = texnum;
3609                                 break;
3610                         }
3611                 }
3612                 // update 2d texture binding
3613                 if (unit->t2d != tex2d)
3614                 {
3615                         GL_ActiveTexture(unitnum);
3616                         if (tex2d)
3617                         {
3618                                 if (unit->t2d == 0)
3619                                 {
3620                                         qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3621                                 }
3622                         }
3623                         else
3624                         {
3625                                 if (unit->t2d)
3626                                 {
3627                                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3628                                 }
3629                         }
3630                         unit->t2d = tex2d;
3631                         qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3632                 }
3633                 // update 3d texture binding
3634                 if (unit->t3d != tex3d)
3635                 {
3636                         GL_ActiveTexture(unitnum);
3637                         if (tex3d)
3638                         {
3639                                 if (unit->t3d == 0)
3640                                 {
3641                                         qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3642                                 }
3643                         }
3644                         else
3645                         {
3646                                 if (unit->t3d)
3647                                 {
3648                                         qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3649                                 }
3650                         }
3651                         unit->t3d = tex3d;
3652                         qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3653                 }
3654                 // update cubemap texture binding
3655                 if (unit->tcubemap != texcubemap)
3656                 {
3657                         GL_ActiveTexture(unitnum);
3658                         if (texcubemap)
3659                         {
3660                                 if (unit->tcubemap == 0)
3661                                 {
3662                                         qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3663                                 }
3664                         }
3665                         else
3666                         {
3667                                 if (unit->tcubemap)
3668                                 {
3669                                         qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3670                                 }
3671                         }
3672                         unit->tcubemap = texcubemap;
3673                         qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3674                 }
3675                 break;
3676         case RENDERPATH_D3D9:
3677 #ifdef SUPPORTD3D
3678                 {
3679                         extern cvar_t gl_texture_anisotropy;
3680                         if (!tex)
3681                         {
3682                                 tex = r_texture_white;
3683                                 // not initialized enough yet...
3684                                 if (!tex)
3685                                         return;
3686                         }
3687                         // upload texture if needed
3688                         R_GetTexture(tex);
3689                         if (unit->texture == tex)
3690                                 return;
3691                         unit->texture = tex;
3692                         IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3693                         //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3694                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3695                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3696                         if (tex->d3daddressw)
3697                                 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW,  tex->d3daddressw);
3698                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3699                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3700                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3701                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3702                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3703                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3704                 }
3705 #endif
3706                 break;
3707         case RENDERPATH_D3D10:
3708                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3709                 break;
3710         case RENDERPATH_D3D11:
3711                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3712                 break;
3713         case RENDERPATH_SOFT:
3714                 if (!tex)
3715                 {
3716                         tex = r_texture_white;
3717                         // not initialized enough yet...
3718                         if (!tex)
3719                                 return;
3720                 }
3721                 texnum = R_GetTexture(tex);
3722                 if (unit->texture == tex)
3723                         return;
3724                 unit->texture = tex;
3725                 DPSOFTRAST_SetTexture(unitnum, texnum);
3726                 break;
3727         }
3728 }
3729
3730 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3731 {
3732         gltextureunit_t *unit = gl_state.units + unitnum;
3733         switch(vid.renderpath)
3734         {
3735         case RENDERPATH_GL11:
3736         case RENDERPATH_GL13:
3737         case RENDERPATH_GL20:
3738         case RENDERPATH_GLES1:
3739         case RENDERPATH_GLES2:
3740                 if (matrix && matrix->m[3][3])
3741                 {
3742                         // texmatrix specified, check if it is different
3743                         if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3744                         {
3745                                 float glmatrix[16];
3746                                 unit->texmatrixenabled = true;
3747                                 unit->matrix = *matrix;
3748                                 CHECKGLERROR
3749                                 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3750                                 GL_ActiveTexture(unitnum);
3751                                 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3752                                 qglLoadMatrixf(glmatrix);CHECKGLERROR
3753                                 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3754                         }
3755                 }
3756                 else
3757                 {
3758                         // no texmatrix specified, revert to identity
3759                         if (unit->texmatrixenabled)
3760                         {
3761                                 unit->texmatrixenabled = false;
3762                                 unit->matrix = identitymatrix;
3763                                 CHECKGLERROR
3764                                 GL_ActiveTexture(unitnum);
3765                                 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3766                                 qglLoadIdentity();CHECKGLERROR
3767                                 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3768                         }
3769                 }
3770                 break;
3771         case RENDERPATH_D3D9:
3772         case RENDERPATH_D3D10:
3773         case RENDERPATH_D3D11:
3774                 break;
3775         case RENDERPATH_SOFT:
3776                 break;
3777         }
3778 }
3779
3780 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3781 {
3782         gltextureunit_t *unit = gl_state.units + unitnum;
3783         CHECKGLERROR
3784         switch(vid.renderpath)
3785         {
3786         case RENDERPATH_GL20:
3787         case RENDERPATH_GLES2:
3788                 // do nothing
3789                 break;
3790         case RENDERPATH_GL13:
3791         case RENDERPATH_GLES1:
3792                 // GL_ARB_texture_env_combine
3793                 if (!combinergb)
3794                         combinergb = GL_MODULATE;
3795                 if (!combinealpha)
3796                         combinealpha = GL_MODULATE;
3797                 if (!rgbscale)
3798                         rgbscale = 1;
3799                 if (!alphascale)
3800                         alphascale = 1;
3801                 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3802                 {
3803                         if (combinergb == GL_DECAL)
3804                                 combinergb = GL_INTERPOLATE_ARB;
3805                         if (unit->combine != GL_COMBINE_ARB)
3806                         {
3807                                 unit->combine = GL_COMBINE_ARB;
3808                                 GL_ActiveTexture(unitnum);
3809                                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3810                                 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3811                         }
3812                         if (unit->combinergb != combinergb)
3813                         {
3814                                 unit->combinergb = combinergb;
3815                                 GL_ActiveTexture(unitnum);
3816                                 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3817                         }
3818                         if (unit->combinealpha != combinealpha)
3819                         {
3820                                 unit->combinealpha = combinealpha;
3821                                 GL_ActiveTexture(unitnum);
3822                                 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3823                         }
3824                         if (unit->rgbscale != rgbscale)
3825                         {
3826                                 unit->rgbscale = rgbscale;
3827                                 GL_ActiveTexture(unitnum);
3828                                 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3829                         }
3830                         if (unit->alphascale != alphascale)
3831                         {
3832                                 unit->alphascale = alphascale;
3833                                 GL_ActiveTexture(unitnum);
3834                                 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3835                         }
3836                 }
3837                 else
3838                 {
3839                         if (unit->combine != combinergb)
3840                         {
3841                                 unit->combine = combinergb;
3842                                 GL_ActiveTexture(unitnum);
3843                                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3844                         }
3845                 }
3846                 break;
3847         case RENDERPATH_GL11:
3848                 // normal GL texenv
3849                 if (!combinergb)
3850                         combinergb = GL_MODULATE;
3851                 if (unit->combine != combinergb)
3852                 {
3853                         unit->combine = combinergb;
3854                         GL_ActiveTexture(unitnum);
3855                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3856                 }
3857                 break;
3858         case RENDERPATH_D3D9:
3859         case RENDERPATH_D3D10:
3860         case RENDERPATH_D3D11:
3861                 break;
3862         case RENDERPATH_SOFT:
3863                 break;
3864         }
3865 }
3866
3867 void R_Mesh_ResetTextureState(void)
3868 {
3869         unsigned int unitnum;
3870
3871         BACKENDACTIVECHECK
3872
3873         for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3874                 R_Mesh_TexBind(unitnum, NULL);
3875         for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3876                 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3877         switch(vid.renderpath)
3878         {
3879         case RENDERPATH_GL20:
3880         case RENDERPATH_GLES2:
3881         case RENDERPATH_D3D9:
3882         case RENDERPATH_D3D10:
3883         case RENDERPATH_D3D11:
3884         case RENDERPATH_SOFT:
3885                 break;
3886         case RENDERPATH_GL11:
3887         case RENDERPATH_GL13:
3888         case RENDERPATH_GLES1:
3889                 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3890                 {
3891                         R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3892                         R_Mesh_TexMatrix(unitnum, NULL);
3893                 }
3894                 break;
3895         }
3896 }
3897
3898
3899
3900 #ifdef SUPPORTD3D
3901 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3902 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3903 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3904
3905 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3906 {
3907         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3908         D3DDECL_END()
3909 };
3910
3911 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3912 {
3913         {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f  ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3914         {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f   ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3915         {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3916         D3DDECL_END()
3917 };
3918
3919 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3920 {
3921         {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f          ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3922         {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f           ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3923         {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3924         {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f         ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3925         {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f         ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3926         {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f          ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3927         {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3928         D3DDECL_END()
3929 };
3930
3931 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3932 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3933 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3934 #endif
3935
3936 static void R_Mesh_InitVertexDeclarations(void)
3937 {
3938 #ifdef SUPPORTD3D
3939         r_vertex3f_d3d9decl = NULL;
3940         r_vertexgeneric_d3d9decl = NULL;
3941         r_vertexmesh_d3d9decl = NULL;
3942         switch(vid.renderpath)
3943         {
3944         case RENDERPATH_GL20:
3945         case RENDERPATH_GL13:
3946         case RENDERPATH_GL11:
3947         case RENDERPATH_GLES1:
3948         case RENDERPATH_GLES2:
3949                 break;
3950         case RENDERPATH_D3D9:
3951                 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3952                 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3953                 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3954                 break;
3955         case RENDERPATH_D3D10:
3956                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3957                 break;
3958         case RENDERPATH_D3D11:
3959                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3960                 break;
3961         case RENDERPATH_SOFT:
3962                 break;
3963         }
3964 #endif
3965 }
3966
3967 static void R_Mesh_DestroyVertexDeclarations(void)
3968 {
3969 #ifdef SUPPORTD3D
3970         if (r_vertex3f_d3d9decl)
3971                 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3972         r_vertex3f_d3d9decl = NULL;
3973         if (r_vertexgeneric_d3d9decl)
3974                 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3975         r_vertexgeneric_d3d9decl = NULL;
3976         if (r_vertexmesh_d3d9decl)
3977                 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3978         r_vertexmesh_d3d9decl = NULL;
3979 #endif
3980 }
3981
3982 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3983 {
3984         // upload temporary vertexbuffer for this rendering
3985         if (!gl_state.usevbo_staticvertex)
3986                 vertexbuffer = NULL;
3987         if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3988         {
3989                 if (gl_state.preparevertices_dynamicvertexbuffer)
3990                         R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3991                 else
3992                         gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3993                 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3994         }
3995         switch(vid.renderpath)
3996         {
3997         case RENDERPATH_GL20:
3998         case RENDERPATH_GLES2:
3999                 if (vertexbuffer)
4000                 {
4001                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4002                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4003                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4004                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4005                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4006                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4007                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4008                 }
4009                 else
4010                 {
4011                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4012                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4013                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4014                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4015                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4016                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4017                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4018                 }
4019                 break;
4020         case RENDERPATH_GL13:
4021         case RENDERPATH_GLES1:
4022                 if (vertexbuffer)
4023                 {
4024                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4025                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4026                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4027                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4028                 }
4029                 else
4030                 {
4031                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4032                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4033                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4034                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4035                 }
4036                 break;
4037         case RENDERPATH_GL11:
4038                 if (vertexbuffer)
4039                 {
4040                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4041                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4042                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4043                 }
4044                 else
4045                 {
4046                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4047                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4048                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4049                 }
4050                 break;
4051         case RENDERPATH_D3D9:
4052 #ifdef SUPPORTD3D
4053                 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
4054                 if (vertexbuffer)
4055                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
4056                 else
4057                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4058                 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4059                 gl_state.d3dvertexdata = (void *)vertex3f;
4060                 gl_state.d3dvertexsize = sizeof(float[3]);
4061 #endif
4062                 break;
4063         case RENDERPATH_D3D10:
4064                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4065                 break;
4066         case RENDERPATH_D3D11:
4067                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4068                 break;
4069         case RENDERPATH_SOFT:
4070                 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4071                 DPSOFTRAST_SetColorPointer(NULL, 0);
4072                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
4073                 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4074                 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4075                 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4076                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4077                 break;
4078         }
4079 }
4080
4081
4082
4083 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
4084 {
4085         size_t size;
4086         size = sizeof(r_vertexgeneric_t) * numvertices;
4087         if (gl_state.preparevertices_tempdatamaxsize < size)
4088         {
4089                 gl_state.preparevertices_tempdatamaxsize = size;
4090                 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4091         }
4092         gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
4093         gl_state.preparevertices_numvertices = numvertices;
4094         return gl_state.preparevertices_vertexgeneric;
4095 }
4096
4097 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
4098 {
4099         R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4100         gl_state.preparevertices_vertexgeneric = NULL;
4101         gl_state.preparevertices_numvertices = 0;
4102         return true;
4103 }
4104
4105 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4106 {
4107         int i;
4108         r_vertexgeneric_t *vertex;
4109         switch(vid.renderpath)
4110         {
4111         case RENDERPATH_GL20:
4112         case RENDERPATH_GLES2:
4113                 if (!vid.useinterleavedarrays)
4114                 {
4115                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4116                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4117                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4118                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4119                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4120                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4121                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4122                         return;
4123                 }
4124                 break;
4125         case RENDERPATH_GL11:
4126         case RENDERPATH_GL13:
4127         case RENDERPATH_GLES1:
4128                 if (!vid.useinterleavedarrays)
4129                 {
4130                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4131                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4132                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4133                         if (vid.texunits >= 2)
4134                                 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4135                         if (vid.texunits >= 3)
4136                                 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4137                         return;
4138                 }
4139                 break;
4140         case RENDERPATH_D3D9:
4141         case RENDERPATH_D3D10:
4142         case RENDERPATH_D3D11:
4143                 break;
4144         case RENDERPATH_SOFT:
4145                 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4146                 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4147                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4148                 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4149                 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4150                 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4151                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4152                 return;
4153         }
4154
4155         // no quick path for this case, convert to vertex structs
4156         vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4157         for (i = 0;i < numvertices;i++)
4158                 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4159         if (color4f)
4160         {
4161                 for (i = 0;i < numvertices;i++)
4162                         Vector4Copy(color4f + 4*i, vertex[i].color4f);
4163         }
4164         else
4165         {
4166                 for (i = 0;i < numvertices;i++)
4167                         Vector4Copy(gl_state.color4f, vertex[i].color4f);
4168         }
4169         if (texcoord2f)
4170                 for (i = 0;i < numvertices;i++)
4171                         Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4172         R_Mesh_PrepareVertices_Generic_Unlock();
4173         R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4174 }
4175
4176 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4177 {
4178         // upload temporary vertexbuffer for this rendering
4179         if (!gl_state.usevbo_staticvertex)
4180                 vertexbuffer = NULL;
4181         if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4182         {
4183                 if (gl_state.preparevertices_dynamicvertexbuffer)
4184                         R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4185                 else
4186                         gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4187                 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4188         }
4189         switch(vid.renderpath)
4190         {
4191         case RENDERPATH_GL20:
4192         case RENDERPATH_GLES2:
4193                 if (vertexbuffer)
4194                 {
4195                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4196                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4197                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
4198                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4199                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4200                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4201                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4202                 }
4203                 else
4204                 {
4205                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4206                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4207                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , NULL, 0);
4208                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4209                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4210                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4211                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4212                 }
4213                 break;
4214         case RENDERPATH_GL13:
4215         case RENDERPATH_GLES1:
4216                 if (vertexbuffer)
4217                 {
4218                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4219                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4220                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
4221                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4222                 }
4223                 else
4224                 {
4225                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4226                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4227                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , NULL, 0);
4228                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4229                 }
4230                 break;
4231         case RENDERPATH_GL11:
4232                 if (vertexbuffer)
4233                 {
4234                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4235                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4236                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
4237                 }
4238                 else
4239                 {
4240                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4241                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4242                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , NULL, 0);
4243                 }
4244                 break;
4245         case RENDERPATH_D3D9:
4246 #ifdef SUPPORTD3D
4247                 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4248                 if (vertexbuffer)
4249                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4250                 else
4251                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4252                 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4253                 gl_state.d3dvertexdata = (void *)vertex;
4254                 gl_state.d3dvertexsize = sizeof(*vertex);
4255 #endif
4256                 break;
4257         case RENDERPATH_D3D10:
4258                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4259                 break;
4260         case RENDERPATH_D3D11:
4261                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4262                 break;
4263         case RENDERPATH_SOFT:
4264                 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4265                 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4266                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4267                 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4268                 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4269                 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4270                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4271                 break;
4272         }
4273 }
4274
4275
4276
4277 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4278 {
4279         size_t size;
4280         size = sizeof(r_vertexmesh_t) * numvertices;
4281         if (gl_state.preparevertices_tempdatamaxsize < size)
4282         {
4283                 gl_state.preparevertices_tempdatamaxsize = size;
4284                 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4285         }
4286         gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4287         gl_state.preparevertices_numvertices = numvertices;
4288         return gl_state.preparevertices_vertexmesh;
4289 }
4290
4291 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4292 {
4293         R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4294         gl_state.preparevertices_vertexmesh = NULL;
4295         gl_state.preparevertices_numvertices = 0;
4296         return true;
4297 }
4298
4299 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)
4300 {
4301         int i;
4302         r_vertexmesh_t *vertex;
4303         switch(vid.renderpath)
4304         {
4305         case RENDERPATH_GL20:
4306         case RENDERPATH_GLES2:
4307                 if (!vid.useinterleavedarrays)
4308                 {
4309                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4310                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4311                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4312                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4313                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4314                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4315                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4316                         return;
4317                 }
4318                 break;
4319         case RENDERPATH_GL11:
4320         case RENDERPATH_GL13:
4321         case RENDERPATH_GLES1:
4322                 if (!vid.useinterleavedarrays)
4323                 {
4324                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4325                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4326                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4327                         if (vid.texunits >= 2)
4328                                 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4329                         if (vid.texunits >= 3)
4330                                 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4331                         return;
4332                 }
4333                 break;
4334         case RENDERPATH_D3D9:
4335         case RENDERPATH_D3D10:
4336         case RENDERPATH_D3D11:
4337                 break;
4338         case RENDERPATH_SOFT:
4339                 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4340                 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4341                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4342                 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4343                 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4344                 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4345                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4346                 return;
4347         }
4348
4349         vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4350         for (i = 0;i < numvertices;i++)
4351                 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4352         if (svector3f)
4353                 for (i = 0;i < numvertices;i++)
4354                         VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4355         if (tvector3f)
4356                 for (i = 0;i < numvertices;i++)
4357                         VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4358         if (normal3f)
4359                 for (i = 0;i < numvertices;i++)
4360                         VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4361         if (color4f)
4362         {
4363                 for (i = 0;i < numvertices;i++)
4364                         Vector4Copy(color4f + 4*i, vertex[i].color4f);
4365         }
4366         else
4367         {
4368                 for (i = 0;i < numvertices;i++)
4369                         Vector4Copy(gl_state.color4f, vertex[i].color4f);
4370         }
4371         if (texcoordtexture2f)
4372                 for (i = 0;i < numvertices;i++)
4373                         Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4374         if (texcoordlightmap2f)
4375                 for (i = 0;i < numvertices;i++)
4376                         Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4377         R_Mesh_PrepareVertices_Mesh_Unlock();
4378         R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4379 }
4380
4381 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4382 {
4383         // upload temporary vertexbuffer for this rendering
4384         if (!gl_state.usevbo_staticvertex)
4385                 vertexbuffer = NULL;
4386         if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4387         {
4388                 if (gl_state.preparevertices_dynamicvertexbuffer)
4389                         R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4390                 else
4391                         gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4392                 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4393         }
4394         switch(vid.renderpath)
4395         {
4396         case RENDERPATH_GL20:
4397         case RENDERPATH_GLES2:
4398                 if (vertexbuffer)
4399                 {
4400                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4401                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4402                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
4403                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(*vertex), vertex->svector3f         , vertexbuffer, (int)((unsigned char *)vertex->svector3f          - (unsigned char *)vertex));
4404                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(*vertex), vertex->tvector3f         , vertexbuffer, (int)((unsigned char *)vertex->tvector3f          - (unsigned char *)vertex));
4405                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(*vertex), vertex->normal3f          , vertexbuffer, (int)((unsigned char *)vertex->normal3f           - (unsigned char *)vertex));
4406                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4407                 }
4408                 else
4409                 {
4410                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4411                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4412                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4413                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(*vertex), vertex->svector3f         , NULL, 0);
4414                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(*vertex), vertex->tvector3f         , NULL, 0);
4415                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(*vertex), vertex->normal3f          , NULL, 0);
4416                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4417                 }
4418                 break;
4419         case RENDERPATH_GL13:
4420         case RENDERPATH_GLES1:
4421                 if (vertexbuffer)
4422                 {
4423                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4424                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4425                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
4426                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4427                 }
4428                 else
4429                 {
4430                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4431                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4432                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4433                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4434                 }
4435                 break;
4436         case RENDERPATH_GL11:
4437                 if (vertexbuffer)
4438                 {
4439                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4440                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4441                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
4442                 }
4443                 else
4444                 {
4445                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4446                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4447                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4448                 }
4449                 break;
4450         case RENDERPATH_D3D9:
4451 #ifdef SUPPORTD3D
4452                 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4453                 if (vertexbuffer)
4454                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4455                 else
4456                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4457                 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4458                 gl_state.d3dvertexdata = (void *)vertex;
4459                 gl_state.d3dvertexsize = sizeof(*vertex);
4460 #endif
4461                 break;
4462         case RENDERPATH_D3D10:
4463                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4464                 break;
4465         case RENDERPATH_D3D11:
4466                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4467                 break;
4468         case RENDERPATH_SOFT:
4469                 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4470                 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4471                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4472                 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4473                 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4474                 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4475                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);
4476                 break;
4477         }
4478 }
4479
4480 void GL_BlendEquationSubtract(qboolean negated)
4481 {
4482         if(negated)
4483         {
4484                 switch(vid.renderpath)
4485                 {
4486                 case RENDERPATH_GL11:
4487                 case RENDERPATH_GL13:
4488                 case RENDERPATH_GL20:
4489                 case RENDERPATH_GLES1:
4490                 case RENDERPATH_GLES2:
4491                         qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4492                         break;
4493                 case RENDERPATH_D3D9:
4494 #ifdef SUPPORTD3D
4495                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
4496 #endif
4497                         break;
4498                 case RENDERPATH_D3D10:
4499                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4500                         break;
4501                 case RENDERPATH_D3D11:
4502                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4503                         break;
4504                 case RENDERPATH_SOFT:
4505                         DPSOFTRAST_BlendSubtract(true);
4506                         break;
4507                 }
4508         }
4509         else
4510         {
4511                 switch(vid.renderpath)
4512                 {
4513                 case RENDERPATH_GL11:
4514                 case RENDERPATH_GL13:
4515                 case RENDERPATH_GL20:
4516                 case RENDERPATH_GLES1:
4517                 case RENDERPATH_GLES2:
4518                         qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4519                         break;
4520                 case RENDERPATH_D3D9:
4521 #ifdef SUPPORTD3D
4522                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_ADD);
4523 #endif
4524                         break;
4525                 case RENDERPATH_D3D10:
4526                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4527                         break;
4528                 case RENDERPATH_D3D11:
4529                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4530                         break;
4531                 case RENDERPATH_SOFT:
4532                         DPSOFTRAST_BlendSubtract(false);
4533                         break;
4534                 }
4535         }
4536 }