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