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