]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_backend.c
overhauling a lot of functions to allow fbo rendering
[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 (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1268                 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1269                 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1270                 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1271                 return temp;
1272         case RENDERPATH_D3D9:
1273         case RENDERPATH_D3D10:
1274         case RENDERPATH_D3D11:
1275                 return 1;
1276         case RENDERPATH_SOFT:
1277                 return 1;
1278         }
1279         return 0;
1280 }
1281
1282 void R_Mesh_DestroyFramebufferObject(int fbo)
1283 {
1284         switch(vid.renderpath)
1285         {
1286         case RENDERPATH_GL11:
1287         case RENDERPATH_GL13:
1288         case RENDERPATH_GL20:
1289         case RENDERPATH_GLES1:
1290         case RENDERPATH_GLES2:
1291                 if (fbo)
1292                         qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1293                 break;
1294         case RENDERPATH_D3D9:
1295         case RENDERPATH_D3D10:
1296         case RENDERPATH_D3D11:
1297                 break;
1298         case RENDERPATH_SOFT:
1299                 break;
1300         }
1301 }
1302
1303 #ifdef SUPPORTD3D
1304 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1305 {
1306 // 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)
1307         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)
1308                 return;
1309
1310         gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1311         if (gl_state.d3drt_depthsurface != depthsurface)
1312         {
1313                 gl_state.d3drt_depthsurface = depthsurface;
1314                 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1315         }
1316         if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1317         {
1318                 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1319                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1320         }
1321         if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1322         {
1323                 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1324                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1325         }
1326         if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1327         {
1328                 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1329                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1330         }
1331         if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1332         {
1333                 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1334                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1335         }
1336 }
1337 #endif
1338
1339 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1340 {
1341         unsigned int i;
1342         unsigned int j;
1343         rtexture_t *textures[5];
1344         Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1345         textures[4] = depthtexture;
1346         // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1347         for (j = 0;j < 5;j++)
1348                 if (textures[j])
1349                         for (i = 0;i < vid.teximageunits;i++)
1350                                 if (gl_state.units[i].texture == textures[j])
1351                                         R_Mesh_TexBind(i, NULL);
1352         // set up framebuffer object or render targets for the active rendering API
1353         switch(vid.renderpath)
1354         {
1355         case RENDERPATH_GL11:
1356         case RENDERPATH_GL13:
1357         case RENDERPATH_GL20:
1358         case RENDERPATH_GLES1:
1359         case RENDERPATH_GLES2:
1360                 if (gl_state.framebufferobject != fbo)
1361                 {
1362                         gl_state.framebufferobject = fbo;
1363                         qglBindFramebufferEXT(GL_FRAMEBUFFER, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1364                 }
1365                 break;
1366         case RENDERPATH_D3D9:
1367 #ifdef SUPPORTD3D
1368                 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1369                 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1370                 if (fbo)
1371                 {
1372                         IDirect3DSurface9 *colorsurfaces[4];
1373                         for (i = 0;i < 4;i++)
1374                         {
1375                                 colorsurfaces[i] = NULL;
1376                                 if (textures[i])
1377                                         IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1378                         }
1379                         // set the render targets for real
1380                         R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1381                         // release the texture surface levels (they won't be lost while bound...)
1382                         for (i = 0;i < 4;i++)
1383                                 if (textures[i])
1384                                         IDirect3DSurface9_Release(colorsurfaces[i]);
1385                 }
1386                 else
1387                         R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1388 #endif
1389                 break;
1390         case RENDERPATH_D3D10:
1391                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1392                 break;
1393         case RENDERPATH_D3D11:
1394                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1395                 break;
1396         case RENDERPATH_SOFT:
1397                 if (fbo)
1398                 {
1399                         int width, height;
1400                         unsigned int *pointers[5];
1401                         memset(pointers, 0, sizeof(pointers));
1402                         for (i = 0;i < 5;i++)
1403                                 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1404                         width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1405                         height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1406                         DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1407                 }
1408                 else
1409                         DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1410                 break;
1411         }
1412 }
1413
1414 #ifdef SUPPORTD3D
1415 static int d3dcmpforglfunc(int f)
1416 {
1417         switch(f)
1418         {
1419         case GL_NEVER: return D3DCMP_NEVER;
1420         case GL_LESS: return D3DCMP_LESS;
1421         case GL_EQUAL: return D3DCMP_EQUAL;
1422         case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1423         case GL_GREATER: return D3DCMP_GREATER;
1424         case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1425         case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1426         case GL_ALWAYS: return D3DCMP_ALWAYS;
1427         default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1428         }
1429 }
1430
1431 static int d3dstencilopforglfunc(int f)
1432 {
1433         switch(f)
1434         {
1435         case GL_KEEP: return D3DSTENCILOP_KEEP;
1436         case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1437         case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1438         default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1439         }
1440 }
1441 #endif
1442
1443 extern cvar_t r_transparent_alphatocoverage;
1444
1445 static void GL_Backend_ResetState(void)
1446 {
1447         unsigned int i;
1448         gl_state.active = true;
1449         gl_state.depthtest = true;
1450         gl_state.alphatest = false;
1451         gl_state.alphafunc = GL_GEQUAL;
1452         gl_state.alphafuncvalue = 0.5f;
1453         gl_state.alphatocoverage = false;
1454         gl_state.blendfunc1 = GL_ONE;
1455         gl_state.blendfunc2 = GL_ZERO;
1456         gl_state.blend = false;
1457         gl_state.depthmask = GL_TRUE;
1458         gl_state.colormask = 15;
1459         gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1460         gl_state.lockrange_first = 0;
1461         gl_state.lockrange_count = 0;
1462         gl_state.cullface = GL_FRONT;
1463         gl_state.cullfaceenable = false;
1464         gl_state.polygonoffset[0] = 0;
1465         gl_state.polygonoffset[1] = 0;
1466         gl_state.framebufferobject = 0;
1467         gl_state.depthfunc = GL_LEQUAL;
1468
1469         switch(vid.renderpath)
1470         {
1471         case RENDERPATH_D3D9:
1472 #ifdef SUPPORTD3D
1473                 {
1474                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1475                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1476                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1477                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1478                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1479                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1480                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1481                 }
1482 #endif
1483                 break;
1484         case RENDERPATH_D3D10:
1485                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1486                 break;
1487         case RENDERPATH_D3D11:
1488                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1489                 break;
1490         case RENDERPATH_GL11:
1491         case RENDERPATH_GL13:
1492         case RENDERPATH_GLES1:
1493 #ifdef GL_ALPHA_TEST
1494                 CHECKGLERROR
1495
1496                 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1497                 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1498                 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1499                 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1500                 qglDisable(GL_BLEND);CHECKGLERROR
1501                 qglCullFace(gl_state.cullface);CHECKGLERROR
1502                 qglDisable(GL_CULL_FACE);CHECKGLERROR
1503                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1504                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1505                 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1506                 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1507
1508                 if (vid.support.arb_vertex_buffer_object)
1509                 {
1510                         qglBindBufferARB(GL_ARRAY_BUFFER, 0);
1511                         qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
1512                 }
1513
1514                 if (vid.support.ext_framebuffer_object)
1515                 {
1516                         //qglBindRenderbufferEXT(GL_RENDERBUFFER, 0);
1517                         qglBindFramebufferEXT(GL_FRAMEBUFFER, 0);
1518                 }
1519
1520                 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1521                 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1522
1523                 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1524                 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1525                 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1526
1527                 if (vid.support.ext_framebuffer_object)
1528                         qglBindFramebufferEXT(GL_FRAMEBUFFER, gl_state.framebufferobject);
1529
1530                 gl_state.unit = MAX_TEXTUREUNITS;
1531                 gl_state.clientunit = MAX_TEXTUREUNITS;
1532                 for (i = 0;i < vid.texunits;i++)
1533                 {
1534                         GL_ActiveTexture(i);
1535                         GL_ClientActiveTexture(i);
1536                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1537                         qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1538                         if (vid.support.ext_texture_3d)
1539                         {
1540                                 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1541                                 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1542                         }
1543                         if (vid.support.arb_texture_cube_map)
1544                         {
1545                                 qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
1546                                 qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
1547                         }
1548                         GL_BindVBO(0);
1549                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1550                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1551                         qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1552                         qglLoadIdentity();CHECKGLERROR
1553                         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1554                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1555                 }
1556                 CHECKGLERROR
1557 #endif
1558                 break;
1559         case RENDERPATH_SOFT:
1560                 DPSOFTRAST_ColorMask(1,1,1,1);
1561                 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1562                 DPSOFTRAST_CullFace(gl_state.cullface);
1563                 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1564                 DPSOFTRAST_DepthMask(gl_state.depthmask);
1565                 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1566                 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1567                 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1568                 break;
1569         case RENDERPATH_GL20:
1570         case RENDERPATH_GLES2:
1571                 CHECKGLERROR
1572                 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1573                 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1574                 qglDisable(GL_BLEND);CHECKGLERROR
1575                 qglCullFace(gl_state.cullface);CHECKGLERROR
1576                 qglDisable(GL_CULL_FACE);CHECKGLERROR
1577                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1578                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1579                 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1580                 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1581                 if (vid.support.arb_vertex_buffer_object)
1582                 {
1583                         qglBindBufferARB(GL_ARRAY_BUFFER, 0);
1584                         qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
1585                 }
1586                 if (vid.support.ext_framebuffer_object)
1587                         qglBindFramebufferEXT(GL_FRAMEBUFFER, gl_state.defaultframebufferobject);
1588                 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1589                 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1590                 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1591                 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1592                 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1593                 gl_state.unit = MAX_TEXTUREUNITS;
1594                 gl_state.clientunit = MAX_TEXTUREUNITS;
1595                 for (i = 0;i < vid.teximageunits;i++)
1596                 {
1597                         GL_ActiveTexture(i);
1598                         qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1599                         if (vid.support.ext_texture_3d)
1600                         {
1601                                 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1602                         }
1603                         if (vid.support.arb_texture_cube_map)
1604                         {
1605                                 qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
1606                         }
1607                 }
1608                 for (i = 0;i < vid.texarrayunits;i++)
1609                 {
1610                         GL_BindVBO(0);
1611                         qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1612                         qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1613                 }
1614                 CHECKGLERROR
1615                 break;
1616         }
1617 }
1618
1619 void GL_ActiveTexture(unsigned int num)
1620 {
1621         if (gl_state.unit != num)
1622         {
1623                 gl_state.unit = num;
1624                 switch(vid.renderpath)
1625                 {
1626                 case RENDERPATH_GL11:
1627                 case RENDERPATH_GL13:
1628                 case RENDERPATH_GL20:
1629                 case RENDERPATH_GLES1:
1630                 case RENDERPATH_GLES2:
1631                         if (qglActiveTexture)
1632                         {
1633                                 CHECKGLERROR
1634                                 qglActiveTexture(GL_TEXTURE0 + gl_state.unit);
1635                                 CHECKGLERROR
1636                         }
1637                         break;
1638                 case RENDERPATH_D3D9:
1639                 case RENDERPATH_D3D10:
1640                 case RENDERPATH_D3D11:
1641                         break;
1642                 case RENDERPATH_SOFT:
1643                         break;
1644                 }
1645         }
1646 }
1647
1648 void GL_ClientActiveTexture(unsigned int num)
1649 {
1650         if (gl_state.clientunit != num)
1651         {
1652                 gl_state.clientunit = num;
1653                 switch(vid.renderpath)
1654                 {
1655                 case RENDERPATH_GL11:
1656                 case RENDERPATH_GL13:
1657                 case RENDERPATH_GLES1:
1658                         if (qglActiveTexture)
1659                         {
1660                                 CHECKGLERROR
1661                                 qglClientActiveTexture(GL_TEXTURE0 + gl_state.clientunit);
1662                                 CHECKGLERROR
1663                         }
1664                         break;
1665                 case RENDERPATH_D3D9:
1666                 case RENDERPATH_D3D10:
1667                 case RENDERPATH_D3D11:
1668                         break;
1669                 case RENDERPATH_SOFT:
1670                         break;
1671                 case RENDERPATH_GL20:
1672                 case RENDERPATH_GLES2:
1673                         break;
1674                 }
1675         }
1676 }
1677
1678 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1679 {
1680         if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1681         {
1682                 qboolean blendenable;
1683                 gl_state.blendfunc1 = blendfunc1;
1684                 gl_state.blendfunc2 = blendfunc2;
1685                 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1686                 switch(vid.renderpath)
1687                 {
1688                 case RENDERPATH_GL11:
1689                 case RENDERPATH_GL13:
1690                 case RENDERPATH_GL20:
1691                 case RENDERPATH_GLES1:
1692                 case RENDERPATH_GLES2:
1693                         CHECKGLERROR
1694                         qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1695                         if (gl_state.blend != blendenable)
1696                         {
1697                                 gl_state.blend = blendenable;
1698                                 if (!gl_state.blend)
1699                                 {
1700                                         qglDisable(GL_BLEND);CHECKGLERROR
1701                                 }
1702                                 else
1703                                 {
1704                                         qglEnable(GL_BLEND);CHECKGLERROR
1705                                 }
1706                         }
1707                         break;
1708                 case RENDERPATH_D3D9:
1709 #ifdef SUPPORTD3D
1710                         {
1711                                 int i;
1712                                 int glblendfunc[2];
1713                                 D3DBLEND d3dblendfunc[2];
1714                                 glblendfunc[0] = gl_state.blendfunc1;
1715                                 glblendfunc[1] = gl_state.blendfunc2;
1716                                 for (i = 0;i < 2;i++)
1717                                 {
1718                                         switch(glblendfunc[i])
1719                                         {
1720                                         case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1721                                         case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1722                                         case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1723                                         case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1724                                         case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1725                                         case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1726                                         case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1727                                         case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1728                                         case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1729                                         case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1730                                         }
1731                                 }
1732                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1733                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1734                                 if (gl_state.blend != blendenable)
1735                                 {
1736                                         gl_state.blend = blendenable;
1737                                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1738                                 }
1739                         }
1740 #endif
1741                         break;
1742                 case RENDERPATH_D3D10:
1743                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1744                         break;
1745                 case RENDERPATH_D3D11:
1746                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1747                         break;
1748                 case RENDERPATH_SOFT:
1749                         DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1750                         break;
1751                 }
1752         }
1753 }
1754
1755 void GL_DepthMask(int state)
1756 {
1757         if (gl_state.depthmask != state)
1758         {
1759                 gl_state.depthmask = state;
1760                 switch(vid.renderpath)
1761                 {
1762                 case RENDERPATH_GL11:
1763                 case RENDERPATH_GL13:
1764                 case RENDERPATH_GL20:
1765                 case RENDERPATH_GLES1:
1766                 case RENDERPATH_GLES2:
1767                         CHECKGLERROR
1768                         qglDepthMask(gl_state.depthmask);CHECKGLERROR
1769                         break;
1770                 case RENDERPATH_D3D9:
1771 #ifdef SUPPORTD3D
1772                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1773 #endif
1774                         break;
1775                 case RENDERPATH_D3D10:
1776                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1777                         break;
1778                 case RENDERPATH_D3D11:
1779                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1780                         break;
1781                 case RENDERPATH_SOFT:
1782                         DPSOFTRAST_DepthMask(gl_state.depthmask);
1783                         break;
1784                 }
1785         }
1786 }
1787
1788 void GL_DepthTest(int state)
1789 {
1790         if (gl_state.depthtest != state)
1791         {
1792                 gl_state.depthtest = state;
1793                 switch(vid.renderpath)
1794                 {
1795                 case RENDERPATH_GL11:
1796                 case RENDERPATH_GL13:
1797                 case RENDERPATH_GL20:
1798                 case RENDERPATH_GLES1:
1799                 case RENDERPATH_GLES2:
1800                         CHECKGLERROR
1801                         if (gl_state.depthtest)
1802                         {
1803                                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1804                         }
1805                         else
1806                         {
1807                                 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1808                         }
1809                         break;
1810                 case RENDERPATH_D3D9:
1811 #ifdef SUPPORTD3D
1812                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1813 #endif
1814                         break;
1815                 case RENDERPATH_D3D10:
1816                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1817                         break;
1818                 case RENDERPATH_D3D11:
1819                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1820                         break;
1821                 case RENDERPATH_SOFT:
1822                         DPSOFTRAST_DepthTest(gl_state.depthtest);
1823                         break;
1824                 }
1825         }
1826 }
1827
1828 void GL_DepthFunc(int state)
1829 {
1830         if (gl_state.depthfunc != state)
1831         {
1832                 gl_state.depthfunc = state;
1833                 switch(vid.renderpath)
1834                 {
1835                 case RENDERPATH_GL11:
1836                 case RENDERPATH_GL13:
1837                 case RENDERPATH_GL20:
1838                 case RENDERPATH_GLES1:
1839                 case RENDERPATH_GLES2:
1840                         CHECKGLERROR
1841                         qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1842                         break;
1843                 case RENDERPATH_D3D9:
1844 #ifdef SUPPORTD3D
1845                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1846 #endif
1847                         break;
1848                 case RENDERPATH_D3D10:
1849                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1850                         break;
1851                 case RENDERPATH_D3D11:
1852                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1853                         break;
1854                 case RENDERPATH_SOFT:
1855                         DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1856                         break;
1857                 }
1858         }
1859 }
1860
1861 void GL_DepthRange(float nearfrac, float farfrac)
1862 {
1863         if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1864         {
1865                 gl_state.depthrange[0] = nearfrac;
1866                 gl_state.depthrange[1] = farfrac;
1867                 switch(vid.renderpath)
1868                 {
1869                 case RENDERPATH_GL11:
1870                 case RENDERPATH_GL13:
1871                 case RENDERPATH_GL20:
1872                 case RENDERPATH_GLES1:
1873                 case RENDERPATH_GLES2:
1874 #ifdef USE_GLES2
1875                         qglDepthRangef(gl_state.depthrange[0], gl_state.depthrange[1]);
1876 #else
1877                         qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1878 #endif
1879                         break;
1880                 case RENDERPATH_D3D9:
1881 #ifdef SUPPORTD3D
1882                         {
1883                                 D3DVIEWPORT9 d3dviewport;
1884                                 d3dviewport.X = gl_viewport.x;
1885                                 d3dviewport.Y = gl_viewport.y;
1886                                 d3dviewport.Width = gl_viewport.width;
1887                                 d3dviewport.Height = gl_viewport.height;
1888                                 d3dviewport.MinZ = gl_state.depthrange[0];
1889                                 d3dviewport.MaxZ = gl_state.depthrange[1];
1890                                 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1891                         }
1892 #endif
1893                         break;
1894                 case RENDERPATH_D3D10:
1895                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1896                         break;
1897                 case RENDERPATH_D3D11:
1898                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1899                         break;
1900                 case RENDERPATH_SOFT:
1901                         DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1902                         break;
1903                 }
1904         }
1905 }
1906
1907 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)
1908 {
1909         switch (vid.renderpath)
1910         {
1911         case RENDERPATH_GL11:
1912         case RENDERPATH_GL13:
1913         case RENDERPATH_GL20:
1914         case RENDERPATH_GLES1:
1915         case RENDERPATH_GLES2:
1916                 CHECKGLERROR
1917                 if (enable)
1918                 {
1919                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1920                 }
1921                 else
1922                 {
1923                         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1924                 }
1925                 if (vid.support.ati_separate_stencil)
1926                 {
1927                         qglStencilMask(writemask);CHECKGLERROR
1928                         qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1929                         qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1930                         qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1931                 }
1932                 else if (vid.support.ext_stencil_two_side)
1933                 {
1934 #ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
1935                         qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1936                         qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1937                         qglStencilMask(writemask);CHECKGLERROR
1938                         qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1939                         qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1940                         qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1941                         qglStencilMask(writemask);CHECKGLERROR
1942                         qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1943                         qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1944 #endif
1945                 }
1946                 break;
1947         case RENDERPATH_D3D9:
1948 #ifdef SUPPORTD3D
1949                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1950                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1951                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1952                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1953                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1954                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1955                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1956                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1957                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1958                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1959                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1960                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1961                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1962 #endif
1963                 break;
1964         case RENDERPATH_D3D10:
1965                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1966                 break;
1967         case RENDERPATH_D3D11:
1968                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1969                 break;
1970         case RENDERPATH_SOFT:
1971                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1972                 break;
1973         }
1974 }
1975
1976 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1977 {
1978         switch (vid.renderpath)
1979         {
1980         case RENDERPATH_GL11:
1981         case RENDERPATH_GL13:
1982         case RENDERPATH_GL20:
1983         case RENDERPATH_GLES1:
1984         case RENDERPATH_GLES2:
1985                 CHECKGLERROR
1986                 if (enable)
1987                 {
1988                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1989                 }
1990                 else
1991                 {
1992                         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1993                 }
1994                 if (vid.support.ext_stencil_two_side)
1995                 {
1996 #ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
1997                         qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1998 #endif
1999                 }
2000                 qglStencilMask(writemask);CHECKGLERROR
2001                 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
2002                 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
2003                 CHECKGLERROR
2004                 break;
2005         case RENDERPATH_D3D9:
2006 #ifdef SUPPORTD3D
2007                 if (vid.support.ati_separate_stencil)
2008                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
2009                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
2010                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
2011                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
2012                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
2013                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
2014                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
2015                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
2016                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
2017 #endif
2018                 break;
2019         case RENDERPATH_D3D10:
2020                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2021                 break;
2022         case RENDERPATH_D3D11:
2023                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2024                 break;
2025         case RENDERPATH_SOFT:
2026                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027                 break;
2028         }
2029 }
2030
2031 void GL_PolygonOffset(float planeoffset, float depthoffset)
2032 {
2033         if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
2034         {
2035                 gl_state.polygonoffset[0] = planeoffset;
2036                 gl_state.polygonoffset[1] = depthoffset;
2037                 switch(vid.renderpath)
2038                 {
2039                 case RENDERPATH_GL11:
2040                 case RENDERPATH_GL13:
2041                 case RENDERPATH_GL20:
2042                 case RENDERPATH_GLES1:
2043                 case RENDERPATH_GLES2:
2044                         qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2045                         break;
2046                 case RENDERPATH_D3D9:
2047 #ifdef SUPPORTD3D
2048                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
2049                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
2050 #endif
2051                         break;
2052                 case RENDERPATH_D3D10:
2053                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2054                         break;
2055                 case RENDERPATH_D3D11:
2056                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2057                         break;
2058                 case RENDERPATH_SOFT:
2059                         DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2060                         break;
2061                 }
2062         }
2063 }
2064
2065 void GL_SetMirrorState(qboolean state)
2066 {
2067         if (v_flipped_state != state)
2068         {
2069                 v_flipped_state = state;
2070                 if (gl_state.cullface == GL_BACK)
2071                         gl_state.cullface = GL_FRONT;
2072                 else if (gl_state.cullface == GL_FRONT)
2073                         gl_state.cullface = GL_BACK;
2074                 else
2075                         return;
2076                 switch(vid.renderpath)
2077                 {
2078                 case RENDERPATH_GL11:
2079                 case RENDERPATH_GL13:
2080                 case RENDERPATH_GL20:
2081                 case RENDERPATH_GLES1:
2082                 case RENDERPATH_GLES2:
2083                         qglCullFace(gl_state.cullface);CHECKGLERROR
2084                         break;
2085                 case RENDERPATH_D3D9:
2086 #ifdef SUPPORTD3D
2087                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2088 #endif
2089                         break;
2090                 case RENDERPATH_D3D10:
2091                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2092                         break;
2093                 case RENDERPATH_D3D11:
2094                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2095                         break;
2096                 case RENDERPATH_SOFT:
2097                         DPSOFTRAST_CullFace(gl_state.cullface);
2098                         break;
2099                 }
2100         }
2101 }
2102
2103 void GL_CullFace(int state)
2104 {
2105         if(v_flipped_state)
2106         {
2107                 if(state == GL_FRONT)
2108                         state = GL_BACK;
2109                 else if(state == GL_BACK)
2110                         state = GL_FRONT;
2111         }
2112
2113         switch(vid.renderpath)
2114         {
2115         case RENDERPATH_GL11:
2116         case RENDERPATH_GL13:
2117         case RENDERPATH_GL20:
2118         case RENDERPATH_GLES1:
2119         case RENDERPATH_GLES2:
2120                 CHECKGLERROR
2121
2122                 if (state != GL_NONE)
2123                 {
2124                         if (!gl_state.cullfaceenable)
2125                         {
2126                                 gl_state.cullfaceenable = true;
2127                                 qglEnable(GL_CULL_FACE);CHECKGLERROR
2128                         }
2129                         if (gl_state.cullface != state)
2130                         {
2131                                 gl_state.cullface = state;
2132                                 qglCullFace(gl_state.cullface);CHECKGLERROR
2133                         }
2134                 }
2135                 else
2136                 {
2137                         if (gl_state.cullfaceenable)
2138                         {
2139                                 gl_state.cullfaceenable = false;
2140                                 qglDisable(GL_CULL_FACE);CHECKGLERROR
2141                         }
2142                 }
2143                 break;
2144         case RENDERPATH_D3D9:
2145 #ifdef SUPPORTD3D
2146                 if (gl_state.cullface != state)
2147                 {
2148                         gl_state.cullface = state;
2149                         switch(gl_state.cullface)
2150                         {
2151                         case GL_NONE:
2152                                 gl_state.cullfaceenable = false;
2153                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2154                                 break;
2155                         case GL_FRONT:
2156                                 gl_state.cullfaceenable = true;
2157                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2158                                 break;
2159                         case GL_BACK:
2160                                 gl_state.cullfaceenable = true;
2161                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2162                                 break;
2163                         }
2164                 }
2165 #endif
2166                 break;
2167         case RENDERPATH_D3D10:
2168                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2169                 break;
2170         case RENDERPATH_D3D11:
2171                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2172                 break;
2173         case RENDERPATH_SOFT:
2174                 if (gl_state.cullface != state)
2175                 {
2176                         gl_state.cullface = state;
2177                         gl_state.cullfaceenable = state != GL_NONE ? true : false;
2178                         DPSOFTRAST_CullFace(gl_state.cullface);
2179                 }
2180                 break;
2181         }
2182 }
2183
2184 void GL_AlphaTest(int state)
2185 {
2186         if (gl_state.alphatest != state)
2187         {
2188                 gl_state.alphatest = state;
2189                 switch(vid.renderpath)
2190                 {
2191                 case RENDERPATH_GL11:
2192                 case RENDERPATH_GL13:
2193                 case RENDERPATH_GLES1:
2194 #ifdef GL_ALPHA_TEST
2195                         // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2196                         CHECKGLERROR
2197                         if (gl_state.alphatest)
2198                         {
2199                                 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2200                         }
2201                         else
2202                         {
2203                                 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2204                         }
2205 #endif
2206                         break;
2207                 case RENDERPATH_D3D9:
2208                 case RENDERPATH_D3D10:
2209                 case RENDERPATH_D3D11:
2210                 case RENDERPATH_SOFT:
2211                 case RENDERPATH_GL20:
2212                 case RENDERPATH_GLES2:
2213                         break;
2214                 }
2215         }
2216 }
2217
2218 void GL_AlphaToCoverage(qboolean state)
2219 {
2220         if (gl_state.alphatocoverage != state)
2221         {
2222                 gl_state.alphatocoverage = state;
2223                 switch(vid.renderpath)
2224                 {
2225                 case RENDERPATH_GL11:
2226                 case RENDERPATH_GL13:
2227                 case RENDERPATH_GLES1:
2228                 case RENDERPATH_GLES2:
2229                 case RENDERPATH_D3D9:
2230                 case RENDERPATH_D3D10:
2231                 case RENDERPATH_D3D11:
2232                 case RENDERPATH_SOFT:
2233                         break;
2234                 case RENDERPATH_GL20:
2235 #ifdef GL_SAMPLE_ALPHA_TO_COVERAGE_ARB
2236                         // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
2237                         CHECKGLERROR
2238                         if (gl_state.alphatocoverage)
2239                         {
2240                                 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2241 //                              qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2242                         }
2243                         else
2244                         {
2245                                 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2246 //                              qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2247                         }
2248 #endif
2249                         break;
2250                 }
2251         }
2252 }
2253
2254 void GL_ColorMask(int r, int g, int b, int a)
2255 {
2256         // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2257         int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2258         if (gl_state.colormask != state)
2259         {
2260                 gl_state.colormask = state;
2261                 switch(vid.renderpath)
2262                 {
2263                 case RENDERPATH_GL11:
2264                 case RENDERPATH_GL13:
2265                 case RENDERPATH_GL20:
2266                 case RENDERPATH_GLES1:
2267                 case RENDERPATH_GLES2:
2268                         CHECKGLERROR
2269                         qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2270                         break;
2271                 case RENDERPATH_D3D9:
2272 #ifdef SUPPORTD3D
2273                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2274 #endif
2275                         break;
2276                 case RENDERPATH_D3D10:
2277                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2278                         break;
2279                 case RENDERPATH_D3D11:
2280                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2281                         break;
2282                 case RENDERPATH_SOFT:
2283                         DPSOFTRAST_ColorMask(r, g, b, a);
2284                         break;
2285                 }
2286         }
2287 }
2288
2289 void GL_Color(float cr, float cg, float cb, float ca)
2290 {
2291         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)
2292         {
2293                 gl_state.color4f[0] = cr;
2294                 gl_state.color4f[1] = cg;
2295                 gl_state.color4f[2] = cb;
2296                 gl_state.color4f[3] = ca;
2297                 switch(vid.renderpath)
2298                 {
2299                 case RENDERPATH_GL11:
2300                 case RENDERPATH_GL13:
2301                 case RENDERPATH_GLES1:
2302                         CHECKGLERROR
2303                         qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2304                         CHECKGLERROR
2305                         break;
2306                 case RENDERPATH_D3D9:
2307                 case RENDERPATH_D3D10:
2308                 case RENDERPATH_D3D11:
2309                         // no equivalent in D3D
2310                         break;
2311                 case RENDERPATH_SOFT:
2312                         DPSOFTRAST_Color4f(cr, cg, cb, ca);
2313                         break;
2314                 case RENDERPATH_GL20:
2315                 case RENDERPATH_GLES2:
2316                         qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2317                         break;
2318                 }
2319         }
2320 }
2321
2322 void GL_Scissor (int x, int y, int width, int height)
2323 {
2324         switch(vid.renderpath)
2325         {
2326         case RENDERPATH_GL11:
2327         case RENDERPATH_GL13:
2328         case RENDERPATH_GL20:
2329         case RENDERPATH_GLES1:
2330         case RENDERPATH_GLES2:
2331                 CHECKGLERROR
2332                 qglScissor(x, y,width,height);
2333                 CHECKGLERROR
2334                 break;
2335         case RENDERPATH_D3D9:
2336 #ifdef SUPPORTD3D
2337                 {
2338                         RECT d3drect;
2339                         d3drect.left = x;
2340                         d3drect.top = y;
2341                         d3drect.right = x + width;
2342                         d3drect.bottom = y + height;
2343                         IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2344                 }
2345 #endif
2346                 break;
2347         case RENDERPATH_D3D10:
2348                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2349                 break;
2350         case RENDERPATH_D3D11:
2351                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2352                 break;
2353         case RENDERPATH_SOFT:
2354                 DPSOFTRAST_Scissor(x, y, width, height);
2355                 break;
2356         }
2357 }
2358
2359 void GL_ScissorTest(int state)
2360 {
2361         if (gl_state.scissortest != state)
2362         {
2363                 gl_state.scissortest = state;
2364                 switch(vid.renderpath)
2365                 {
2366                 case RENDERPATH_GL11:
2367                 case RENDERPATH_GL13:
2368                 case RENDERPATH_GL20:
2369                 case RENDERPATH_GLES1:
2370                 case RENDERPATH_GLES2:
2371                         CHECKGLERROR
2372                         if(gl_state.scissortest)
2373                                 qglEnable(GL_SCISSOR_TEST);
2374                         else
2375                                 qglDisable(GL_SCISSOR_TEST);
2376                         CHECKGLERROR
2377                         break;
2378                 case RENDERPATH_D3D9:
2379 #ifdef SUPPORTD3D
2380                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2381 #endif
2382                         break;
2383                 case RENDERPATH_D3D10:
2384                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2385                         break;
2386                 case RENDERPATH_D3D11:
2387                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2388                         break;
2389                 case RENDERPATH_SOFT:
2390                         DPSOFTRAST_ScissorTest(gl_state.scissortest);
2391                         break;
2392                 }
2393         }
2394 }
2395
2396 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2397 {
2398         static const float blackcolor[4] = {0, 0, 0, 0};
2399         // prevent warnings when trying to clear a buffer that does not exist
2400         if (!colorvalue)
2401                 colorvalue = blackcolor;
2402         if (!vid.stencil)
2403         {
2404                 mask &= ~GL_STENCIL_BUFFER_BIT;
2405                 stencilvalue = 0;
2406         }
2407         switch(vid.renderpath)
2408         {
2409         case RENDERPATH_GL11:
2410         case RENDERPATH_GL13:
2411         case RENDERPATH_GL20:
2412         case RENDERPATH_GLES1:
2413         case RENDERPATH_GLES2:
2414                 CHECKGLERROR
2415                 if (mask & GL_COLOR_BUFFER_BIT)
2416                 {
2417                         qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2418                 }
2419                 if (mask & GL_DEPTH_BUFFER_BIT)
2420                 {
2421 #ifdef USE_GLES2
2422                         qglClearDepthf(depthvalue);CHECKGLERROR
2423 #else
2424                         qglClearDepth(depthvalue);CHECKGLERROR
2425 #endif
2426                 }
2427                 if (mask & GL_STENCIL_BUFFER_BIT)
2428                 {
2429                         qglClearStencil(stencilvalue);CHECKGLERROR
2430                 }
2431                 qglClear(mask);CHECKGLERROR
2432                 break;
2433         case RENDERPATH_D3D9:
2434 #ifdef SUPPORTD3D
2435                 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);
2436 #endif
2437                 break;
2438         case RENDERPATH_D3D10:
2439                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2440                 break;
2441         case RENDERPATH_D3D11:
2442                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2443                 break;
2444         case RENDERPATH_SOFT:
2445                 if (mask & GL_COLOR_BUFFER_BIT)
2446                         DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2447                 if (mask & GL_DEPTH_BUFFER_BIT)
2448                         DPSOFTRAST_ClearDepth(depthvalue);
2449                 break;
2450         }
2451 }
2452
2453 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2454 {
2455         switch(vid.renderpath)
2456         {
2457         case RENDERPATH_GL11:
2458         case RENDERPATH_GL13:
2459         case RENDERPATH_GL20:
2460         case RENDERPATH_GLES1:
2461         case RENDERPATH_GLES2:
2462                 CHECKGLERROR
2463                 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2464                 break;
2465         case RENDERPATH_D3D9:
2466 #ifdef SUPPORTD3D
2467                 {
2468                         // LordHavoc: we can't directly download the backbuffer because it may be
2469                         // multisampled, and it may not be lockable, so we blit it to a lockable
2470                         // surface of the same dimensions (but without multisample) to resolve the
2471                         // multisample buffer to a normal image, and then lock that...
2472                         IDirect3DSurface9 *stretchsurface = NULL;
2473                         if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2474                         {
2475                                 D3DLOCKED_RECT lockedrect;
2476                                 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2477                                 {
2478                                         if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2479                                         {
2480                                                 int line;
2481                                                 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2482                                                 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2483                                                         memcpy(outpixels + line * width * 4, row, width * 4);
2484                                                 IDirect3DSurface9_UnlockRect(stretchsurface);
2485                                         }
2486                                 }
2487                                 IDirect3DSurface9_Release(stretchsurface);
2488                         }
2489                         // code scraps
2490                         //IDirect3DSurface9 *syssurface = NULL;
2491                         //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2492                         //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2493                         //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2494                         //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2495                         //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2496                         //IDirect3DSurface9_UnlockRect(syssurface);
2497                         //IDirect3DSurface9_Release(syssurface);
2498                 }
2499 #endif
2500                 break;
2501         case RENDERPATH_D3D10:
2502                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2503                 break;
2504         case RENDERPATH_D3D11:
2505                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2506                 break;
2507         case RENDERPATH_SOFT:
2508                 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2509                 break;
2510         }
2511 }
2512
2513 // called at beginning of frame
2514 void R_Mesh_Start(void)
2515 {
2516         BACKENDACTIVECHECK
2517         R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
2518         R_Mesh_SetUseVBO();
2519         if (gl_printcheckerror.integer && !gl_paranoid.integer)
2520         {
2521                 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2522                 Cvar_SetValueQuick(&gl_paranoid, 1);
2523         }
2524 }
2525
2526 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2527 {
2528         int shaderobject;
2529         int shadercompiled;
2530         char compilelog[MAX_INPUTLINE];
2531         shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2532         if (!shaderobject)
2533                 return false;
2534         qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2535         qglCompileShader(shaderobject);CHECKGLERROR
2536         qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2537         qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2538         if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning") || developer_extra.integer))
2539         {
2540                 int i, j, pretextlines = 0;
2541                 for (i = 0;i < numstrings - 1;i++)
2542                         for (j = 0;strings[i][j];j++)
2543                                 if (strings[i][j] == '\n')
2544                                         pretextlines++;
2545                 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2546         }
2547         if (!shadercompiled)
2548         {
2549                 qglDeleteShader(shaderobject);CHECKGLERROR
2550                 return false;
2551         }
2552         qglAttachShader(programobject, shaderobject);CHECKGLERROR
2553         qglDeleteShader(shaderobject);CHECKGLERROR
2554         return true;
2555 }
2556
2557 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)
2558 {
2559         GLint programlinked;
2560         GLuint programobject = 0;
2561         char linklog[MAX_INPUTLINE];
2562         CHECKGLERROR
2563
2564         programobject = qglCreateProgram();CHECKGLERROR
2565         if (!programobject)
2566                 return 0;
2567
2568         qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2569         qglBindAttribLocation(programobject, GLSLATTRIB_COLOR    , "Attrib_Color"    );
2570         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2571         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2572         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2573         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2574         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2575         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2576         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2577         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2578 #ifndef USE_GLES2
2579         if(vid.support.gl20shaders130)
2580                 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2581 #endif
2582
2583         if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2584                 goto cleanup;
2585
2586 #ifdef GL_GEOMETRY_SHADER
2587         if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2588                 goto cleanup;
2589 #endif
2590
2591         if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2592                 goto cleanup;
2593
2594         qglLinkProgram(programobject);CHECKGLERROR
2595         qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2596         qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2597         if (linklog[0])
2598         {
2599                 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer)
2600                         Con_DPrintf("program link log:\n%s\n", linklog);
2601                 // software vertex shader is ok but software fragment shader is WAY
2602                 // too slow, fail program if so.
2603                 // NOTE: this string might be ATI specific, but that's ok because the
2604                 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2605                 // software fragment shader due to low instruction and dependent
2606                 // texture limits.
2607                 if (strstr(linklog, "fragment shader will run in software"))
2608                         programlinked = false;
2609         }
2610         if (!programlinked)
2611                 goto cleanup;
2612         return programobject;
2613 cleanup:
2614         qglDeleteProgram(programobject);CHECKGLERROR
2615         return 0;
2616 }
2617
2618 void GL_Backend_FreeProgram(unsigned int prog)
2619 {
2620         CHECKGLERROR
2621         qglDeleteProgram(prog);
2622         CHECKGLERROR
2623 }
2624
2625 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2626 {
2627         int i;
2628         if (offset)
2629         {
2630                 for (i = 0;i < count;i++)
2631                         *out++ = *in++ + offset;
2632         }
2633         else
2634                 memcpy(out, in, sizeof(*out) * count);
2635 }
2636
2637 // renders triangles using vertices from the active arrays
2638 int paranoidblah = 0;
2639 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)
2640 {
2641         unsigned int numelements = numtriangles * 3;
2642         int bufferobject3i;
2643         size_t bufferoffset3i;
2644         int bufferobject3s;
2645         size_t bufferoffset3s;
2646         if (numvertices < 3 || numtriangles < 1)
2647         {
2648                 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2649                         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);
2650                 return;
2651         }
2652         if (!gl_mesh_prefer_short_elements.integer)
2653         {
2654                 if (element3i)
2655                         element3s = NULL;
2656                 if (element3i_indexbuffer)
2657                         element3i_indexbuffer = NULL;
2658         }
2659         // adjust the pointers for firsttriangle
2660         if (element3i)
2661                 element3i += firsttriangle * 3;
2662         if (element3i_indexbuffer)
2663                 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2664         if (element3s)
2665                 element3s += firsttriangle * 3;
2666         if (element3s_indexbuffer)
2667                 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2668         switch(vid.renderpath)
2669         {
2670         case RENDERPATH_GL11:
2671         case RENDERPATH_GL13:
2672         case RENDERPATH_GL20:
2673         case RENDERPATH_GLES1:
2674         case RENDERPATH_GLES2:
2675                 // check if the user specified to ignore static index buffers
2676                 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2677                 {
2678                         element3i_indexbuffer = NULL;
2679                         element3s_indexbuffer = NULL;
2680                 }
2681                 break;
2682         case RENDERPATH_D3D9:
2683         case RENDERPATH_D3D10:
2684         case RENDERPATH_D3D11:
2685                 break;
2686         case RENDERPATH_SOFT:
2687                 break;
2688         }
2689         // upload a dynamic index buffer if needed
2690         if (element3s)
2691         {
2692                 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2693                 {
2694                         if (gl_state.draw_dynamicindexbuffer)
2695                                 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2696                         else
2697                                 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2698                         element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2699                         element3s_bufferoffset = 0;
2700                 }
2701         }
2702         else if (element3i)
2703         {
2704                 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2705                 {
2706                         if (gl_state.draw_dynamicindexbuffer)
2707                                 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2708                         else
2709                                 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2710                         element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2711                         element3i_bufferoffset = 0;
2712                 }
2713         }
2714         bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2715         bufferoffset3i = element3i_bufferoffset;
2716         bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2717         bufferoffset3s = element3s_bufferoffset;
2718         r_refdef.stats.draws++;
2719         r_refdef.stats.draws_vertices += numvertices;
2720         r_refdef.stats.draws_elements += numelements;
2721         if (gl_paranoid.integer)
2722         {
2723                 unsigned int i;
2724                 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2725 #if 0
2726                 unsigned int j, size;
2727                 const int *p;
2728                 // note: there's no validation done here on buffer objects because it
2729                 // is somewhat difficult to get at the data, and gl_paranoid can be
2730                 // used without buffer objects if the need arises
2731                 // (the data could be gotten using glMapBuffer but it would be very
2732                 //  slow due to uncachable video memory reads)
2733                 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2734                         Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2735                 CHECKGLERROR
2736                 if (gl_state.pointer_vertex_pointer)
2737                         for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2738                                 paranoidblah += *p;
2739                 if (gl_state.pointer_color_enabled)
2740                 {
2741                         if (!qglIsEnabled(GL_COLOR_ARRAY))
2742                                 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2743                         CHECKGLERROR
2744                         if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2745                                 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2746                                         paranoidblah += *p;
2747                 }
2748                 for (i = 0;i < vid.texarrayunits;i++)
2749                 {
2750                         if (gl_state.units[i].arrayenabled)
2751                         {
2752                                 GL_ClientActiveTexture(i);
2753                                 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2754                                         Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2755                                 CHECKGLERROR
2756                                 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2757                                         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++)
2758                                                 paranoidblah += *p;
2759                         }
2760                 }
2761 #endif
2762                 if (element3i)
2763                 {
2764                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2765                         {
2766                                 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2767                                 {
2768                                         Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2769                                         return;
2770                                 }
2771                         }
2772                 }
2773                 if (element3s)
2774                 {
2775                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2776                         {
2777                                 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2778                                 {
2779                                         Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2780                                         return;
2781                                 }
2782                         }
2783                 }
2784         }
2785         if (r_render.integer || r_refdef.draw2dstage)
2786         {
2787                 switch(vid.renderpath)
2788                 {
2789                 case RENDERPATH_GL11:
2790                 case RENDERPATH_GL13:
2791                 case RENDERPATH_GL20:
2792                         CHECKGLERROR
2793                         if (gl_mesh_testmanualfeeding.integer)
2794                         {
2795 #ifndef USE_GLES2
2796                                 unsigned int i, j, element;
2797                                 const GLfloat *p;
2798                                 qglBegin(GL_TRIANGLES);
2799                                 if(vid.renderpath == RENDERPATH_GL20)
2800                                 {
2801                                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2802                                         {
2803                                                 if (element3i)
2804                                                         element = element3i[i];
2805                                                 else if (element3s)
2806                                                         element = element3s[i];
2807                                                 else
2808                                                         element = firstvertex + i;
2809                                                 for (j = 0;j < vid.texarrayunits;j++)
2810                                                 {
2811                                                         if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2812                                                         {
2813                                                                 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2814                                                                 {
2815                                                                         p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2816                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2817                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2], p[3]);
2818                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2819                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2]);
2820                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2821                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1]);
2822                                                                         else
2823                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, p[0]);
2824                                                                 }
2825                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2826                                                                 {
2827                                                                         const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2828                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2829                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2], s[3]);
2830                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2831                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2]);
2832                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2833                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1]);
2834                                                                         else if (gl_state.units[j].pointer_texcoord_components == 1)
2835                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, s[0]);
2836                                                                 }
2837                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2838                                                                 {
2839                                                                         const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2840                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2841                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2], sb[3]);
2842                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2843                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2]);
2844                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2845                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1]);
2846                                                                         else if (gl_state.units[j].pointer_texcoord_components == 1)
2847                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0]);
2848                                                                 }
2849                                                         }
2850                                                 }
2851                                                 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2852                                                 {
2853                                                         if (gl_state.pointer_color_gltype == GL_FLOAT)
2854                                                         {
2855                                                                 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2856                                                                 qglVertexAttrib4f(GLSLATTRIB_COLOR, p[0], p[1], p[2], p[3]);
2857                                                         }
2858                                                         else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2859                                                         {
2860                                                                 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2861                                                                 qglVertexAttrib4Nub(GLSLATTRIB_COLOR, ub[0], ub[1], ub[2], ub[3]);
2862                                                         }
2863                                                 }
2864                                                 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2865                                                 {
2866                                                         p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2867                                                         if (gl_state.pointer_vertex_components == 4)
2868                                                                 qglVertexAttrib4f(GLSLATTRIB_POSITION, p[0], p[1], p[2], p[3]);
2869                                                         else if (gl_state.pointer_vertex_components == 3)
2870                                                                 qglVertexAttrib3f(GLSLATTRIB_POSITION, p[0], p[1], p[2]);
2871                                                         else
2872                                                                 qglVertexAttrib2f(GLSLATTRIB_POSITION, p[0], p[1]);
2873                                                 }
2874                                         }
2875                                 }
2876                                 else
2877                                 {
2878                                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2879                                         {
2880                                                 if (element3i)
2881                                                         element = element3i[i];
2882                                                 else if (element3s)
2883                                                         element = element3s[i];
2884                                                 else
2885                                                         element = firstvertex + i;
2886                                                 for (j = 0;j < vid.texarrayunits;j++)
2887                                                 {
2888                                                         if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2889                                                         {
2890                                                                 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2891                                                                 {
2892                                                                         p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2893                                                                         if (vid.texarrayunits > 1)
2894                                                                         {
2895                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2896                                                                                         qglMultiTexCoord4f(GL_TEXTURE0 + j, p[0], p[1], p[2], p[3]);
2897                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2898                                                                                         qglMultiTexCoord3f(GL_TEXTURE0 + j, p[0], p[1], p[2]);
2899                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2900                                                                                         qglMultiTexCoord2f(GL_TEXTURE0 + j, p[0], p[1]);
2901                                                                                 else
2902                                                                                         qglMultiTexCoord1f(GL_TEXTURE0 + j, p[0]);
2903                                                                         }
2904                                                                         else
2905                                                                         {
2906                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2907                                                                                         qglTexCoord4f(p[0], p[1], p[2], p[3]);
2908                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2909                                                                                         qglTexCoord3f(p[0], p[1], p[2]);
2910                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2911                                                                                         qglTexCoord2f(p[0], p[1]);
2912                                                                                 else
2913                                                                                         qglTexCoord1f(p[0]);
2914                                                                         }
2915                                                                 }
2916                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2917                                                                 {
2918                                                                         const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2919                                                                         if (vid.texarrayunits > 1)
2920                                                                         {
2921                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2922                                                                                         qglMultiTexCoord4f(GL_TEXTURE0 + j, s[0], s[1], s[2], s[3]);
2923                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2924                                                                                         qglMultiTexCoord3f(GL_TEXTURE0 + j, s[0], s[1], s[2]);
2925                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2926                                                                                         qglMultiTexCoord2f(GL_TEXTURE0 + j, s[0], s[1]);
2927                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
2928                                                                                         qglMultiTexCoord1f(GL_TEXTURE0 + j, s[0]);
2929                                                                         }
2930                                                                         else
2931                                                                         {
2932                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2933                                                                                         qglTexCoord4f(s[0], s[1], s[2], s[3]);
2934                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2935                                                                                         qglTexCoord3f(s[0], s[1], s[2]);
2936                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2937                                                                                         qglTexCoord2f(s[0], s[1]);
2938                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
2939                                                                                         qglTexCoord1f(s[0]);
2940                                                                         }
2941                                                                 }
2942                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2943                                                                 {
2944                                                                         const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2945                                                                         if (vid.texarrayunits > 1)
2946                                                                         {
2947                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2948                                                                                         qglMultiTexCoord4f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2], sb[3]);
2949                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2950                                                                                         qglMultiTexCoord3f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2]);
2951                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2952                                                                                         qglMultiTexCoord2f(GL_TEXTURE0 + j, sb[0], sb[1]);
2953                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
2954                                                                                         qglMultiTexCoord1f(GL_TEXTURE0 + j, sb[0]);
2955                                                                         }
2956                                                                         else
2957                                                                         {
2958                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2959                                                                                         qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2960                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2961                                                                                         qglTexCoord3f(sb[0], sb[1], sb[2]);
2962                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2963                                                                                         qglTexCoord2f(sb[0], sb[1]);
2964                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
2965                                                                                         qglTexCoord1f(sb[0]);
2966                                                                         }
2967                                                                 }
2968                                                         }
2969                                                 }
2970                                                 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2971                                                 {
2972                                                         if (gl_state.pointer_color_gltype == GL_FLOAT)
2973                                                         {
2974                                                                 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2975                                                                 qglColor4f(p[0], p[1], p[2], p[3]);
2976                                                         }
2977                                                         else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2978                                                         {
2979                                                                 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2980                                                                 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2981                                                         }
2982                                                 }
2983                                                 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2984                                                 {
2985                                                         p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2986                                                         if (gl_state.pointer_vertex_components == 4)
2987                                                                 qglVertex4f(p[0], p[1], p[2], p[3]);
2988                                                         else if (gl_state.pointer_vertex_components == 3)
2989                                                                 qglVertex3f(p[0], p[1], p[2]);
2990                                                         else
2991                                                                 qglVertex2f(p[0], p[1]);
2992                                                 }
2993                                         }
2994                                 }
2995                                 qglEnd();
2996                                 CHECKGLERROR
2997 #endif
2998                         }
2999                         else if (bufferobject3s)
3000                         {
3001                                 GL_BindEBO(bufferobject3s);
3002 #ifndef USE_GLES2
3003                                 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
3004                                 {
3005                                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
3006                                         CHECKGLERROR
3007                                 }
3008                                 else
3009 #endif
3010                                 {
3011                                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
3012                                         CHECKGLERROR
3013                                 }
3014                         }
3015                         else if (bufferobject3i)
3016                         {
3017                                 GL_BindEBO(bufferobject3i);
3018 #ifndef USE_GLES2
3019                                 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
3020                                 {
3021                                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
3022                                         CHECKGLERROR
3023                                 }
3024                                 else
3025 #endif
3026                                 {
3027                                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
3028                                         CHECKGLERROR
3029                                 }
3030                         }
3031                         else if (element3s)
3032                         {
3033                                 GL_BindEBO(0);
3034 #ifndef USE_GLES2
3035                                 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
3036                                 {
3037                                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
3038                                         CHECKGLERROR
3039                                 }
3040                                 else
3041 #endif
3042                                 {
3043                                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
3044                                         CHECKGLERROR
3045                                 }
3046                         }
3047                         else if (element3i)
3048                         {
3049                                 GL_BindEBO(0);
3050 #ifndef USE_GLES2
3051                                 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
3052                                 {
3053                                         qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
3054                                         CHECKGLERROR
3055                                 }
3056                                 else
3057 #endif
3058                                 {
3059                                         qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
3060                                         CHECKGLERROR
3061                                 }
3062                         }
3063                         else
3064                         {
3065                                 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
3066                                 CHECKGLERROR
3067                         }
3068                         break;
3069                 case RENDERPATH_D3D9:
3070 #ifdef SUPPORTD3D
3071                         if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
3072                         {
3073                                 if (element3s_indexbuffer)
3074                                 {
3075                                         IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
3076                                         IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
3077                                 }
3078                                 else if (element3i_indexbuffer)
3079                                 {
3080                                         IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
3081                                         IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
3082                                 }
3083                                 else
3084                                         IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
3085                         }
3086                         else
3087                         {
3088                                 if (element3s)
3089                                         IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
3090                                 else if (element3i)
3091                                         IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
3092                                 else
3093                                         IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
3094                         }
3095 #endif
3096                         break;
3097                 case RENDERPATH_D3D10:
3098                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3099                         break;
3100                 case RENDERPATH_D3D11:
3101                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3102                         break;
3103                 case RENDERPATH_SOFT:
3104                         DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
3105                         break;
3106                 case RENDERPATH_GLES1:
3107                 case RENDERPATH_GLES2:
3108                         // GLES does not have glDrawRangeElements, and generally
3109                         // underperforms with index buffers, so this code path is
3110                         // relatively straightforward...
3111 #if 0
3112                         if (gl_paranoid.integer)
3113                         {
3114                                 int r, prog, enabled, i;
3115                                 GLsizei         attriblength;
3116                                 GLint           attribsize;
3117                                 GLenum          attribtype;
3118                                 GLchar          attribname[1024];
3119                                 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
3120                                 if (r != GL_FRAMEBUFFER_COMPLETE)
3121                                         Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
3122 #ifndef GL_CURRENT_PROGRAM
3123 #define GL_CURRENT_PROGRAM 0x8B8D
3124 #endif
3125                                 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
3126                                 if (r < 0 || r > 10000)
3127                                         Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
3128                                 prog = r;
3129                                 for (i = 0;i < 8;i++)
3130                                 {
3131                                         qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
3132                                         if (!r)
3133                                                 continue;
3134                                         qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
3135                                         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);
3136                                 }
3137                         }
3138 #endif
3139                         if (element3s)
3140                         {
3141                                 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
3142                                 CHECKGLERROR
3143                         }
3144                         else if (element3i)
3145                         {
3146                                 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
3147                                 CHECKGLERROR
3148                         }
3149                         else
3150                         {
3151                                 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
3152                                 CHECKGLERROR
3153                         }
3154                         break;
3155                 }
3156         }
3157 }
3158
3159 // restores backend state, used when done with 3D rendering
3160 void R_Mesh_Finish(void)
3161 {
3162         R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
3163 }
3164
3165 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
3166 {
3167         r_meshbuffer_t *buffer;
3168         if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
3169                 return NULL;
3170         buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
3171         memset(buffer, 0, sizeof(*buffer));
3172         buffer->bufferobject = 0;
3173         buffer->devicebuffer = NULL;
3174         buffer->size = 0;
3175         buffer->isindexbuffer = isindexbuffer;
3176         buffer->isdynamic = isdynamic;
3177         buffer->isindex16 = isindex16;
3178         strlcpy(buffer->name, name, sizeof(buffer->name));
3179         R_Mesh_UpdateMeshBuffer(buffer, data, size);
3180         return buffer;
3181 }
3182
3183 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
3184 {
3185         if (!buffer)
3186                 return;
3187         if (buffer->isindexbuffer)
3188         {
3189                 r_refdef.stats.indexbufferuploadcount++;
3190                 r_refdef.stats.indexbufferuploadsize += size;
3191         }
3192         else
3193         {
3194                 r_refdef.stats.vertexbufferuploadcount++;
3195                 r_refdef.stats.vertexbufferuploadsize += size;
3196         }
3197         switch(vid.renderpath)
3198         {
3199         case RENDERPATH_GL11:
3200         case RENDERPATH_GL13:
3201         case RENDERPATH_GL20:
3202         case RENDERPATH_GLES1:
3203         case RENDERPATH_GLES2:
3204                 if (!buffer->bufferobject)
3205                         qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3206                 if (buffer->isindexbuffer)
3207                         GL_BindEBO(buffer->bufferobject);
3208                 else
3209                         GL_BindVBO(buffer->bufferobject);
3210                 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW);
3211                 break;
3212         case RENDERPATH_D3D9:
3213 #ifdef SUPPORTD3D
3214                 {
3215                         int result;
3216                         void *datapointer = NULL;
3217                         if (buffer->isindexbuffer)
3218                         {
3219                                 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3220                                 if (size > buffer->size || !buffer->devicebuffer)
3221                                 {
3222                                         if (buffer->devicebuffer)
3223                                                 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3224                                         buffer->devicebuffer = NULL;
3225                                         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)))
3226                                                 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);
3227                                         buffer->devicebuffer = (void *)d3d9indexbuffer;
3228                                         buffer->size = size;
3229                                 }
3230                                 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3231                                 {
3232                                         if (data)
3233                                                 memcpy(datapointer, data, size);
3234                                         else
3235                                                 memset(datapointer, 0, size);
3236                                         IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3237                                 }
3238                         }
3239                         else
3240                         {
3241                                 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3242                                 if (size > buffer->size || !buffer->devicebuffer)
3243                                 {
3244                                         if (buffer->devicebuffer)
3245                                                 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3246                                         buffer->devicebuffer = NULL;
3247                                         if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3248                                                 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);
3249                                         buffer->devicebuffer = (void *)d3d9vertexbuffer;
3250                                         buffer->size = size;
3251                                 }
3252                                 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3253                                 {
3254                                         if (data)
3255                                                 memcpy(datapointer, data, size);
3256                                         else
3257                                                 memset(datapointer, 0, size);
3258                                         IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3259                                 }
3260                         }
3261                 }
3262 #endif
3263                 break;
3264         case RENDERPATH_D3D10:
3265                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3266                 break;
3267         case RENDERPATH_D3D11:
3268                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3269                 break;
3270         case RENDERPATH_SOFT:
3271                 break;
3272         }
3273 }
3274
3275 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3276 {
3277         if (!buffer)
3278                 return;
3279         switch(vid.renderpath)
3280         {
3281         case RENDERPATH_GL11:
3282         case RENDERPATH_GL13:
3283         case RENDERPATH_GL20:
3284         case RENDERPATH_GLES1:
3285         case RENDERPATH_GLES2:
3286                 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3287                 break;
3288         case RENDERPATH_D3D9:
3289 #ifdef SUPPORTD3D
3290                 if (gl_state.d3dvertexbuffer == (void *)buffer)
3291                         gl_state.d3dvertexbuffer = NULL;
3292                 if (buffer->devicebuffer)
3293                 {
3294                         if (buffer->isindexbuffer)
3295                                 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3296                         else
3297                                 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3298                         buffer->devicebuffer = NULL;
3299                 }
3300 #endif
3301                 break;
3302         case RENDERPATH_D3D10:
3303                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3304                 break;
3305         case RENDERPATH_D3D11:
3306                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3307                 break;
3308         case RENDERPATH_SOFT:
3309                 break;
3310         }
3311         Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3312 }
3313
3314 void GL_Mesh_ListVBOs(qboolean printeach)
3315 {
3316         int i, endindex;
3317         size_t ebocount = 0, ebomemory = 0;
3318         size_t vbocount = 0, vbomemory = 0;
3319         r_meshbuffer_t *buffer;
3320         endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3321         for (i = 0;i < endindex;i++)
3322         {
3323                 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3324                 if (!buffer)
3325                         continue;
3326                 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)");}
3327                 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)");}
3328         }
3329         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);
3330 }
3331
3332
3333
3334 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3335 {
3336         switch(vid.renderpath)
3337         {
3338         case RENDERPATH_GL11:
3339         case RENDERPATH_GL13:
3340         case RENDERPATH_GLES1:
3341                 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)
3342                 {
3343                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3344                         gl_state.pointer_vertex_components = components;
3345                         gl_state.pointer_vertex_gltype = gltype;
3346                         gl_state.pointer_vertex_stride = stride;
3347                         gl_state.pointer_vertex_pointer = pointer;
3348                         gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3349                         gl_state.pointer_vertex_offset = bufferoffset;
3350                         CHECKGLERROR
3351                         GL_BindVBO(bufferobject);
3352                         qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3353                 }
3354                 break;
3355         case RENDERPATH_GL20:
3356         case RENDERPATH_GLES2:
3357                 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)
3358                 {
3359                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3360                         gl_state.pointer_vertex_components = components;
3361                         gl_state.pointer_vertex_gltype = gltype;
3362                         gl_state.pointer_vertex_stride = stride;
3363                         gl_state.pointer_vertex_pointer = pointer;
3364                         gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3365                         gl_state.pointer_vertex_offset = bufferoffset;
3366                         CHECKGLERROR
3367                         GL_BindVBO(bufferobject);
3368                         qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3369                 }
3370                 break;
3371         case RENDERPATH_D3D9:
3372         case RENDERPATH_D3D10:
3373         case RENDERPATH_D3D11:
3374         case RENDERPATH_SOFT:
3375                 break;
3376         }
3377 }
3378
3379 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3380 {
3381         // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3382         // the pointer only.
3383         switch(vid.renderpath)
3384         {
3385         case RENDERPATH_GL11:
3386         case RENDERPATH_GL13:
3387         case RENDERPATH_GLES1:
3388 #ifdef GL_MODELVIEW
3389                 CHECKGLERROR
3390                 if (pointer)
3391                 {
3392                         // caller wants color array enabled
3393                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3394                         if (!gl_state.pointer_color_enabled)
3395                         {
3396                                 gl_state.pointer_color_enabled = true;
3397                                 CHECKGLERROR
3398                                 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3399                         }
3400                         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)
3401                         {
3402                                 gl_state.pointer_color_components = components;
3403                                 gl_state.pointer_color_gltype = gltype;
3404                                 gl_state.pointer_color_stride = stride;
3405                                 gl_state.pointer_color_pointer = pointer;
3406                                 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3407                                 gl_state.pointer_color_offset = bufferoffset;
3408                                 CHECKGLERROR
3409                                 GL_BindVBO(bufferobject);
3410                                 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3411                         }
3412                 }
3413                 else
3414                 {
3415                         // caller wants color array disabled
3416                         if (gl_state.pointer_color_enabled)
3417                         {
3418                                 gl_state.pointer_color_enabled = false;
3419                                 CHECKGLERROR
3420                                 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3421                                 // when color array is on the glColor gets trashed, set it again
3422                                 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3423                         }
3424                 }
3425 #endif
3426                 break;
3427         case RENDERPATH_GL20:
3428         case RENDERPATH_GLES2:
3429                 CHECKGLERROR
3430                 if (pointer)
3431                 {
3432                         // caller wants color array enabled
3433                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3434                         if (!gl_state.pointer_color_enabled)
3435                         {
3436                                 gl_state.pointer_color_enabled = true;
3437                                 CHECKGLERROR
3438                                 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3439                         }
3440                         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)
3441                         {
3442                                 gl_state.pointer_color_components = components;
3443                                 gl_state.pointer_color_gltype = gltype;
3444                                 gl_state.pointer_color_stride = stride;
3445                                 gl_state.pointer_color_pointer = pointer;
3446                                 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3447                                 gl_state.pointer_color_offset = bufferoffset;
3448                                 CHECKGLERROR
3449                                 GL_BindVBO(bufferobject);
3450                                 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3451                         }
3452                 }
3453                 else
3454                 {
3455                         // caller wants color array disabled
3456                         if (gl_state.pointer_color_enabled)
3457                         {
3458                                 gl_state.pointer_color_enabled = false;
3459                                 CHECKGLERROR
3460                                 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3461                                 // when color array is on the glColor gets trashed, set it again
3462                                 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3463                         }
3464                 }
3465                 break;
3466         case RENDERPATH_D3D9:
3467         case RENDERPATH_D3D10:
3468         case RENDERPATH_D3D11:
3469         case RENDERPATH_SOFT:
3470                 break;
3471         }
3472 }
3473
3474 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)
3475 {
3476         gltextureunit_t *unit = gl_state.units + unitnum;
3477         // update array settings
3478         // note: there is no need to check bufferobject here because all cases
3479         // that involve a valid bufferobject also supply a texcoord array
3480         switch(vid.renderpath)
3481         {
3482         case RENDERPATH_GL11:
3483         case RENDERPATH_GL13:
3484         case RENDERPATH_GLES1:
3485 #ifdef GL_MODELVIEW
3486                 CHECKGLERROR
3487                 if (pointer)
3488                 {
3489                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3490                         // texture array unit is enabled, enable the array
3491                         if (!unit->arrayenabled)
3492                         {
3493                                 unit->arrayenabled = true;
3494                                 GL_ClientActiveTexture(unitnum);
3495                                 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3496                         }
3497                         // texcoord array
3498                         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)
3499                         {
3500                                 unit->pointer_texcoord_components = components;
3501                                 unit->pointer_texcoord_gltype = gltype;
3502                                 unit->pointer_texcoord_stride = stride;
3503                                 unit->pointer_texcoord_pointer = pointer;
3504                                 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3505                                 unit->pointer_texcoord_offset = bufferoffset;
3506                                 GL_ClientActiveTexture(unitnum);
3507                                 GL_BindVBO(bufferobject);
3508                                 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3509                         }
3510                 }
3511                 else
3512                 {
3513                         // texture array unit is disabled, disable the array
3514                         if (unit->arrayenabled)
3515                         {
3516                                 unit->arrayenabled = false;
3517                                 GL_ClientActiveTexture(unitnum);
3518                                 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3519                         }
3520                 }
3521 #endif
3522                 break;
3523         case RENDERPATH_GL20:
3524         case RENDERPATH_GLES2:
3525                 CHECKGLERROR
3526                 if (pointer)
3527                 {
3528                         int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3529                         // texture array unit is enabled, enable the array
3530                         if (!unit->arrayenabled)
3531                         {
3532                                 unit->arrayenabled = true;
3533                                 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3534                         }
3535                         // texcoord array
3536                         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)
3537                         {
3538                                 unit->pointer_texcoord_components = components;
3539                                 unit->pointer_texcoord_gltype = gltype;
3540                                 unit->pointer_texcoord_stride = stride;
3541                                 unit->pointer_texcoord_pointer = pointer;
3542                                 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3543                                 unit->pointer_texcoord_offset = bufferoffset;
3544                                 GL_BindVBO(bufferobject);
3545                                 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3546                         }
3547                 }
3548                 else
3549                 {
3550                         // texture array unit is disabled, disable the array
3551                         if (unit->arrayenabled)
3552                         {
3553                                 unit->arrayenabled = false;
3554                                 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3555                         }
3556                 }
3557                 break;
3558         case RENDERPATH_D3D9:
3559         case RENDERPATH_D3D10:
3560         case RENDERPATH_D3D11:
3561         case RENDERPATH_SOFT:
3562                 break;
3563         }
3564 }
3565
3566 int R_Mesh_TexBound(unsigned int unitnum, int id)
3567 {
3568         gltextureunit_t *unit = gl_state.units + unitnum;
3569         if (unitnum >= vid.teximageunits)
3570                 return 0;
3571         if (id == GL_TEXTURE_2D)
3572                 return unit->t2d;
3573         if (id == GL_TEXTURE_3D)
3574                 return unit->t3d;
3575         if (id == GL_TEXTURE_CUBE_MAP)
3576                 return unit->tcubemap;
3577         return 0;
3578 }
3579
3580 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3581 {
3582         switch(vid.renderpath)
3583         {
3584         case RENDERPATH_GL11:
3585         case RENDERPATH_GL13:
3586         case RENDERPATH_GL20:
3587         case RENDERPATH_GLES1:
3588         case RENDERPATH_GLES2:
3589                 R_Mesh_TexBind(0, tex);
3590                 GL_ActiveTexture(0);CHECKGLERROR
3591                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3592                 break;
3593         case RENDERPATH_D3D9:
3594 #ifdef SUPPORTD3D
3595                 {
3596                         IDirect3DSurface9 *currentsurface = NULL;
3597                         IDirect3DSurface9 *texturesurface = NULL;
3598                         RECT sourcerect;
3599                         RECT destrect;
3600                         sourcerect.left = sx;
3601                         sourcerect.top = sy;
3602                         sourcerect.right = sx + width;
3603                         sourcerect.bottom = sy + height;
3604                         destrect.left = tx;
3605                         destrect.top = ty;
3606                         destrect.right = tx + width;
3607                         destrect.bottom = ty + height;
3608                         if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3609                         {
3610                                 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &currentsurface)))
3611                                 {
3612                                         IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3613                                         IDirect3DSurface9_Release(currentsurface);
3614                                 }
3615                                 IDirect3DSurface9_Release(texturesurface);
3616                         }
3617                 }
3618 #endif
3619                 break;
3620         case RENDERPATH_D3D10:
3621                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3622                 break;
3623         case RENDERPATH_D3D11:
3624                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3625                 break;
3626         case RENDERPATH_SOFT:
3627                 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3628                 break;
3629         }
3630 }
3631
3632 #ifdef SUPPORTD3D
3633 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};
3634 #endif
3635
3636 void R_Mesh_ClearBindingsForTexture(int texnum)
3637 {
3638         gltextureunit_t *unit;
3639         unsigned int unitnum;
3640         // 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)
3641         for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3642         {
3643                 unit = gl_state.units + unitnum;
3644                 if (unit->t2d == texnum)
3645                         unit->t2d = -1;
3646                 if (unit->t3d == texnum)
3647                         unit->t3d = -1;
3648                 if (unit->tcubemap == texnum)
3649                         unit->tcubemap = -1;
3650         }
3651 }
3652
3653 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3654 {
3655         gltextureunit_t *unit = gl_state.units + unitnum;
3656         int tex2d, tex3d, texcubemap, texnum;
3657         if (unitnum >= vid.teximageunits)
3658                 return;
3659 //      if (unit->texture == tex)
3660 //              return;
3661         switch(vid.renderpath)
3662         {
3663         case RENDERPATH_GL20:
3664         case RENDERPATH_GLES2:
3665                 if (!tex)
3666                 {
3667                         tex = r_texture_white;
3668                         // not initialized enough yet...
3669                         if (!tex)
3670                                 return;
3671                 }
3672                 unit->texture = tex;
3673                 texnum = R_GetTexture(tex);
3674                 switch(tex->gltexturetypeenum)
3675                 {
3676                 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3677                 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3678                 case GL_TEXTURE_CUBE_MAP: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR}break;
3679                 }
3680                 break;
3681         case RENDERPATH_GL11:
3682         case RENDERPATH_GL13:
3683         case RENDERPATH_GLES1:
3684                 unit->texture = tex;
3685                 tex2d = 0;
3686                 tex3d = 0;
3687                 texcubemap = 0;
3688                 if (tex)
3689                 {
3690                         texnum = R_GetTexture(tex);
3691                         switch(tex->gltexturetypeenum)
3692                         {
3693                         case GL_TEXTURE_2D:
3694                                 tex2d = texnum;
3695                                 break;
3696                         case GL_TEXTURE_3D:
3697                                 tex3d = texnum;
3698                                 break;
3699                         case GL_TEXTURE_CUBE_MAP:
3700                                 texcubemap = texnum;
3701                                 break;
3702                         }
3703                 }
3704                 // update 2d texture binding
3705                 if (unit->t2d != tex2d)
3706                 {
3707                         GL_ActiveTexture(unitnum);
3708                         if (tex2d)
3709                         {
3710                                 if (unit->t2d == 0)
3711                                 {
3712                                         qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3713                                 }
3714                         }
3715                         else
3716                         {
3717                                 if (unit->t2d)
3718                                 {
3719                                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3720                                 }
3721                         }
3722                         unit->t2d = tex2d;
3723                         qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3724                 }
3725                 // update 3d texture binding
3726                 if (unit->t3d != tex3d)
3727                 {
3728                         GL_ActiveTexture(unitnum);
3729                         if (tex3d)
3730                         {
3731                                 if (unit->t3d == 0)
3732                                 {
3733                                         qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3734                                 }
3735                         }
3736                         else
3737                         {
3738                                 if (unit->t3d)
3739                                 {
3740                                         qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3741                                 }
3742                         }
3743                         unit->t3d = tex3d;
3744                         qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3745                 }
3746                 // update cubemap texture binding
3747                 if (unit->tcubemap != texcubemap)
3748                 {
3749                         GL_ActiveTexture(unitnum);
3750                         if (texcubemap)
3751                         {
3752                                 if (unit->tcubemap == 0)
3753                                 {
3754                                         qglEnable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
3755                                 }
3756                         }
3757                         else
3758                         {
3759                                 if (unit->tcubemap)
3760                                 {
3761                                         qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
3762                                 }
3763                         }
3764                         unit->tcubemap = texcubemap;
3765                         qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR
3766                 }
3767                 break;
3768         case RENDERPATH_D3D9:
3769 #ifdef SUPPORTD3D
3770                 {
3771                         extern cvar_t gl_texture_anisotropy;
3772                         if (!tex)
3773                         {
3774                                 tex = r_texture_white;
3775                                 // not initialized enough yet...
3776                                 if (!tex)
3777                                         return;
3778                         }
3779                         // upload texture if needed
3780                         R_GetTexture(tex);
3781                         if (unit->texture == tex)
3782                                 return;
3783                         unit->texture = tex;
3784                         IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3785                         //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3786                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3787                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3788                         if (tex->d3daddressw)
3789                                 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW,  tex->d3daddressw);
3790                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3791                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3792                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3793                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3794                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3795                         IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3796                 }
3797 #endif
3798                 break;
3799         case RENDERPATH_D3D10:
3800                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3801                 break;
3802         case RENDERPATH_D3D11:
3803                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3804                 break;
3805         case RENDERPATH_SOFT:
3806                 if (!tex)
3807                 {
3808                         tex = r_texture_white;
3809                         // not initialized enough yet...
3810                         if (!tex)
3811                                 return;
3812                 }
3813                 texnum = R_GetTexture(tex);
3814                 if (unit->texture == tex)
3815                         return;
3816                 unit->texture = tex;
3817                 DPSOFTRAST_SetTexture(unitnum, texnum);
3818                 break;
3819         }
3820 }
3821
3822 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3823 {
3824         gltextureunit_t *unit = gl_state.units + unitnum;
3825         switch(vid.renderpath)
3826         {
3827         case RENDERPATH_GL11:
3828         case RENDERPATH_GL13:
3829         case RENDERPATH_GL20:
3830         case RENDERPATH_GLES1:
3831         case RENDERPATH_GLES2:
3832 #ifdef GL_MODELVIEW
3833                 if (matrix && matrix->m[3][3])
3834                 {
3835                         // texmatrix specified, check if it is different
3836                         if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3837                         {
3838                                 float glmatrix[16];
3839                                 unit->texmatrixenabled = true;
3840                                 unit->matrix = *matrix;
3841                                 CHECKGLERROR
3842                                 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3843                                 GL_ActiveTexture(unitnum);
3844                                 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3845                                 qglLoadMatrixf(glmatrix);CHECKGLERROR
3846                                 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3847                         }
3848                 }
3849                 else
3850                 {
3851                         // no texmatrix specified, revert to identity
3852                         if (unit->texmatrixenabled)
3853                         {
3854                                 unit->texmatrixenabled = false;
3855                                 unit->matrix = identitymatrix;
3856                                 CHECKGLERROR
3857                                 GL_ActiveTexture(unitnum);
3858                                 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3859                                 qglLoadIdentity();CHECKGLERROR
3860                                 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3861                         }
3862                 }
3863 #endif
3864                 break;
3865         case RENDERPATH_D3D9:
3866         case RENDERPATH_D3D10:
3867         case RENDERPATH_D3D11:
3868                 break;
3869         case RENDERPATH_SOFT:
3870                 break;
3871         }
3872 }
3873
3874 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3875 {
3876         gltextureunit_t *unit = gl_state.units + unitnum;
3877         CHECKGLERROR
3878         switch(vid.renderpath)
3879         {
3880         case RENDERPATH_GL20:
3881         case RENDERPATH_GLES2:
3882                 // do nothing
3883                 break;
3884         case RENDERPATH_GL13:
3885         case RENDERPATH_GLES1:
3886 #ifdef GL_TEXTURE_ENV
3887                 // GL_ARB_texture_env_combine
3888                 if (!combinergb)
3889                         combinergb = GL_MODULATE;
3890                 if (!combinealpha)
3891                         combinealpha = GL_MODULATE;
3892                 if (!rgbscale)
3893                         rgbscale = 1;
3894                 if (!alphascale)
3895                         alphascale = 1;
3896                 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3897                 {
3898                         if (combinergb == GL_DECAL)
3899                                 combinergb = GL_INTERPOLATE;
3900                         if (unit->combine != GL_COMBINE)
3901                         {
3902                                 unit->combine = GL_COMBINE;
3903                                 GL_ActiveTexture(unitnum);
3904                                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);CHECKGLERROR
3905                                 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE mode
3906                         }
3907                         if (unit->combinergb != combinergb)
3908                         {
3909                                 unit->combinergb = combinergb;
3910                                 GL_ActiveTexture(unitnum);
3911                                 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, unit->combinergb);CHECKGLERROR
3912                         }
3913                         if (unit->combinealpha != combinealpha)
3914                         {
3915                                 unit->combinealpha = combinealpha;
3916                                 GL_ActiveTexture(unitnum);
3917                                 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, unit->combinealpha);CHECKGLERROR
3918                         }
3919                         if (unit->rgbscale != rgbscale)
3920                         {
3921                                 unit->rgbscale = rgbscale;
3922                                 GL_ActiveTexture(unitnum);
3923                                 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, unit->rgbscale);CHECKGLERROR
3924                         }
3925                         if (unit->alphascale != alphascale)
3926                         {
3927                                 unit->alphascale = alphascale;
3928                                 GL_ActiveTexture(unitnum);
3929                                 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3930                         }
3931                 }
3932                 else
3933                 {
3934                         if (unit->combine != combinergb)
3935                         {
3936                                 unit->combine = combinergb;
3937                                 GL_ActiveTexture(unitnum);
3938                                 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3939                         }
3940                 }
3941 #endif
3942                 break;
3943         case RENDERPATH_GL11:
3944                 // normal GL texenv
3945 #ifdef GL_TEXTURE_ENV
3946                 if (!combinergb)
3947                         combinergb = GL_MODULATE;
3948                 if (unit->combine != combinergb)
3949                 {
3950                         unit->combine = combinergb;
3951                         GL_ActiveTexture(unitnum);
3952                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3953                 }
3954 #endif
3955                 break;
3956         case RENDERPATH_D3D9:
3957         case RENDERPATH_D3D10:
3958         case RENDERPATH_D3D11:
3959                 break;
3960         case RENDERPATH_SOFT:
3961                 break;
3962         }
3963 }
3964
3965 void R_Mesh_ResetTextureState(void)
3966 {
3967         unsigned int unitnum;
3968
3969         BACKENDACTIVECHECK
3970
3971         for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3972                 R_Mesh_TexBind(unitnum, NULL);
3973         for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3974                 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3975         switch(vid.renderpath)
3976         {
3977         case RENDERPATH_GL20:
3978         case RENDERPATH_GLES2:
3979         case RENDERPATH_D3D9:
3980         case RENDERPATH_D3D10:
3981         case RENDERPATH_D3D11:
3982         case RENDERPATH_SOFT:
3983                 break;
3984         case RENDERPATH_GL11:
3985         case RENDERPATH_GL13:
3986         case RENDERPATH_GLES1:
3987                 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3988                 {
3989                         R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3990                         R_Mesh_TexMatrix(unitnum, NULL);
3991                 }
3992                 break;
3993         }
3994 }
3995
3996
3997
3998 #ifdef SUPPORTD3D
3999 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
4000 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
4001 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
4002
4003 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
4004 {
4005         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4006         D3DDECL_END()
4007 };
4008
4009 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
4010 {
4011         {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f  ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4012         {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f   ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4013         {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
4014         D3DDECL_END()
4015 };
4016
4017 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
4018 {
4019         {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f          ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4020         {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f           ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
4021         {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
4022         {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f         ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
4023         {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f         ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
4024         {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f          ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
4025         {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
4026         D3DDECL_END()
4027 };
4028
4029 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
4030 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
4031 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
4032 #endif
4033
4034 static void R_Mesh_InitVertexDeclarations(void)
4035 {
4036 #ifdef SUPPORTD3D
4037         r_vertex3f_d3d9decl = NULL;
4038         r_vertexgeneric_d3d9decl = NULL;
4039         r_vertexmesh_d3d9decl = NULL;
4040         switch(vid.renderpath)
4041         {
4042         case RENDERPATH_GL20:
4043         case RENDERPATH_GL13:
4044         case RENDERPATH_GL11:
4045         case RENDERPATH_GLES1:
4046         case RENDERPATH_GLES2:
4047                 break;
4048         case RENDERPATH_D3D9:
4049                 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
4050                 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
4051                 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
4052                 break;
4053         case RENDERPATH_D3D10:
4054                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4055                 break;
4056         case RENDERPATH_D3D11:
4057                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4058                 break;
4059         case RENDERPATH_SOFT:
4060                 break;
4061         }
4062 #endif
4063 }
4064
4065 static void R_Mesh_DestroyVertexDeclarations(void)
4066 {
4067 #ifdef SUPPORTD3D
4068         if (r_vertex3f_d3d9decl)
4069                 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
4070         r_vertex3f_d3d9decl = NULL;
4071         if (r_vertexgeneric_d3d9decl)
4072                 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
4073         r_vertexgeneric_d3d9decl = NULL;
4074         if (r_vertexmesh_d3d9decl)
4075                 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
4076         r_vertexmesh_d3d9decl = NULL;
4077 #endif
4078 }
4079
4080 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
4081 {
4082         // upload temporary vertexbuffer for this rendering
4083         if (!gl_state.usevbo_staticvertex)
4084                 vertexbuffer = NULL;
4085         if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4086         {
4087                 if (gl_state.preparevertices_dynamicvertexbuffer)
4088                         R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
4089                 else
4090                         gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
4091                 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4092         }
4093         switch(vid.renderpath)
4094         {
4095         case RENDERPATH_GL20:
4096         case RENDERPATH_GLES2:
4097                 if (vertexbuffer)
4098                 {
4099                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4100                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4101                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4102                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4103                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4104                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4105                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4106                 }
4107                 else
4108                 {
4109                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4110                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4111                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4112                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4113                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4114                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4115                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4116                 }
4117                 break;
4118         case RENDERPATH_GL13:
4119         case RENDERPATH_GLES1:
4120                 if (vertexbuffer)
4121                 {
4122                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4123                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4124                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4125                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4126                 }
4127                 else
4128                 {
4129                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4130                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4131                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4132                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4133                 }
4134                 break;
4135         case RENDERPATH_GL11:
4136                 if (vertexbuffer)
4137                 {
4138                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4139                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4140                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4141                 }
4142                 else
4143                 {
4144                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
4145                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4146                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4147                 }
4148                 break;
4149         case RENDERPATH_D3D9:
4150 #ifdef SUPPORTD3D
4151                 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
4152                 if (vertexbuffer)
4153                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
4154                 else
4155                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4156                 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4157                 gl_state.d3dvertexdata = (void *)vertex3f;
4158                 gl_state.d3dvertexsize = sizeof(float[3]);
4159 #endif
4160                 break;
4161         case RENDERPATH_D3D10:
4162                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4163                 break;
4164         case RENDERPATH_D3D11:
4165                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4166                 break;
4167         case RENDERPATH_SOFT:
4168                 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4169                 DPSOFTRAST_SetColorPointer(NULL, 0);
4170                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
4171                 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4172                 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4173                 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4174                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4175                 break;
4176         }
4177 }
4178
4179
4180
4181 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
4182 {
4183         size_t size;
4184         size = sizeof(r_vertexgeneric_t) * numvertices;
4185         if (gl_state.preparevertices_tempdatamaxsize < size)
4186         {
4187                 gl_state.preparevertices_tempdatamaxsize = size;
4188                 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4189         }
4190         gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
4191         gl_state.preparevertices_numvertices = numvertices;
4192         return gl_state.preparevertices_vertexgeneric;
4193 }
4194
4195 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
4196 {
4197         R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4198         gl_state.preparevertices_vertexgeneric = NULL;
4199         gl_state.preparevertices_numvertices = 0;
4200         return true;
4201 }
4202
4203 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4204 {
4205         int i;
4206         r_vertexgeneric_t *vertex;
4207         switch(vid.renderpath)
4208         {
4209         case RENDERPATH_GL20:
4210         case RENDERPATH_GLES2:
4211                 if (!vid.useinterleavedarrays)
4212                 {
4213                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4214                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4215                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4216                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4217                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4218                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4219                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4220                         return;
4221                 }
4222                 break;
4223         case RENDERPATH_GL11:
4224         case RENDERPATH_GL13:
4225         case RENDERPATH_GLES1:
4226                 if (!vid.useinterleavedarrays)
4227                 {
4228                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4229                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4230                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4231                         if (vid.texunits >= 2)
4232                                 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4233                         if (vid.texunits >= 3)
4234                                 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4235                         return;
4236                 }
4237                 break;
4238         case RENDERPATH_D3D9:
4239         case RENDERPATH_D3D10:
4240         case RENDERPATH_D3D11:
4241                 break;
4242         case RENDERPATH_SOFT:
4243                 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4244                 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4245                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4246                 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4247                 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4248                 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4249                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4250                 return;
4251         }
4252
4253         // no quick path for this case, convert to vertex structs
4254         vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4255         for (i = 0;i < numvertices;i++)
4256                 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4257         if (color4f)
4258         {
4259                 for (i = 0;i < numvertices;i++)
4260                         Vector4Copy(color4f + 4*i, vertex[i].color4f);
4261         }
4262         else
4263         {
4264                 for (i = 0;i < numvertices;i++)
4265                         Vector4Copy(gl_state.color4f, vertex[i].color4f);
4266         }
4267         if (texcoord2f)
4268                 for (i = 0;i < numvertices;i++)
4269                         Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4270         R_Mesh_PrepareVertices_Generic_Unlock();
4271         R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4272 }
4273
4274 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4275 {
4276         // upload temporary vertexbuffer for this rendering
4277         if (!gl_state.usevbo_staticvertex)
4278                 vertexbuffer = NULL;
4279         if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4280         {
4281                 if (gl_state.preparevertices_dynamicvertexbuffer)
4282                         R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4283                 else
4284                         gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4285                 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4286         }
4287         switch(vid.renderpath)
4288         {
4289         case RENDERPATH_GL20:
4290         case RENDERPATH_GLES2:
4291                 if (vertexbuffer)
4292                 {
4293                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4294                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4295                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
4296                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4297                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4298                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4299                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4300                 }
4301                 else
4302                 {
4303                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4304                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4305                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , NULL, 0);
4306                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4307                         R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4308                         R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4309                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4310                 }
4311                 break;
4312         case RENDERPATH_GL13:
4313         case RENDERPATH_GLES1:
4314                 if (vertexbuffer)
4315                 {
4316                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4317                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4318                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
4319                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4320                 }
4321                 else
4322                 {
4323                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4324                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4325                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , NULL, 0);
4326                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4327                 }
4328                 break;
4329         case RENDERPATH_GL11:
4330                 if (vertexbuffer)
4331                 {
4332                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4333                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4334                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f         - (unsigned char *)vertex));
4335                 }
4336                 else
4337                 {
4338                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4339                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4340                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoord2f        , NULL, 0);
4341                 }
4342                 break;
4343         case RENDERPATH_D3D9:
4344 #ifdef SUPPORTD3D
4345                 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4346                 if (vertexbuffer)
4347                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4348                 else
4349                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4350                 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4351                 gl_state.d3dvertexdata = (void *)vertex;
4352                 gl_state.d3dvertexsize = sizeof(*vertex);
4353 #endif
4354                 break;
4355         case RENDERPATH_D3D10:
4356                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4357                 break;
4358         case RENDERPATH_D3D11:
4359                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4360                 break;
4361         case RENDERPATH_SOFT:
4362                 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4363                 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4364                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4365                 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4366                 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4367                 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4368                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4369                 break;
4370         }
4371 }
4372
4373
4374
4375 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4376 {
4377         size_t size;
4378         size = sizeof(r_vertexmesh_t) * numvertices;
4379         if (gl_state.preparevertices_tempdatamaxsize < size)
4380         {
4381                 gl_state.preparevertices_tempdatamaxsize = size;
4382                 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4383         }
4384         gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4385         gl_state.preparevertices_numvertices = numvertices;
4386         return gl_state.preparevertices_vertexmesh;
4387 }
4388
4389 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4390 {
4391         R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4392         gl_state.preparevertices_vertexmesh = NULL;
4393         gl_state.preparevertices_numvertices = 0;
4394         return true;
4395 }
4396
4397 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)
4398 {
4399         int i;
4400         r_vertexmesh_t *vertex;
4401         switch(vid.renderpath)
4402         {
4403         case RENDERPATH_GL20:
4404         case RENDERPATH_GLES2:
4405                 if (!vid.useinterleavedarrays)
4406                 {
4407                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4408                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4409                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4410                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4411                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4412                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4413                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4414                         return;
4415                 }
4416                 break;
4417         case RENDERPATH_GL11:
4418         case RENDERPATH_GL13:
4419         case RENDERPATH_GLES1:
4420                 if (!vid.useinterleavedarrays)
4421                 {
4422                         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4423                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4424                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4425                         if (vid.texunits >= 2)
4426                                 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4427                         if (vid.texunits >= 3)
4428                                 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4429                         return;
4430                 }
4431                 break;
4432         case RENDERPATH_D3D9:
4433         case RENDERPATH_D3D10:
4434         case RENDERPATH_D3D11:
4435                 break;
4436         case RENDERPATH_SOFT:
4437                 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4438                 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4439                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4440                 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4441                 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4442                 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4443                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4444                 return;
4445         }
4446
4447         vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4448         for (i = 0;i < numvertices;i++)
4449                 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4450         if (svector3f)
4451                 for (i = 0;i < numvertices;i++)
4452                         VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4453         if (tvector3f)
4454                 for (i = 0;i < numvertices;i++)
4455                         VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4456         if (normal3f)
4457                 for (i = 0;i < numvertices;i++)
4458                         VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4459         if (color4f)
4460         {
4461                 for (i = 0;i < numvertices;i++)
4462                         Vector4Copy(color4f + 4*i, vertex[i].color4f);
4463         }
4464         else
4465         {
4466                 for (i = 0;i < numvertices;i++)
4467                         Vector4Copy(gl_state.color4f, vertex[i].color4f);
4468         }
4469         if (texcoordtexture2f)
4470                 for (i = 0;i < numvertices;i++)
4471                         Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4472         if (texcoordlightmap2f)
4473                 for (i = 0;i < numvertices;i++)
4474                         Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4475         R_Mesh_PrepareVertices_Mesh_Unlock();
4476         R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4477 }
4478
4479 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4480 {
4481         // upload temporary vertexbuffer for this rendering
4482         if (!gl_state.usevbo_staticvertex)
4483                 vertexbuffer = NULL;
4484         if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4485         {
4486                 if (gl_state.preparevertices_dynamicvertexbuffer)
4487                         R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4488                 else
4489                         gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4490                 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4491         }
4492         switch(vid.renderpath)
4493         {
4494         case RENDERPATH_GL20:
4495         case RENDERPATH_GLES2:
4496                 if (vertexbuffer)
4497                 {
4498                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4499                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4500                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
4501                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(*vertex), vertex->svector3f         , vertexbuffer, (int)((unsigned char *)vertex->svector3f          - (unsigned char *)vertex));
4502                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(*vertex), vertex->tvector3f         , vertexbuffer, (int)((unsigned char *)vertex->tvector3f          - (unsigned char *)vertex));
4503                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(*vertex), vertex->normal3f          , vertexbuffer, (int)((unsigned char *)vertex->normal3f           - (unsigned char *)vertex));
4504                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4505                 }
4506                 else
4507                 {
4508                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4509                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4510                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4511                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT        , sizeof(*vertex), vertex->svector3f         , NULL, 0);
4512                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT        , sizeof(*vertex), vertex->tvector3f         , NULL, 0);
4513                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT        , sizeof(*vertex), vertex->normal3f          , NULL, 0);
4514                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4515                 }
4516                 break;
4517         case RENDERPATH_GL13:
4518         case RENDERPATH_GLES1:
4519                 if (vertexbuffer)
4520                 {
4521                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4522                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4523                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
4524                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4525                 }
4526                 else
4527                 {
4528                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4529                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4530                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4531                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4532                 }
4533                 break;
4534         case RENDERPATH_GL11:
4535                 if (vertexbuffer)
4536                 {
4537                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , vertexbuffer, (int)((unsigned char *)vertex->vertex3f           - (unsigned char *)vertex));
4538                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , vertexbuffer, (int)((unsigned char *)vertex->color4f            - (unsigned char *)vertex));
4539                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f  - (unsigned char *)vertex));
4540                 }
4541                 else
4542                 {
4543                         R_Mesh_VertexPointer(     3, GL_FLOAT        , sizeof(*vertex), vertex->vertex3f          , NULL, 0);
4544                         R_Mesh_ColorPointer(      4, GL_FLOAT        , sizeof(*vertex), vertex->color4f           , NULL, 0);
4545                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT        , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4546                 }
4547                 break;
4548         case RENDERPATH_D3D9:
4549 #ifdef SUPPORTD3D
4550                 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4551                 if (vertexbuffer)
4552                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4553                 else
4554                         IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4555                 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4556                 gl_state.d3dvertexdata = (void *)vertex;
4557                 gl_state.d3dvertexsize = sizeof(*vertex);
4558 #endif
4559                 break;
4560         case RENDERPATH_D3D10:
4561                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4562                 break;
4563         case RENDERPATH_D3D11:
4564                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4565                 break;
4566         case RENDERPATH_SOFT:
4567                 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4568                 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4569                 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4570                 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4571                 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4572                 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4573                 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);
4574                 break;
4575         }
4576 }
4577
4578 void GL_BlendEquationSubtract(qboolean negated)
4579 {
4580         if(negated)
4581         {
4582                 switch(vid.renderpath)
4583                 {
4584                 case RENDERPATH_GL11:
4585                 case RENDERPATH_GL13:
4586                 case RENDERPATH_GL20:
4587                 case RENDERPATH_GLES1:
4588                 case RENDERPATH_GLES2:
4589                         qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT);
4590                         break;
4591                 case RENDERPATH_D3D9:
4592 #ifdef SUPPORTD3D
4593                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
4594 #endif
4595                         break;
4596                 case RENDERPATH_D3D10:
4597                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4598                         break;
4599                 case RENDERPATH_D3D11:
4600                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4601                         break;
4602                 case RENDERPATH_SOFT:
4603                         DPSOFTRAST_BlendSubtract(true);
4604                         break;
4605                 }
4606         }
4607         else
4608         {
4609                 switch(vid.renderpath)
4610                 {
4611                 case RENDERPATH_GL11:
4612                 case RENDERPATH_GL13:
4613                 case RENDERPATH_GL20:
4614                 case RENDERPATH_GLES1:
4615                 case RENDERPATH_GLES2:
4616                         qglBlendEquationEXT(GL_FUNC_ADD);
4617                         break;
4618                 case RENDERPATH_D3D9:
4619 #ifdef SUPPORTD3D
4620                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_ADD);
4621 #endif
4622                         break;
4623                 case RENDERPATH_D3D10:
4624                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4625                         break;
4626                 case RENDERPATH_D3D11:
4627                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4628                         break;
4629                 case RENDERPATH_SOFT:
4630                         DPSOFTRAST_BlendSubtract(false);
4631                         break;
4632                 }
4633         }
4634 }