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