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