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