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