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