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