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