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