added r_transparent_sortsurfacesbynearest cvar (default 1), this
[xonotic/darkplaces.git] / gl_backend.c
1
2 #include "quakedef.h"
3 #include "cl_collision.h"
4 #include "dpsoftrast.h"
5 #ifdef SUPPORTD3D
6 #include <d3d9.h>
7 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
8 extern D3DCAPS9 vid_d3d9caps;
9 #endif
10
11 // on GLES we have to use some proper #define's
12 #ifndef GL_FRAMEBUFFER
13 #define GL_FRAMEBUFFER                                   0x8D40
14 #define GL_DEPTH_ATTACHMENT                              0x8D00
15 #define GL_COLOR_ATTACHMENT0                             0x8CE0
16 #define GL_INVALID_FRAMEBUFFER_OPERATION                 0x0506
17 #endif
18 #ifndef GL_COLOR_ATTACHMENT1
19 #define GL_COLOR_ATTACHMENT1                             0x8CE1
20 #define GL_COLOR_ATTACHMENT2                             0x8CE2
21 #define GL_COLOR_ATTACHMENT3                             0x8CE3
22 #define GL_COLOR_ATTACHMENT4                             0x8CE4
23 #define GL_COLOR_ATTACHMENT5                             0x8CE5
24 #define GL_COLOR_ATTACHMENT6                             0x8CE6
25 #define GL_COLOR_ATTACHMENT7                             0x8CE7
26 #define GL_COLOR_ATTACHMENT8                             0x8CE8
27 #define GL_COLOR_ATTACHMENT9                             0x8CE9
28 #define GL_COLOR_ATTACHMENT10                            0x8CEA
29 #define GL_COLOR_ATTACHMENT11                            0x8CEB
30 #define GL_COLOR_ATTACHMENT12                            0x8CEC
31 #define GL_COLOR_ATTACHMENT13                            0x8CED
32 #define GL_COLOR_ATTACHMENT14                            0x8CEE
33 #define GL_COLOR_ATTACHMENT15                            0x8CEF
34 #endif
35 #ifndef GL_ARRAY_BUFFER
36 #define GL_ARRAY_BUFFER               0x8892
37 #define GL_ELEMENT_ARRAY_BUFFER       0x8893
38 #endif
39 //#ifndef GL_VERTEX_ARRAY
40 //#define GL_VERTEX_ARRAY                               0x8074
41 //#define GL_COLOR_ARRAY                                0x8076
42 //#define GL_TEXTURE_COORD_ARRAY                        0x8078
43 //#endif
44 #ifndef GL_TEXTURE0
45 #define GL_TEXTURE0                                     0x84C0
46 #define GL_TEXTURE1                                     0x84C1
47 #define GL_TEXTURE2                                     0x84C2
48 #define GL_TEXTURE3                                     0x84C3
49 #define GL_TEXTURE4                                     0x84C4
50 #define GL_TEXTURE5                                     0x84C5
51 #define GL_TEXTURE6                                     0x84C6
52 #define GL_TEXTURE7                                     0x84C7
53 #define GL_TEXTURE8                                     0x84C8
54 #define GL_TEXTURE9                                     0x84C9
55 #define GL_TEXTURE10                            0x84CA
56 #define GL_TEXTURE11                            0x84CB
57 #define GL_TEXTURE12                            0x84CC
58 #define GL_TEXTURE13                            0x84CD
59 #define GL_TEXTURE14                            0x84CE
60 #define GL_TEXTURE15                            0x84CF
61 #define GL_TEXTURE16                            0x84D0
62 #define GL_TEXTURE17                            0x84D1
63 #define GL_TEXTURE18                            0x84D2
64 #define GL_TEXTURE19                            0x84D3
65 #define GL_TEXTURE20                            0x84D4
66 #define GL_TEXTURE21                            0x84D5
67 #define GL_TEXTURE22                            0x84D6
68 #define GL_TEXTURE23                            0x84D7
69 #define GL_TEXTURE24                            0x84D8
70 #define GL_TEXTURE25                            0x84D9
71 #define GL_TEXTURE26                            0x84DA
72 #define GL_TEXTURE27                            0x84DB
73 #define GL_TEXTURE28                            0x84DC
74 #define GL_TEXTURE29                            0x84DD
75 #define GL_TEXTURE30                            0x84DE
76 #define GL_TEXTURE31                            0x84DF
77 #endif
78
79 #ifndef GL_TEXTURE_3D
80 #define GL_TEXTURE_3D                           0x806F
81 #endif
82 #ifndef GL_TEXTURE_CUBE_MAP
83 #define GL_TEXTURE_CUBE_MAP                 0x8513
84 #endif
85 //#ifndef GL_MODELVIEW
86 //#define GL_MODELVIEW                          0x1700
87 //#endif
88 //#ifndef GL_PROJECTION
89 //#define GL_PROJECTION                         0x1701
90 //#endif
91 //#ifndef GL_DECAL
92 //#define GL_DECAL                              0x2101
93 //#endif
94 //#ifndef GL_INTERPOLATE
95 //#define GL_INTERPOLATE                                0x8575
96 //#endif
97
98
99 #define MAX_RENDERTARGETS 4
100
101 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
102 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
103 cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
104 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
105 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
106
107 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
108 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
109 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
110 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
111 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
112 cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
113 cvar_t gl_vbo_dynamicvertex = {CVAR_SAVE, "gl_vbo_dynamicvertex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
114 cvar_t gl_vbo_dynamicindex = {CVAR_SAVE, "gl_vbo_dynamicindex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
115 cvar_t gl_fbo = {CVAR_SAVE, "gl_fbo", "1", "make use of GL_ARB_framebuffer_object extension to enable shadowmaps and other features using pixel formats different from the framebuffer"};
116
117 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
118 qboolean v_flipped_state = false;
119
120 r_viewport_t gl_viewport;
121 matrix4x4_t gl_modelmatrix;
122 matrix4x4_t gl_viewmatrix;
123 matrix4x4_t gl_modelviewmatrix;
124 matrix4x4_t gl_projectionmatrix;
125 matrix4x4_t gl_modelviewprojectionmatrix;
126 float gl_modelview16f[16];
127 float gl_modelviewprojection16f[16];
128 qboolean gl_modelmatrixchanged;
129
130 int gl_maxdrawrangeelementsvertices;
131 int gl_maxdrawrangeelementsindices;
132
133 #ifdef DEBUGGL
134 int errornumber = 0;
135
136 void GL_PrintError(int errornumber, const char *filename, int linenumber)
137 {
138         switch(errornumber)
139         {
140 #ifdef GL_INVALID_ENUM
141         case GL_INVALID_ENUM:
142                 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
143                 break;
144 #endif
145 #ifdef GL_INVALID_VALUE
146         case GL_INVALID_VALUE:
147                 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
148                 break;
149 #endif
150 #ifdef GL_INVALID_OPERATION
151         case GL_INVALID_OPERATION:
152                 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
153                 break;
154 #endif
155 #ifdef GL_STACK_OVERFLOW
156         case GL_STACK_OVERFLOW:
157                 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
158                 break;
159 #endif
160 #ifdef GL_STACK_UNDERFLOW
161         case GL_STACK_UNDERFLOW:
162                 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
163                 break;
164 #endif
165 #ifdef GL_OUT_OF_MEMORY
166         case GL_OUT_OF_MEMORY:
167                 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
168                 break;
169 #endif
170 #ifdef GL_TABLE_TOO_LARGE
171         case GL_TABLE_TOO_LARGE:
172                 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
173                 break;
174 #endif
175 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION
176         case GL_INVALID_FRAMEBUFFER_OPERATION:
177                 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
178                 break;
179 #endif
180         default:
181                 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
182                 break;
183         }
184 }
185 #endif
186
187 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
188
189 void SCR_ScreenShot_f (void);
190
191 typedef struct gltextureunit_s
192 {
193         int pointer_texcoord_components;
194         int pointer_texcoord_gltype;
195         size_t pointer_texcoord_stride;
196         const void *pointer_texcoord_pointer;
197         const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
198         size_t pointer_texcoord_offset;
199
200         rtexture_t *texture;
201         int t2d, t3d, tcubemap;
202         int arrayenabled;
203         int rgbscale, alphascale;
204         int combine;
205         int combinergb, combinealpha;
206         // texmatrixenabled exists only to avoid unnecessary texmatrix compares
207         int texmatrixenabled;
208         matrix4x4_t matrix;
209 }
210 gltextureunit_t;
211
212 typedef struct gl_state_s
213 {
214         int cullface;
215         int cullfaceenable;
216         int blendfunc1;
217         int blendfunc2;
218         qboolean blend;
219         GLboolean depthmask;
220         int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
221         int depthtest;
222         int depthfunc;
223         float depthrange[2];
224         float polygonoffset[2];
225         int alphatest;
226         int alphafunc;
227         float alphafuncvalue;
228         qboolean alphatocoverage;
229         int scissortest;
230         unsigned int unit;
231         unsigned int clientunit;
232         gltextureunit_t units[MAX_TEXTUREUNITS];
233         float color4f[4];
234         int lockrange_first;
235         int lockrange_count;
236         int vertexbufferobject;
237         int elementbufferobject;
238         int framebufferobject;
239         int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
240         qboolean pointer_color_enabled;
241
242         int pointer_vertex_components;
243         int pointer_vertex_gltype;
244         size_t pointer_vertex_stride;
245         const void *pointer_vertex_pointer;
246         const r_meshbuffer_t *pointer_vertex_vertexbuffer;
247         size_t pointer_vertex_offset;
248
249         int pointer_color_components;
250         int pointer_color_gltype;
251         size_t pointer_color_stride;
252         const void *pointer_color_pointer;
253         const r_meshbuffer_t *pointer_color_vertexbuffer;
254         size_t pointer_color_offset;
255
256         void *preparevertices_tempdata;
257         size_t preparevertices_tempdatamaxsize;
258         r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
259         r_vertexgeneric_t *preparevertices_vertexgeneric;
260         r_vertexmesh_t *preparevertices_vertexmesh;
261         int preparevertices_numvertices;
262
263         r_meshbuffer_t *draw_dynamicindexbuffer;
264
265         qboolean usevbo_staticvertex;
266         qboolean usevbo_staticindex;
267         qboolean usevbo_dynamicvertex;
268         qboolean usevbo_dynamicindex;
269
270         memexpandablearray_t meshbufferarray;
271
272         qboolean active;
273
274 #ifdef SUPPORTD3D
275 //      rtexture_t *d3drt_depthtexture;
276 //      rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
277         IDirect3DSurface9 *d3drt_depthsurface;
278         IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
279         IDirect3DSurface9 *d3drt_backbufferdepthsurface;
280         IDirect3DSurface9 *d3drt_backbuffercolorsurface;
281         void *d3dvertexbuffer;
282         void *d3dvertexdata;
283         size_t d3dvertexsize;
284 #endif
285 }
286 gl_state_t;
287
288 static gl_state_t gl_state;
289
290
291 /*
292 note: here's strip order for a terrain row:
293 0--1--2--3--4
294 |\ |\ |\ |\ |
295 | \| \| \| \|
296 A--B--C--D--E
297 clockwise
298
299 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
300
301 *elements++ = i + row;
302 *elements++ = i;
303 *elements++ = i + row + 1;
304 *elements++ = i;
305 *elements++ = i + 1;
306 *elements++ = i + row + 1;
307
308
309 for (y = 0;y < rows - 1;y++)
310 {
311         for (x = 0;x < columns - 1;x++)
312         {
313                 i = y * rows + x;
314                 *elements++ = i + columns;
315                 *elements++ = i;
316                 *elements++ = i + columns + 1;
317                 *elements++ = i;
318                 *elements++ = i + 1;
319                 *elements++ = i + columns + 1;
320         }
321 }
322
323 alternative:
324 0--1--2--3--4
325 | /| /|\ | /|
326 |/ |/ | \|/ |
327 A--B--C--D--E
328 counterclockwise
329
330 for (y = 0;y < rows - 1;y++)
331 {
332         for (x = 0;x < columns - 1;x++)
333         {
334                 i = y * rows + x;
335                 *elements++ = i;
336                 *elements++ = i + columns;
337                 *elements++ = i + columns + 1;
338                 *elements++ = i + columns;
339                 *elements++ = i + columns + 1;
340                 *elements++ = i + 1;
341         }
342 }
343 */
344
345 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
346 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
347 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
348 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
349
350 static void GL_VBOStats_f(void)
351 {
352         GL_Mesh_ListVBOs(true);
353 }
354
355 static void GL_Backend_ResetState(void);
356
357 static void R_Mesh_InitVertexDeclarations(void);
358 static void R_Mesh_DestroyVertexDeclarations(void);
359
360 static void R_Mesh_SetUseVBO(void)
361 {
362         switch(vid.renderpath)
363         {
364         case RENDERPATH_GL11:
365         case RENDERPATH_GL13:
366         case RENDERPATH_GL20:
367         case RENDERPATH_GLES1:
368                 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
369                 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
370                 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
371                 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
372                 break;
373         case RENDERPATH_D3D9:
374                 gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
375                 gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo;
376                 break;
377         case RENDERPATH_D3D10:
378                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
379                 break;
380         case RENDERPATH_D3D11:
381                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
382                 break;
383         case RENDERPATH_SOFT:
384                 gl_state.usevbo_staticvertex = false;
385                 gl_state.usevbo_staticindex = false;
386                 gl_state.usevbo_dynamicvertex = false;
387                 gl_state.usevbo_dynamicindex = false;
388                 break;
389         case RENDERPATH_GLES2:
390                 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
391                 gl_state.usevbo_staticindex = false;
392                 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
393                 gl_state.usevbo_dynamicindex = false;
394                 break;
395         }
396 }
397
398 static void gl_backend_start(void)
399 {
400         memset(&gl_state, 0, sizeof(gl_state));
401
402         R_Mesh_InitVertexDeclarations();
403
404         R_Mesh_SetUseVBO();
405         Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
406
407         Con_DPrintf("OpenGL backend started.\n");
408
409         CHECKGLERROR
410
411         GL_Backend_ResetState();
412
413         switch(vid.renderpath)
414         {
415         case RENDERPATH_GL11:
416         case RENDERPATH_GL13:
417         case RENDERPATH_GL20:
418         case RENDERPATH_GLES1:
419         case RENDERPATH_GLES2:
420                 // fetch current fbo here (default fbo is not 0 on some GLES devices)
421                 if (vid.support.ext_framebuffer_object)
422                         qglGetIntegerv(GL_FRAMEBUFFER_BINDING, &gl_state.defaultframebufferobject);
423                 break;
424         case RENDERPATH_D3D9:
425 #ifdef SUPPORTD3D
426                 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
427                 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
428 #endif
429                 break;
430         case RENDERPATH_D3D10:
431                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
432                 break;
433         case RENDERPATH_D3D11:
434                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
435                 break;
436         case RENDERPATH_SOFT:
437                 break;
438         }
439 }
440
441 static void gl_backend_shutdown(void)
442 {
443         Con_DPrint("OpenGL Backend shutting down\n");
444
445         switch(vid.renderpath)
446         {
447         case RENDERPATH_GL11:
448         case RENDERPATH_GL13:
449         case RENDERPATH_GL20:
450         case RENDERPATH_SOFT:
451         case RENDERPATH_GLES1:
452         case RENDERPATH_GLES2:
453                 break;
454         case RENDERPATH_D3D9:
455 #ifdef SUPPORTD3D
456                 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
457                 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
458 #endif
459                 break;
460         case RENDERPATH_D3D10:
461                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
462                 break;
463         case RENDERPATH_D3D11:
464                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
465                 break;
466         }
467
468         if (gl_state.preparevertices_tempdata)
469                 Mem_Free(gl_state.preparevertices_tempdata);
470         if (gl_state.preparevertices_dynamicvertexbuffer)
471                 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
472
473         Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
474
475         R_Mesh_DestroyVertexDeclarations();
476
477         memset(&gl_state, 0, sizeof(gl_state));
478 }
479
480 static void gl_backend_newmap(void)
481 {
482 }
483
484 static void gl_backend_devicelost(void)
485 {
486         int i, endindex;
487         r_meshbuffer_t *buffer;
488 #ifdef SUPPORTD3D
489         gl_state.d3dvertexbuffer = NULL;
490 #endif
491         switch(vid.renderpath)
492         {
493         case RENDERPATH_GL11:
494         case RENDERPATH_GL13:
495         case RENDERPATH_GL20:
496         case RENDERPATH_SOFT:
497         case RENDERPATH_GLES1:
498         case RENDERPATH_GLES2:
499                 break;
500         case RENDERPATH_D3D9:
501 #ifdef SUPPORTD3D
502                 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
503                 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
504 #endif
505                 break;
506         case RENDERPATH_D3D10:
507                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
508                 break;
509         case RENDERPATH_D3D11:
510                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
511                 break;
512         }
513         endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
514         for (i = 0;i < endindex;i++)
515         {
516                 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
517                 if (!buffer || !buffer->isdynamic)
518                         continue;
519                 switch(vid.renderpath)
520                 {
521                 case RENDERPATH_GL11:
522                 case RENDERPATH_GL13:
523                 case RENDERPATH_GL20:
524                 case RENDERPATH_SOFT:
525                 case RENDERPATH_GLES1:
526                 case RENDERPATH_GLES2:
527                         break;
528                 case RENDERPATH_D3D9:
529 #ifdef SUPPORTD3D
530                         if (buffer->devicebuffer)
531                         {
532                                 if (buffer->isindexbuffer)
533                                         IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
534                                 else
535                                         IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
536                                 buffer->devicebuffer = NULL;
537                         }
538 #endif
539                         break;
540                 case RENDERPATH_D3D10:
541                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
542                         break;
543                 case RENDERPATH_D3D11:
544                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
545                         break;
546                 }
547         }
548 }
549
550 static void gl_backend_devicerestored(void)
551 {
552         switch(vid.renderpath)
553         {
554         case RENDERPATH_GL11:
555         case RENDERPATH_GL13:
556         case RENDERPATH_GL20:
557         case RENDERPATH_SOFT:
558         case RENDERPATH_GLES1:
559         case RENDERPATH_GLES2:
560                 break;
561         case RENDERPATH_D3D9:
562 #ifdef SUPPORTD3D
563                 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
564                 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
565 #endif
566                 break;
567         case RENDERPATH_D3D10:
568                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
569                 break;
570         case RENDERPATH_D3D11:
571                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
572                 break;
573         }
574 }
575
576 void gl_backend_init(void)
577 {
578         int i;
579
580         for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
581         {
582                 polygonelement3s[i * 3 + 0] = 0;
583                 polygonelement3s[i * 3 + 1] = i + 1;
584                 polygonelement3s[i * 3 + 2] = i + 2;
585         }
586         // elements for rendering a series of quads as triangles
587         for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
588         {
589                 quadelement3s[i * 6 + 0] = i * 4;
590                 quadelement3s[i * 6 + 1] = i * 4 + 1;
591                 quadelement3s[i * 6 + 2] = i * 4 + 2;
592                 quadelement3s[i * 6 + 3] = i * 4;
593                 quadelement3s[i * 6 + 4] = i * 4 + 2;
594                 quadelement3s[i * 6 + 5] = i * 4 + 3;
595         }
596
597         for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
598                 polygonelement3i[i] = polygonelement3s[i];
599         for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
600                 quadelement3i[i] = quadelement3s[i];
601
602         Cvar_RegisterVariable(&r_render);
603         Cvar_RegisterVariable(&r_renderview);
604         Cvar_RegisterVariable(&r_waterwarp);
605         Cvar_RegisterVariable(&gl_polyblend);
606         Cvar_RegisterVariable(&v_flipped);
607         Cvar_RegisterVariable(&gl_dither);
608         Cvar_RegisterVariable(&gl_vbo);
609         Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
610         Cvar_RegisterVariable(&gl_vbo_dynamicindex);
611         Cvar_RegisterVariable(&gl_paranoid);
612         Cvar_RegisterVariable(&gl_printcheckerror);
613
614         Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
615         Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
616         Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
617
618         Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
619
620         R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
621 }
622
623 void GL_SetMirrorState(qboolean state);
624
625 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
626 {
627         vec4_t temp;
628         float iw;
629         Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
630         Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
631         iw = 1.0f / out[3];
632         out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
633
634         // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
635         //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
636         out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
637
638         out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
639 }
640
641 void GL_Finish(void)
642 {
643         switch(vid.renderpath)
644         {
645         case RENDERPATH_GL11:
646         case RENDERPATH_GL13:
647         case RENDERPATH_GL20:
648         case RENDERPATH_GLES1:
649         case RENDERPATH_GLES2:
650                 qglFinish();
651                 break;
652         case RENDERPATH_D3D9:
653                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
654                 break;
655         case RENDERPATH_D3D10:
656                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
657                 break;
658         case RENDERPATH_D3D11:
659                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
660                 break;
661         case RENDERPATH_SOFT:
662                 DPSOFTRAST_Finish();
663                 break;
664         }
665 }
666
667 static int bboxedges[12][2] =
668 {
669         // top
670         {0, 1}, // +X
671         {0, 2}, // +Y
672         {1, 3}, // Y, +X
673         {2, 3}, // X, +Y
674         // bottom
675         {4, 5}, // +X
676         {4, 6}, // +Y
677         {5, 7}, // Y, +X
678         {6, 7}, // X, +Y
679         // verticals
680         {0, 4}, // +Z
681         {1, 5}, // X, +Z
682         {2, 6}, // Y, +Z
683         {3, 7}, // XY, +Z
684 };
685
686 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
687 {
688         int i, ix1, iy1, ix2, iy2;
689         float x1, y1, x2, y2;
690         vec4_t v, v2;
691         float vertex[20][3];
692         int j, k;
693         vec4_t plane4f;
694         int numvertices;
695         float corner[8][4];
696         float dist[8];
697         int sign[8];
698         float f;
699
700         scissor[0] = r_refdef.view.viewport.x;
701         scissor[1] = r_refdef.view.viewport.y;
702         scissor[2] = r_refdef.view.viewport.width;
703         scissor[3] = r_refdef.view.viewport.height;
704
705         // if view is inside the box, just say yes it's visible
706         if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
707                 return false;
708
709         x1 = y1 = x2 = y2 = 0;
710
711         // transform all corners that are infront of the nearclip plane
712         VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
713         plane4f[3] = r_refdef.view.frustum[4].dist;
714         numvertices = 0;
715         for (i = 0;i < 8;i++)
716         {
717                 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
718                 dist[i] = DotProduct4(corner[i], plane4f);
719                 sign[i] = dist[i] > 0;
720                 if (!sign[i])
721                 {
722                         VectorCopy(corner[i], vertex[numvertices]);
723                         numvertices++;
724                 }
725         }
726         // if some points are behind the nearclip, add clipped edge points to make
727         // sure that the scissor boundary is complete
728         if (numvertices > 0 && numvertices < 8)
729         {
730                 // add clipped edge points
731                 for (i = 0;i < 12;i++)
732                 {
733                         j = bboxedges[i][0];
734                         k = bboxedges[i][1];
735                         if (sign[j] != sign[k])
736                         {
737                                 f = dist[j] / (dist[j] - dist[k]);
738                                 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
739                                 numvertices++;
740                         }
741                 }
742         }
743
744         // if we have no points to check, it is behind the view plane
745         if (!numvertices)
746                 return true;
747
748         // if we have some points to transform, check what screen area is covered
749         x1 = y1 = x2 = y2 = 0;
750         v[3] = 1.0f;
751         //Con_Printf("%i vertices to transform...\n", numvertices);
752         for (i = 0;i < numvertices;i++)
753         {
754                 VectorCopy(vertex[i], v);
755                 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
756                 //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
757                 if (i)
758                 {
759                         if (x1 > v2[0]) x1 = v2[0];
760                         if (x2 < v2[0]) x2 = v2[0];
761                         if (y1 > v2[1]) y1 = v2[1];
762                         if (y2 < v2[1]) y2 = v2[1];
763                 }
764                 else
765                 {
766                         x1 = x2 = v2[0];
767                         y1 = y2 = v2[1];
768                 }
769         }
770
771         // now convert the scissor rectangle to integer screen coordinates
772         ix1 = (int)(x1 - 1.0f);
773         //iy1 = vid.height - (int)(y2 - 1.0f);
774         //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
775         iy1 = (int)(y1 - 1.0f);
776         ix2 = (int)(x2 + 1.0f);
777         //iy2 = vid.height - (int)(y1 + 1.0f);
778         //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
779         iy2 = (int)(y2 + 1.0f);
780         //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
781
782         // clamp it to the screen
783         if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
784         if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
785         if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
786         if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
787
788         // if it is inside out, it's not visible
789         if (ix2 <= ix1 || iy2 <= iy1)
790                 return true;
791
792         // the light area is visible, set up the scissor rectangle
793         scissor[0] = ix1;
794         scissor[1] = iy1;
795         scissor[2] = ix2 - ix1;
796         scissor[3] = iy2 - iy1;
797
798         // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
799         switch(vid.renderpath)
800         {
801         case RENDERPATH_D3D9:
802         case RENDERPATH_D3D10:
803         case RENDERPATH_D3D11:
804                 scissor[1] = vid.height - scissor[1] - scissor[3];
805                 break;
806         case RENDERPATH_GL11:
807         case RENDERPATH_GL13:
808         case RENDERPATH_GL20:
809         case RENDERPATH_SOFT:
810         case RENDERPATH_GLES1:
811         case RENDERPATH_GLES2:
812                 break;
813         }
814
815         return false;
816 }
817
818
819 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
820 {
821         float q[4];
822         float d;
823         float clipPlane[4], v3[3], v4[3];
824         float normal[3];
825
826         // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
827
828         VectorSet(normal, normalx, normaly, normalz);
829         Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
830         VectorScale(normal, -dist, v3);
831         Matrix4x4_Transform(&v->viewmatrix, v3, v4);
832         // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
833         clipPlane[3] = -DotProduct(v4, clipPlane);
834
835 #if 0
836 {
837         // testing code for comparing results
838         float clipPlane2[4];
839         VectorCopy4(clipPlane, clipPlane2);
840         R_EntityMatrix(&identitymatrix);
841         VectorSet(q, normal[0], normal[1], normal[2], -dist);
842         qglClipPlane(GL_CLIP_PLANE0, q);
843         qglGetClipPlane(GL_CLIP_PLANE0, q);
844         VectorCopy4(q, clipPlane);
845 }
846 #endif
847
848         // Calculate the clip-space corner point opposite the clipping plane
849         // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
850         // transform it into camera space by multiplying it
851         // by the inverse of the projection matrix
852         q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
853         q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
854         q[2] = -1.0f;
855         q[3] = (1.0f + m[10]) / m[14];
856
857         // Calculate the scaled plane vector
858         d = 2.0f / DotProduct4(clipPlane, q);
859
860         // Replace the third row of the projection matrix
861         m[2] = clipPlane[0] * d;
862         m[6] = clipPlane[1] * d;
863         m[10] = clipPlane[2] * d + 1.0f;
864         m[14] = clipPlane[3] * d;
865 }
866
867 void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float x1, float y1, float x2, float y2, float nearclip, float farclip, const float *nearplane)
868 {
869         float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
870         float m[16];
871         memset(v, 0, sizeof(*v));
872         v->type = R_VIEWPORTTYPE_ORTHO;
873         v->cameramatrix = *cameramatrix;
874         v->x = x;
875         v->y = y;
876         v->z = 0;
877         v->width = width;
878         v->height = height;
879         v->depth = 1;
880         memset(m, 0, sizeof(m));
881         m[0]  = 2/(right - left);
882         m[5]  = 2/(top - bottom);
883         m[10] = -2/(zFar - zNear);
884         m[12] = - (right + left)/(right - left);
885         m[13] = - (top + bottom)/(top - bottom);
886         m[14] = - (zFar + zNear)/(zFar - zNear);
887         m[15] = 1;
888         switch(vid.renderpath)
889         {
890         case RENDERPATH_GL11:
891         case RENDERPATH_GL13:
892         case RENDERPATH_GL20:
893         case RENDERPATH_SOFT:
894         case RENDERPATH_GLES1:
895         case RENDERPATH_GLES2:
896                 break;
897         case RENDERPATH_D3D9:
898         case RENDERPATH_D3D10:
899         case RENDERPATH_D3D11:
900                 m[10] = -1/(zFar - zNear);
901                 m[14] = -zNear/(zFar-zNear);
902                 break;
903         }
904         v->screentodepth[0] = -farclip / (farclip - nearclip);
905         v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
906
907         Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
908
909         if (nearplane)
910                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
911
912         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
913
914 #if 0
915         {
916                 vec4_t test1;
917                 vec4_t test2;
918                 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
919                 R_Viewport_TransformToScreen(v, test1, test2);
920                 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
921         }
922 #endif
923 }
924
925 void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane)
926 {
927         matrix4x4_t tempmatrix, basematrix;
928         float m[16];
929         memset(v, 0, sizeof(*v));
930
931         v->type = R_VIEWPORTTYPE_PERSPECTIVE;
932         v->cameramatrix = *cameramatrix;
933         v->x = x;
934         v->y = y;
935         v->z = 0;
936         v->width = width;
937         v->height = height;
938         v->depth = 1;
939         memset(m, 0, sizeof(m));
940         m[0]  = 1.0 / frustumx;
941         m[5]  = 1.0 / frustumy;
942         m[10] = -(farclip + nearclip) / (farclip - nearclip);
943         m[11] = -1;
944         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
945         v->screentodepth[0] = -farclip / (farclip - nearclip);
946         v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
947
948         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
949         Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
950         Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
951         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
952
953         if (nearplane)
954                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
955
956         if(v_flipped.integer)
957         {
958                 m[0] = -m[0];
959                 m[4] = -m[4];
960                 m[8] = -m[8];
961                 m[12] = -m[12];
962         }
963
964         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
965 }
966
967 void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, const float *nearplane)
968 {
969         matrix4x4_t tempmatrix, basematrix;
970         const float nudge = 1.0 - 1.0 / (1<<23);
971         float m[16];
972         memset(v, 0, sizeof(*v));
973
974         v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
975         v->cameramatrix = *cameramatrix;
976         v->x = x;
977         v->y = y;
978         v->z = 0;
979         v->width = width;
980         v->height = height;
981         v->depth = 1;
982         memset(m, 0, sizeof(m));
983         m[ 0] = 1.0 / frustumx;
984         m[ 5] = 1.0 / frustumy;
985         m[10] = -nudge;
986         m[11] = -1;
987         m[14] = -2 * nearclip * nudge;
988         v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
989         v->screentodepth[1] = m[14] * -0.5;
990
991         Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
992         Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
993         Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
994         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
995
996         if (nearplane)
997                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
998
999         if(v_flipped.integer)
1000         {
1001                 m[0] = -m[0];
1002                 m[4] = -m[4];
1003                 m[8] = -m[8];
1004                 m[12] = -m[12];
1005         }
1006
1007         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1008 }
1009
1010 float cubeviewmatrix[6][16] =
1011 {
1012     // standard cubemap projections
1013     { // +X
1014          0, 0,-1, 0,
1015          0,-1, 0, 0,
1016         -1, 0, 0, 0,
1017          0, 0, 0, 1,
1018     },
1019     { // -X
1020          0, 0, 1, 0,
1021          0,-1, 0, 0,
1022          1, 0, 0, 0,
1023          0, 0, 0, 1,
1024     },
1025     { // +Y
1026          1, 0, 0, 0,
1027          0, 0,-1, 0,
1028          0, 1, 0, 0,
1029          0, 0, 0, 1,
1030     },
1031     { // -Y
1032          1, 0, 0, 0,
1033          0, 0, 1, 0,
1034          0,-1, 0, 0,
1035          0, 0, 0, 1,
1036     },
1037     { // +Z
1038          1, 0, 0, 0,
1039          0,-1, 0, 0,
1040          0, 0,-1, 0,
1041          0, 0, 0, 1,
1042     },
1043     { // -Z
1044         -1, 0, 0, 0,
1045          0,-1, 0, 0,
1046          0, 0, 1, 0,
1047          0, 0, 0, 1,
1048     },
1049 };
1050 float rectviewmatrix[6][16] =
1051 {
1052     // sign-preserving cubemap projections
1053     { // +X
1054          0, 0,-1, 0,
1055          0, 1, 0, 0,
1056          1, 0, 0, 0,
1057          0, 0, 0, 1,
1058     },
1059     { // -X
1060          0, 0, 1, 0,
1061          0, 1, 0, 0,
1062          1, 0, 0, 0,
1063          0, 0, 0, 1,
1064     },
1065     { // +Y
1066          1, 0, 0, 0,
1067          0, 0,-1, 0,
1068          0, 1, 0, 0,
1069          0, 0, 0, 1,
1070     },
1071     { // -Y
1072          1, 0, 0, 0,
1073          0, 0, 1, 0,
1074          0, 1, 0, 0,
1075          0, 0, 0, 1,
1076     },
1077     { // +Z
1078          1, 0, 0, 0,
1079          0, 1, 0, 0,
1080          0, 0,-1, 0,
1081          0, 0, 0, 1,
1082     },
1083     { // -Z
1084          1, 0, 0, 0,
1085          0, 1, 0, 0,
1086          0, 0, 1, 0,
1087          0, 0, 0, 1,
1088     },
1089 };
1090
1091 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
1092 {
1093         matrix4x4_t tempmatrix, basematrix;
1094         float m[16];
1095         memset(v, 0, sizeof(*v));
1096         v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1097         v->cameramatrix = *cameramatrix;
1098         v->width = size;
1099         v->height = size;
1100         v->depth = 1;
1101         memset(m, 0, sizeof(m));
1102         m[0] = m[5] = 1.0f;
1103         m[10] = -(farclip + nearclip) / (farclip - nearclip);
1104         m[11] = -1;
1105         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1106
1107         Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
1108         Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1109         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1110
1111         if (nearplane)
1112                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1113
1114         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1115 }
1116
1117 void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane)
1118 {
1119         matrix4x4_t tempmatrix, basematrix;
1120         float m[16];
1121         memset(v, 0, sizeof(*v));
1122         v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1123         v->cameramatrix = *cameramatrix;
1124         v->x = (side & 1) * size;
1125         v->y = (side >> 1) * size;
1126         v->width = size;
1127         v->height = size;
1128         v->depth = 1;
1129         memset(m, 0, sizeof(m));
1130         m[0] = m[5] = 1.0f * ((float)size - border) / size;
1131         m[10] = -(farclip + nearclip) / (farclip - nearclip);
1132         m[11] = -1;
1133         m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1134
1135         Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1136         Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1137         Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1138
1139         switch(vid.renderpath)
1140         {
1141         case RENDERPATH_GL20:
1142         case RENDERPATH_GL13:
1143         case RENDERPATH_GL11:
1144         case RENDERPATH_SOFT:
1145         case RENDERPATH_GLES1:
1146         case RENDERPATH_GLES2:
1147                 break;
1148         case RENDERPATH_D3D9:
1149                 m[5] *= -1;
1150                 break;
1151         case RENDERPATH_D3D10:
1152                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1153                 break;
1154         case RENDERPATH_D3D11:
1155                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1156                 break;
1157         }
1158
1159         if (nearplane)
1160                 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1161
1162         Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1163 }
1164
1165 void R_SetViewport(const r_viewport_t *v)
1166 {
1167         float m[16];
1168         gl_viewport = *v;
1169
1170         // FIXME: v_flipped_state is evil, this probably breaks somewhere
1171         GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1172
1173         // copy over the matrices to our state
1174         gl_viewmatrix = v->viewmatrix;
1175         gl_projectionmatrix = v->projectmatrix;
1176
1177         switch(vid.renderpath)
1178         {
1179         case RENDERPATH_GL13:
1180         case RENDERPATH_GL11:
1181         case RENDERPATH_GLES1:
1182 #ifdef GL_PROJECTION
1183                 CHECKGLERROR
1184                 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1185                 // Load the projection matrix into OpenGL
1186                 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1187                 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1188                 qglLoadMatrixf(m);CHECKGLERROR
1189                 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1190 #endif
1191                 break;
1192         case RENDERPATH_D3D9:
1193 #ifdef SUPPORTD3D
1194                 {
1195                         D3DVIEWPORT9 d3dviewport;
1196                         d3dviewport.X = gl_viewport.x;
1197                         d3dviewport.Y = gl_viewport.y;
1198                         d3dviewport.Width = gl_viewport.width;
1199                         d3dviewport.Height = gl_viewport.height;
1200                         d3dviewport.MinZ = gl_state.depthrange[0];
1201                         d3dviewport.MaxZ = gl_state.depthrange[1];
1202                         IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1203                 }
1204 #endif
1205                 break;
1206         case RENDERPATH_D3D10:
1207                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1208                 break;
1209         case RENDERPATH_D3D11:
1210                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1211                 break;
1212         case RENDERPATH_SOFT:
1213                 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1214                 break;
1215         case RENDERPATH_GL20:
1216         case RENDERPATH_GLES2:
1217                 CHECKGLERROR
1218                 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1219                 break;
1220         }
1221
1222         // force an update of the derived matrices
1223         gl_modelmatrixchanged = true;
1224         R_EntityMatrix(&gl_modelmatrix);
1225 }
1226
1227 void R_GetViewport(r_viewport_t *v)
1228 {
1229         *v = gl_viewport;
1230 }
1231
1232 static void GL_BindVBO(int bufferobject)
1233 {
1234         if (gl_state.vertexbufferobject != bufferobject)
1235         {
1236                 gl_state.vertexbufferobject = bufferobject;
1237                 CHECKGLERROR
1238                 qglBindBufferARB(GL_ARRAY_BUFFER, bufferobject);CHECKGLERROR
1239         }
1240 }
1241
1242 static void GL_BindEBO(int bufferobject)
1243 {
1244         if (gl_state.elementbufferobject != bufferobject)
1245         {
1246                 gl_state.elementbufferobject = bufferobject;
1247                 CHECKGLERROR
1248                 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, bufferobject);CHECKGLERROR
1249         }
1250 }
1251
1252 static const GLuint drawbuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
1253 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1254 {
1255         switch(vid.renderpath)
1256         {
1257         case RENDERPATH_GL11:
1258         case RENDERPATH_GL13:
1259         case RENDERPATH_GL20:
1260         case RENDERPATH_GLES1:
1261         case RENDERPATH_GLES2:
1262                 if (vid.support.arb_framebuffer_object)
1263                 {
1264                         int temp;
1265                         GLuint status;
1266                         qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
1267                         R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1268                         // GL_ARB_framebuffer_object (GL3-class hardware) - depth stencil attachment
1269                         if (depthtexture  && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, depthtexture->glisdepthstencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT  , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
1270                         if (depthtexture  && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, depthtexture->glisdepthstencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT  , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
1271                         if (colortexture  && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
1272                         if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
1273                         if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR
1274                         if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR
1275                         if (colortexture  && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR
1276                         if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR
1277                         if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
1278                         if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
1279
1280                         if (colortexture4 && qglDrawBuffersARB)
1281                         {
1282                                 qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
1283                                 qglReadBuffer(GL_NONE);CHECKGLERROR
1284                         }
1285                         else if (colortexture3 && qglDrawBuffersARB)
1286                         {
1287                                 qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR
1288                                 qglReadBuffer(GL_NONE);CHECKGLERROR
1289                         }
1290                         else if (colortexture2 && qglDrawBuffersARB)
1291                         {
1292                                 qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR
1293                                 qglReadBuffer(GL_NONE);CHECKGLERROR
1294                         }
1295                         else if (colortexture && qglDrawBuffer)
1296                         {
1297                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1298                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1299                         }
1300                         else if (qglDrawBuffer)
1301                         {
1302                                 qglDrawBuffer(GL_NONE);CHECKGLERROR
1303                                 qglReadBuffer(GL_NONE);CHECKGLERROR
1304                         }
1305                         status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
1306                         if (status != GL_FRAMEBUFFER_COMPLETE)
1307                         {
1308                                 Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
1309                                 qglDeleteFramebuffers(1, (GLuint*)&temp);
1310                                 temp = 0;
1311                         }
1312                         return temp;
1313                 }
1314                 else if (vid.support.ext_framebuffer_object)
1315                 {
1316                         int temp;
1317                         GLuint status;
1318                         qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
1319                         R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1320                         // GL_EXT_framebuffer_object (GL2-class hardware) - no depth stencil attachment, let it break stencil
1321                         if (depthtexture  && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT  , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
1322                         if (depthtexture  && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT  , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
1323                         if (colortexture  && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
1324                         if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
1325                         if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR
1326                         if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR
1327                         if (colortexture  && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR
1328                         if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR
1329                         if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
1330                         if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
1331
1332                         if (colortexture4 && qglDrawBuffersARB)
1333                         {
1334                                 qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
1335                                 qglReadBuffer(GL_NONE);CHECKGLERROR
1336                         }
1337                         else if (colortexture3 && qglDrawBuffersARB)
1338                         {
1339                                 qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR
1340                                 qglReadBuffer(GL_NONE);CHECKGLERROR
1341                         }
1342                         else if (colortexture2 && qglDrawBuffersARB)
1343                         {
1344                                 qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR
1345                                 qglReadBuffer(GL_NONE);CHECKGLERROR
1346                         }
1347                         else if (colortexture && qglDrawBuffer)
1348                         {
1349                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1350                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1351                         }
1352                         else if (qglDrawBuffer)
1353                         {
1354                                 qglDrawBuffer(GL_NONE);CHECKGLERROR
1355                                 qglReadBuffer(GL_NONE);CHECKGLERROR
1356                         }
1357                         status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
1358                         if (status != GL_FRAMEBUFFER_COMPLETE)
1359                         {
1360                                 Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
1361                                 qglDeleteFramebuffers(1, (GLuint*)&temp);
1362                                 temp = 0;
1363                         }
1364                         return temp;
1365                 }
1366                 return 0;
1367         case RENDERPATH_D3D9:
1368         case RENDERPATH_D3D10:
1369         case RENDERPATH_D3D11:
1370                 return 1;
1371         case RENDERPATH_SOFT:
1372                 return 1;
1373         }
1374         return 0;
1375 }
1376
1377 void R_Mesh_DestroyFramebufferObject(int fbo)
1378 {
1379         switch(vid.renderpath)
1380         {
1381         case RENDERPATH_GL11:
1382         case RENDERPATH_GL13:
1383         case RENDERPATH_GL20:
1384         case RENDERPATH_GLES1:
1385         case RENDERPATH_GLES2:
1386                 if (fbo)
1387                         qglDeleteFramebuffers(1, (GLuint*)&fbo);
1388                 break;
1389         case RENDERPATH_D3D9:
1390         case RENDERPATH_D3D10:
1391         case RENDERPATH_D3D11:
1392                 break;
1393         case RENDERPATH_SOFT:
1394                 break;
1395         }
1396 }
1397
1398 #ifdef SUPPORTD3D
1399 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1400 {
1401         gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1402         if (gl_state.d3drt_depthsurface != depthsurface)
1403         {
1404                 gl_state.d3drt_depthsurface = depthsurface;
1405                 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1406         }
1407         if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1408         {
1409                 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1410                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1411         }
1412         if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1413         {
1414                 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1415                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1416         }
1417         if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1418         {
1419                 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1420                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1421         }
1422         if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1423         {
1424                 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1425                 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1426         }
1427 }
1428 #endif
1429
1430 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1431 {
1432         unsigned int i;
1433         unsigned int j;
1434         rtexture_t *textures[5];
1435         Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1436         textures[4] = depthtexture;
1437         // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1438         for (j = 0;j < 5;j++)
1439                 if (textures[j])
1440                         for (i = 0;i < vid.teximageunits;i++)
1441                                 if (gl_state.units[i].texture == textures[j])
1442                                         R_Mesh_TexBind(i, NULL);
1443         // set up framebuffer object or render targets for the active rendering API
1444         switch(vid.renderpath)
1445         {
1446         case RENDERPATH_GL11:
1447         case RENDERPATH_GL13:
1448         case RENDERPATH_GL20:
1449         case RENDERPATH_GLES1:
1450         case RENDERPATH_GLES2:
1451                 if (gl_state.framebufferobject != fbo)
1452                 {
1453                         gl_state.framebufferobject = fbo;
1454                         qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1455                 }
1456                 break;
1457         case RENDERPATH_D3D9:
1458 #ifdef SUPPORTD3D
1459                 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1460                 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1461                 if (fbo)
1462                 {
1463                         IDirect3DSurface9 *surfaces[5];
1464                         for (i = 0;i < 5;i++)
1465                         {
1466                                 surfaces[i] = NULL;
1467                                 if (textures[i])
1468                                 {
1469                                         if (textures[i]->d3dsurface)
1470                                                 surfaces[i] = (IDirect3DSurface9 *)textures[i]->d3dsurface;
1471                                         else
1472                                                 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &surfaces[i]);
1473                                 }
1474                         }
1475                         // set the render targets for real
1476                         R_Mesh_SetRenderTargetsD3D9(surfaces[4], surfaces[0], surfaces[1], surfaces[2], surfaces[3]);
1477                         // release the texture surface levels (they won't be lost while bound...)
1478                         for (i = 0;i < 5;i++)
1479                                 if (textures[i] && !textures[i]->d3dsurface)
1480                                         IDirect3DSurface9_Release(surfaces[i]);
1481                 }
1482                 else
1483                         R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1484 #endif
1485                 break;
1486         case RENDERPATH_D3D10:
1487                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1488                 break;
1489         case RENDERPATH_D3D11:
1490                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1491                 break;
1492         case RENDERPATH_SOFT:
1493                 if (fbo)
1494                 {
1495                         int width, height;
1496                         unsigned int *pointers[5];
1497                         memset(pointers, 0, sizeof(pointers));
1498                         for (i = 0;i < 5;i++)
1499                                 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1500                         width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1501                         height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1502                         DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1503                 }
1504                 else
1505                         DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1506                 break;
1507         }
1508 }
1509
1510 #ifdef SUPPORTD3D
1511 static int d3dcmpforglfunc(int f)
1512 {
1513         switch(f)
1514         {
1515         case GL_NEVER: return D3DCMP_NEVER;
1516         case GL_LESS: return D3DCMP_LESS;
1517         case GL_EQUAL: return D3DCMP_EQUAL;
1518         case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1519         case GL_GREATER: return D3DCMP_GREATER;
1520         case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1521         case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1522         case GL_ALWAYS: return D3DCMP_ALWAYS;
1523         default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1524         }
1525 }
1526
1527 static int d3dstencilopforglfunc(int f)
1528 {
1529         switch(f)
1530         {
1531         case GL_KEEP: return D3DSTENCILOP_KEEP;
1532         case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1533         case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1534         default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1535         }
1536 }
1537 #endif
1538
1539 static void GL_Backend_ResetState(void)
1540 {
1541         unsigned int i;
1542         gl_state.active = true;
1543         gl_state.depthtest = true;
1544         gl_state.alphatest = false;
1545         gl_state.alphafunc = GL_GEQUAL;
1546         gl_state.alphafuncvalue = 0.5f;
1547         gl_state.alphatocoverage = false;
1548         gl_state.blendfunc1 = GL_ONE;
1549         gl_state.blendfunc2 = GL_ZERO;
1550         gl_state.blend = false;
1551         gl_state.depthmask = GL_TRUE;
1552         gl_state.colormask = 15;
1553         gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1554         gl_state.lockrange_first = 0;
1555         gl_state.lockrange_count = 0;
1556         gl_state.cullface = GL_FRONT;
1557         gl_state.cullfaceenable = false;
1558         gl_state.polygonoffset[0] = 0;
1559         gl_state.polygonoffset[1] = 0;
1560         gl_state.framebufferobject = 0;
1561         gl_state.depthfunc = GL_LEQUAL;
1562
1563         switch(vid.renderpath)
1564         {
1565         case RENDERPATH_D3D9:
1566 #ifdef SUPPORTD3D
1567                 {
1568                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1569                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1570                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1571                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1572                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1573                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1574                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1575                 }
1576 #endif
1577                 break;
1578         case RENDERPATH_D3D10:
1579                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1580                 break;
1581         case RENDERPATH_D3D11:
1582                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1583                 break;
1584         case RENDERPATH_GL11:
1585         case RENDERPATH_GL13:
1586         case RENDERPATH_GLES1:
1587 #ifdef GL_ALPHA_TEST
1588                 CHECKGLERROR
1589
1590                 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1591                 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1592                 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1593                 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1594                 qglDisable(GL_BLEND);CHECKGLERROR
1595                 qglCullFace(gl_state.cullface);CHECKGLERROR
1596                 qglDisable(GL_CULL_FACE);CHECKGLERROR
1597                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1598                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1599                 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1600                 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1601
1602                 if (vid.support.arb_vertex_buffer_object)
1603                 {
1604                         qglBindBufferARB(GL_ARRAY_BUFFER, 0);
1605                         qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
1606                 }
1607
1608                 if (vid.support.ext_framebuffer_object)
1609                 {
1610                         //qglBindRenderbuffer(GL_RENDERBUFFER, 0);
1611                         qglBindFramebuffer(GL_FRAMEBUFFER, 0);
1612                 }
1613
1614                 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1615                 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1616
1617                 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1618                 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1619                 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1620
1621                 if (vid.support.ext_framebuffer_object)
1622                         qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject);
1623
1624                 gl_state.unit = MAX_TEXTUREUNITS;
1625                 gl_state.clientunit = MAX_TEXTUREUNITS;
1626                 for (i = 0;i < vid.texunits;i++)
1627                 {
1628                         GL_ActiveTexture(i);
1629                         GL_ClientActiveTexture(i);
1630                         qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1631                         qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1632                         if (vid.support.ext_texture_3d)
1633                         {
1634                                 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1635                                 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1636                         }
1637                         if (vid.support.arb_texture_cube_map)
1638                         {
1639                                 qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR
1640                                 qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
1641                         }
1642                         GL_BindVBO(0);
1643                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1644                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1645                         qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1646                         qglLoadIdentity();CHECKGLERROR
1647                         qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1648                         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1649                 }
1650                 CHECKGLERROR
1651 #endif
1652                 break;
1653         case RENDERPATH_SOFT:
1654                 DPSOFTRAST_ColorMask(1,1,1,1);
1655                 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1656                 DPSOFTRAST_CullFace(gl_state.cullface);
1657                 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1658                 DPSOFTRAST_DepthMask(gl_state.depthmask);
1659                 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1660                 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1661                 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1662                 break;
1663         case RENDERPATH_GL20:
1664         case RENDERPATH_GLES2:
1665                 CHECKGLERROR
1666                 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1667                 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1668                 qglDisable(GL_BLEND);CHECKGLERROR
1669                 qglCullFace(gl_state.cullface);CHECKGLERROR
1670                 qglDisable(GL_CULL_FACE);CHECKGLERROR
1671                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1672                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1673                 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1674                 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1675                 if (vid.support.arb_vertex_buffer_object)
1676                 {
1677                         qglBindBufferARB(GL_ARRAY_BUFFER, 0);
1678                         qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
1679                 }
1680                 if (vid.support.ext_framebuffer_object)
1681                         qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.defaultframebufferobject);
1682                 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1683                 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1684                 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1685                 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1686                 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1687                 gl_state.unit = MAX_TEXTUREUNITS;
1688                 gl_state.clientunit = MAX_TEXTUREUNITS;
1689                 for (i = 0;i < vid.teximageunits;i++)
1690                 {
1691                         GL_ActiveTexture(i);
1692                         qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1693                         if (vid.support.ext_texture_3d)
1694                         {
1695                                 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1696                         }
1697                         if (vid.support.arb_texture_cube_map)
1698                         {
1699                                 qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
1700                         }
1701                 }
1702                 for (i = 0;i < vid.texarrayunits;i++)
1703                 {
1704                         GL_BindVBO(0);
1705                         qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1706                         qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1707                 }
1708                 CHECKGLERROR
1709                 break;
1710         }
1711 }
1712
1713 void GL_ActiveTexture(unsigned int num)
1714 {
1715         if (gl_state.unit != num)
1716         {
1717                 gl_state.unit = num;
1718                 switch(vid.renderpath)
1719                 {
1720                 case RENDERPATH_GL11:
1721                 case RENDERPATH_GL13:
1722                 case RENDERPATH_GL20:
1723                 case RENDERPATH_GLES1:
1724                 case RENDERPATH_GLES2:
1725                         if (qglActiveTexture)
1726                         {
1727                                 CHECKGLERROR
1728                                 qglActiveTexture(GL_TEXTURE0 + gl_state.unit);
1729                                 CHECKGLERROR
1730                         }
1731                         break;
1732                 case RENDERPATH_D3D9:
1733                 case RENDERPATH_D3D10:
1734                 case RENDERPATH_D3D11:
1735                         break;
1736                 case RENDERPATH_SOFT:
1737                         break;
1738                 }
1739         }
1740 }
1741
1742 void GL_ClientActiveTexture(unsigned int num)
1743 {
1744         if (gl_state.clientunit != num)
1745         {
1746                 gl_state.clientunit = num;
1747                 switch(vid.renderpath)
1748                 {
1749                 case RENDERPATH_GL11:
1750                 case RENDERPATH_GL13:
1751                 case RENDERPATH_GLES1:
1752                         if (qglActiveTexture)
1753                         {
1754                                 CHECKGLERROR
1755                                 qglClientActiveTexture(GL_TEXTURE0 + gl_state.clientunit);
1756                                 CHECKGLERROR
1757                         }
1758                         break;
1759                 case RENDERPATH_D3D9:
1760                 case RENDERPATH_D3D10:
1761                 case RENDERPATH_D3D11:
1762                         break;
1763                 case RENDERPATH_SOFT:
1764                         break;
1765                 case RENDERPATH_GL20:
1766                 case RENDERPATH_GLES2:
1767                         break;
1768                 }
1769         }
1770 }
1771
1772 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1773 {
1774         if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1775         {
1776                 qboolean blendenable;
1777                 gl_state.blendfunc1 = blendfunc1;
1778                 gl_state.blendfunc2 = blendfunc2;
1779                 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1780                 switch(vid.renderpath)
1781                 {
1782                 case RENDERPATH_GL11:
1783                 case RENDERPATH_GL13:
1784                 case RENDERPATH_GL20:
1785                 case RENDERPATH_GLES1:
1786                 case RENDERPATH_GLES2:
1787                         CHECKGLERROR
1788                         qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1789                         if (gl_state.blend != blendenable)
1790                         {
1791                                 gl_state.blend = blendenable;
1792                                 if (!gl_state.blend)
1793                                 {
1794                                         qglDisable(GL_BLEND);CHECKGLERROR
1795                                 }
1796                                 else
1797                                 {
1798                                         qglEnable(GL_BLEND);CHECKGLERROR
1799                                 }
1800                         }
1801                         break;
1802                 case RENDERPATH_D3D9:
1803 #ifdef SUPPORTD3D
1804                         {
1805                                 int i;
1806                                 int glblendfunc[2];
1807                                 D3DBLEND d3dblendfunc[2];
1808                                 glblendfunc[0] = gl_state.blendfunc1;
1809                                 glblendfunc[1] = gl_state.blendfunc2;
1810                                 for (i = 0;i < 2;i++)
1811                                 {
1812                                         switch(glblendfunc[i])
1813                                         {
1814                                         case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1815                                         case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1816                                         case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1817                                         case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1818                                         case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1819                                         case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1820                                         case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1821                                         case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1822                                         case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1823                                         case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1824                                         }
1825                                 }
1826                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1827                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1828                                 if (gl_state.blend != blendenable)
1829                                 {
1830                                         gl_state.blend = blendenable;
1831                                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1832                                 }
1833                         }
1834 #endif
1835                         break;
1836                 case RENDERPATH_D3D10:
1837                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838                         break;
1839                 case RENDERPATH_D3D11:
1840                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1841                         break;
1842                 case RENDERPATH_SOFT:
1843                         DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1844                         break;
1845                 }
1846         }
1847 }
1848
1849 void GL_DepthMask(int state)
1850 {
1851         if (gl_state.depthmask != state)
1852         {
1853                 gl_state.depthmask = state;
1854                 switch(vid.renderpath)
1855                 {
1856                 case RENDERPATH_GL11:
1857                 case RENDERPATH_GL13:
1858                 case RENDERPATH_GL20:
1859                 case RENDERPATH_GLES1:
1860                 case RENDERPATH_GLES2:
1861                         CHECKGLERROR
1862                         qglDepthMask(gl_state.depthmask);CHECKGLERROR
1863                         break;
1864                 case RENDERPATH_D3D9:
1865 #ifdef SUPPORTD3D
1866                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1867 #endif
1868                         break;
1869                 case RENDERPATH_D3D10:
1870                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1871                         break;
1872                 case RENDERPATH_D3D11:
1873                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1874                         break;
1875                 case RENDERPATH_SOFT:
1876                         DPSOFTRAST_DepthMask(gl_state.depthmask);
1877                         break;
1878                 }
1879         }
1880 }
1881
1882 void GL_DepthTest(int state)
1883 {
1884         if (gl_state.depthtest != state)
1885         {
1886                 gl_state.depthtest = state;
1887                 switch(vid.renderpath)
1888                 {
1889                 case RENDERPATH_GL11:
1890                 case RENDERPATH_GL13:
1891                 case RENDERPATH_GL20:
1892                 case RENDERPATH_GLES1:
1893                 case RENDERPATH_GLES2:
1894                         CHECKGLERROR
1895                         if (gl_state.depthtest)
1896                         {
1897                                 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1898                         }
1899                         else
1900                         {
1901                                 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1902                         }
1903                         break;
1904                 case RENDERPATH_D3D9:
1905 #ifdef SUPPORTD3D
1906                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1907 #endif
1908                         break;
1909                 case RENDERPATH_D3D10:
1910                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1911                         break;
1912                 case RENDERPATH_D3D11:
1913                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1914                         break;
1915                 case RENDERPATH_SOFT:
1916                         DPSOFTRAST_DepthTest(gl_state.depthtest);
1917                         break;
1918                 }
1919         }
1920 }
1921
1922 void GL_DepthFunc(int state)
1923 {
1924         if (gl_state.depthfunc != state)
1925         {
1926                 gl_state.depthfunc = state;
1927                 switch(vid.renderpath)
1928                 {
1929                 case RENDERPATH_GL11:
1930                 case RENDERPATH_GL13:
1931                 case RENDERPATH_GL20:
1932                 case RENDERPATH_GLES1:
1933                 case RENDERPATH_GLES2:
1934                         CHECKGLERROR
1935                         qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1936                         break;
1937                 case RENDERPATH_D3D9:
1938 #ifdef SUPPORTD3D
1939                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1940 #endif
1941                         break;
1942                 case RENDERPATH_D3D10:
1943                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944                         break;
1945                 case RENDERPATH_D3D11:
1946                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1947                         break;
1948                 case RENDERPATH_SOFT:
1949                         DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1950                         break;
1951                 }
1952         }
1953 }
1954
1955 void GL_DepthRange(float nearfrac, float farfrac)
1956 {
1957         if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1958         {
1959                 gl_state.depthrange[0] = nearfrac;
1960                 gl_state.depthrange[1] = farfrac;
1961                 switch(vid.renderpath)
1962                 {
1963                 case RENDERPATH_GL11:
1964                 case RENDERPATH_GL13:
1965                 case RENDERPATH_GL20:
1966                 case RENDERPATH_GLES1:
1967                 case RENDERPATH_GLES2:
1968 #ifdef USE_GLES2
1969                         qglDepthRangef(gl_state.depthrange[0], gl_state.depthrange[1]);
1970 #else
1971                         qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1972 #endif
1973                         break;
1974                 case RENDERPATH_D3D9:
1975 #ifdef SUPPORTD3D
1976                         {
1977                                 D3DVIEWPORT9 d3dviewport;
1978                                 d3dviewport.X = gl_viewport.x;
1979                                 d3dviewport.Y = gl_viewport.y;
1980                                 d3dviewport.Width = gl_viewport.width;
1981                                 d3dviewport.Height = gl_viewport.height;
1982                                 d3dviewport.MinZ = gl_state.depthrange[0];
1983                                 d3dviewport.MaxZ = gl_state.depthrange[1];
1984                                 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1985                         }
1986 #endif
1987                         break;
1988                 case RENDERPATH_D3D10:
1989                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990                         break;
1991                 case RENDERPATH_D3D11:
1992                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993                         break;
1994                 case RENDERPATH_SOFT:
1995                         DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1996                         break;
1997                 }
1998         }
1999 }
2000
2001 void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int frontzfail, int frontzpass, int backfail, int backzfail, int backzpass, int frontcompare, int backcompare, int comparereference, int comparemask)
2002 {
2003         switch (vid.renderpath)
2004         {
2005         case RENDERPATH_GL11:
2006         case RENDERPATH_GL13:
2007         case RENDERPATH_GL20:
2008         case RENDERPATH_GLES1:
2009         case RENDERPATH_GLES2:
2010                 CHECKGLERROR
2011                 if (enable)
2012                 {
2013                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2014                 }
2015                 else
2016                 {
2017                         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2018                 }
2019                 if (vid.support.ati_separate_stencil)
2020                 {
2021                         qglStencilMask(writemask);CHECKGLERROR
2022                         qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
2023                         qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
2024                         qglStencilFuncSeparate(GL_FRONT, frontcompare, comparereference, comparereference);CHECKGLERROR
2025                         qglStencilFuncSeparate(GL_BACK, backcompare, comparereference, comparereference);CHECKGLERROR
2026                 }
2027                 else if (vid.support.ext_stencil_two_side)
2028                 {
2029 #ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
2030                         qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
2031                         qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
2032                         qglStencilMask(writemask);CHECKGLERROR
2033                         qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
2034                         qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
2035                         qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
2036                         qglStencilMask(writemask);CHECKGLERROR
2037                         qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
2038                         qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
2039 #endif
2040                 }
2041                 break;
2042         case RENDERPATH_D3D9:
2043 #ifdef SUPPORTD3D
2044                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
2045                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
2046                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
2047                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
2048                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
2049                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
2050                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
2051                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
2052                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
2053                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
2054                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
2055                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
2056                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
2057 #endif
2058                 break;
2059         case RENDERPATH_D3D10:
2060                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2061                 break;
2062         case RENDERPATH_D3D11:
2063                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2064                 break;
2065         case RENDERPATH_SOFT:
2066                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2067                 break;
2068         }
2069 }
2070
2071 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
2072 {
2073         switch (vid.renderpath)
2074         {
2075         case RENDERPATH_GL11:
2076         case RENDERPATH_GL13:
2077         case RENDERPATH_GL20:
2078         case RENDERPATH_GLES1:
2079         case RENDERPATH_GLES2:
2080                 CHECKGLERROR
2081                 if (enable)
2082                 {
2083                         qglEnable(GL_STENCIL_TEST);CHECKGLERROR
2084                 }
2085                 else
2086                 {
2087                         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2088                 }
2089                 if (vid.support.ext_stencil_two_side)
2090                 {
2091 #ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
2092                         qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
2093 #endif
2094                 }
2095                 qglStencilMask(writemask);CHECKGLERROR
2096                 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
2097                 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
2098                 CHECKGLERROR
2099                 break;
2100         case RENDERPATH_D3D9:
2101 #ifdef SUPPORTD3D
2102                 if (vid.support.ati_separate_stencil)
2103                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
2104                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
2105                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
2106                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
2107                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
2108                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
2109                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
2110                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
2111                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
2112 #endif
2113                 break;
2114         case RENDERPATH_D3D10:
2115                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2116                 break;
2117         case RENDERPATH_D3D11:
2118                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2119                 break;
2120         case RENDERPATH_SOFT:
2121                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2122                 break;
2123         }
2124 }
2125
2126 void GL_PolygonOffset(float planeoffset, float depthoffset)
2127 {
2128         if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
2129         {
2130                 gl_state.polygonoffset[0] = planeoffset;
2131                 gl_state.polygonoffset[1] = depthoffset;
2132                 switch(vid.renderpath)
2133                 {
2134                 case RENDERPATH_GL11:
2135                 case RENDERPATH_GL13:
2136                 case RENDERPATH_GL20:
2137                 case RENDERPATH_GLES1:
2138                 case RENDERPATH_GLES2:
2139                         qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2140                         break;
2141                 case RENDERPATH_D3D9:
2142 #ifdef SUPPORTD3D
2143                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
2144                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
2145 #endif
2146                         break;
2147                 case RENDERPATH_D3D10:
2148                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2149                         break;
2150                 case RENDERPATH_D3D11:
2151                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2152                         break;
2153                 case RENDERPATH_SOFT:
2154                         DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2155                         break;
2156                 }
2157         }
2158 }
2159
2160 void GL_SetMirrorState(qboolean state)
2161 {
2162         if (v_flipped_state != state)
2163         {
2164                 v_flipped_state = state;
2165                 if (gl_state.cullface == GL_BACK)
2166                         gl_state.cullface = GL_FRONT;
2167                 else if (gl_state.cullface == GL_FRONT)
2168                         gl_state.cullface = GL_BACK;
2169                 else
2170                         return;
2171                 switch(vid.renderpath)
2172                 {
2173                 case RENDERPATH_GL11:
2174                 case RENDERPATH_GL13:
2175                 case RENDERPATH_GL20:
2176                 case RENDERPATH_GLES1:
2177                 case RENDERPATH_GLES2:
2178                         qglCullFace(gl_state.cullface);CHECKGLERROR
2179                         break;
2180                 case RENDERPATH_D3D9:
2181 #ifdef SUPPORTD3D
2182                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2183 #endif
2184                         break;
2185                 case RENDERPATH_D3D10:
2186                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2187                         break;
2188                 case RENDERPATH_D3D11:
2189                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2190                         break;
2191                 case RENDERPATH_SOFT:
2192                         DPSOFTRAST_CullFace(gl_state.cullface);
2193                         break;
2194                 }
2195         }
2196 }
2197
2198 void GL_CullFace(int state)
2199 {
2200         if(v_flipped_state)
2201         {
2202                 if(state == GL_FRONT)
2203                         state = GL_BACK;
2204                 else if(state == GL_BACK)
2205                         state = GL_FRONT;
2206         }
2207
2208         switch(vid.renderpath)
2209         {
2210         case RENDERPATH_GL11:
2211         case RENDERPATH_GL13:
2212         case RENDERPATH_GL20:
2213         case RENDERPATH_GLES1:
2214         case RENDERPATH_GLES2:
2215                 CHECKGLERROR
2216
2217                 if (state != GL_NONE)
2218                 {
2219                         if (!gl_state.cullfaceenable)
2220                         {
2221                                 gl_state.cullfaceenable = true;
2222                                 qglEnable(GL_CULL_FACE);CHECKGLERROR
2223                         }
2224                         if (gl_state.cullface != state)
2225                         {
2226                                 gl_state.cullface = state;
2227                                 qglCullFace(gl_state.cullface);CHECKGLERROR
2228                         }
2229                 }
2230                 else
2231                 {
2232                         if (gl_state.cullfaceenable)
2233                         {
2234                                 gl_state.cullfaceenable = false;
2235                                 qglDisable(GL_CULL_FACE);CHECKGLERROR
2236                         }
2237                 }
2238                 break;
2239         case RENDERPATH_D3D9:
2240 #ifdef SUPPORTD3D
2241                 if (gl_state.cullface != state)
2242                 {
2243                         gl_state.cullface = state;
2244                         switch(gl_state.cullface)
2245                         {
2246                         case GL_NONE:
2247                                 gl_state.cullfaceenable = false;
2248                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2249                                 break;
2250                         case GL_FRONT:
2251                                 gl_state.cullfaceenable = true;
2252                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2253                                 break;
2254                         case GL_BACK:
2255                                 gl_state.cullfaceenable = true;
2256                                 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2257                                 break;
2258                         }
2259                 }
2260 #endif
2261                 break;
2262         case RENDERPATH_D3D10:
2263                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2264                 break;
2265         case RENDERPATH_D3D11:
2266                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2267                 break;
2268         case RENDERPATH_SOFT:
2269                 if (gl_state.cullface != state)
2270                 {
2271                         gl_state.cullface = state;
2272                         gl_state.cullfaceenable = state != GL_NONE ? true : false;
2273                         DPSOFTRAST_CullFace(gl_state.cullface);
2274                 }
2275                 break;
2276         }
2277 }
2278
2279 void GL_AlphaTest(int state)
2280 {
2281         if (gl_state.alphatest != state)
2282         {
2283                 gl_state.alphatest = state;
2284                 switch(vid.renderpath)
2285                 {
2286                 case RENDERPATH_GL11:
2287                 case RENDERPATH_GL13:
2288                 case RENDERPATH_GLES1:
2289 #ifdef GL_ALPHA_TEST
2290                         // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2291                         CHECKGLERROR
2292                         if (gl_state.alphatest)
2293                         {
2294                                 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2295                         }
2296                         else
2297                         {
2298                                 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2299                         }
2300 #endif
2301                         break;
2302                 case RENDERPATH_D3D9:
2303                 case RENDERPATH_D3D10:
2304                 case RENDERPATH_D3D11:
2305                 case RENDERPATH_SOFT:
2306                 case RENDERPATH_GL20:
2307                 case RENDERPATH_GLES2:
2308                         break;
2309                 }
2310         }
2311 }
2312
2313 void GL_AlphaToCoverage(qboolean state)
2314 {
2315         if (gl_state.alphatocoverage != state)
2316         {
2317                 gl_state.alphatocoverage = state;
2318                 switch(vid.renderpath)
2319                 {
2320                 case RENDERPATH_GL11:
2321                 case RENDERPATH_GL13:
2322                 case RENDERPATH_GLES1:
2323                 case RENDERPATH_GLES2:
2324                 case RENDERPATH_D3D9:
2325                 case RENDERPATH_D3D10:
2326                 case RENDERPATH_D3D11:
2327                 case RENDERPATH_SOFT:
2328                         break;
2329                 case RENDERPATH_GL20:
2330 #ifdef GL_SAMPLE_ALPHA_TO_COVERAGE_ARB
2331                         // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
2332                         CHECKGLERROR
2333                         if (gl_state.alphatocoverage)
2334                         {
2335                                 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2336 //                              qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2337                         }
2338                         else
2339                         {
2340                                 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2341 //                              qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2342                         }
2343 #endif
2344                         break;
2345                 }
2346         }
2347 }
2348
2349 void GL_ColorMask(int r, int g, int b, int a)
2350 {
2351         // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2352         int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2353         if (gl_state.colormask != state)
2354         {
2355                 gl_state.colormask = state;
2356                 switch(vid.renderpath)
2357                 {
2358                 case RENDERPATH_GL11:
2359                 case RENDERPATH_GL13:
2360                 case RENDERPATH_GL20:
2361                 case RENDERPATH_GLES1:
2362                 case RENDERPATH_GLES2:
2363                         CHECKGLERROR
2364                         qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2365                         break;
2366                 case RENDERPATH_D3D9:
2367 #ifdef SUPPORTD3D
2368                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2369 #endif
2370                         break;
2371                 case RENDERPATH_D3D10:
2372                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2373                         break;
2374                 case RENDERPATH_D3D11:
2375                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2376                         break;
2377                 case RENDERPATH_SOFT:
2378                         DPSOFTRAST_ColorMask(r, g, b, a);
2379                         break;
2380                 }
2381         }
2382 }
2383
2384 void GL_Color(float cr, float cg, float cb, float ca)
2385 {
2386         if (gl_state.pointer_color_enabled || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
2387         {
2388                 gl_state.color4f[0] = cr;
2389                 gl_state.color4f[1] = cg;
2390                 gl_state.color4f[2] = cb;
2391                 gl_state.color4f[3] = ca;
2392                 switch(vid.renderpath)
2393                 {
2394                 case RENDERPATH_GL11:
2395                 case RENDERPATH_GL13:
2396                 case RENDERPATH_GLES1:
2397                         CHECKGLERROR
2398                         qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2399                         CHECKGLERROR
2400                         break;
2401                 case RENDERPATH_D3D9:
2402                 case RENDERPATH_D3D10:
2403                 case RENDERPATH_D3D11:
2404                         // no equivalent in D3D
2405                         break;
2406                 case RENDERPATH_SOFT:
2407                         DPSOFTRAST_Color4f(cr, cg, cb, ca);
2408                         break;
2409                 case RENDERPATH_GL20:
2410                 case RENDERPATH_GLES2:
2411                         qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2412                         break;
2413                 }
2414         }
2415 }
2416
2417 void GL_Scissor (int x, int y, int width, int height)
2418 {
2419         switch(vid.renderpath)
2420         {
2421         case RENDERPATH_GL11:
2422         case RENDERPATH_GL13:
2423         case RENDERPATH_GL20:
2424         case RENDERPATH_GLES1:
2425         case RENDERPATH_GLES2:
2426                 CHECKGLERROR
2427                 qglScissor(x, y,width,height);
2428                 CHECKGLERROR
2429                 break;
2430         case RENDERPATH_D3D9:
2431 #ifdef SUPPORTD3D
2432                 {
2433                         RECT d3drect;
2434                         d3drect.left = x;
2435                         d3drect.top = y;
2436                         d3drect.right = x + width;
2437                         d3drect.bottom = y + height;
2438                         IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2439                 }
2440 #endif
2441                 break;
2442         case RENDERPATH_D3D10:
2443                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2444                 break;
2445         case RENDERPATH_D3D11:
2446                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2447                 break;
2448         case RENDERPATH_SOFT:
2449                 DPSOFTRAST_Scissor(x, y, width, height);
2450                 break;
2451         }
2452 }
2453
2454 void GL_ScissorTest(int state)
2455 {
2456         if (gl_state.scissortest != state)
2457         {
2458                 gl_state.scissortest = state;
2459                 switch(vid.renderpath)
2460                 {
2461                 case RENDERPATH_GL11:
2462                 case RENDERPATH_GL13:
2463                 case RENDERPATH_GL20:
2464                 case RENDERPATH_GLES1:
2465                 case RENDERPATH_GLES2:
2466                         CHECKGLERROR
2467                         if(gl_state.scissortest)
2468                                 qglEnable(GL_SCISSOR_TEST);
2469                         else
2470                                 qglDisable(GL_SCISSOR_TEST);
2471                         CHECKGLERROR
2472                         break;
2473                 case RENDERPATH_D3D9:
2474 #ifdef SUPPORTD3D
2475                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2476 #endif
2477                         break;
2478                 case RENDERPATH_D3D10:
2479                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2480                         break;
2481                 case RENDERPATH_D3D11:
2482                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2483                         break;
2484                 case RENDERPATH_SOFT:
2485                         DPSOFTRAST_ScissorTest(gl_state.scissortest);
2486                         break;
2487                 }
2488         }
2489 }
2490
2491 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2492 {
2493         static const float blackcolor[4] = {0, 0, 0, 0};
2494         // prevent warnings when trying to clear a buffer that does not exist
2495         if (!colorvalue)
2496                 colorvalue = blackcolor;
2497         if (!vid.stencil)
2498         {
2499                 mask &= ~GL_STENCIL_BUFFER_BIT;
2500                 stencilvalue = 0;
2501         }
2502         switch(vid.renderpath)
2503         {
2504         case RENDERPATH_GL11:
2505         case RENDERPATH_GL13:
2506         case RENDERPATH_GL20:
2507         case RENDERPATH_GLES1:
2508         case RENDERPATH_GLES2:
2509                 CHECKGLERROR
2510                 if (mask & GL_COLOR_BUFFER_BIT)
2511                 {
2512                         qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2513                 }
2514                 if (mask & GL_DEPTH_BUFFER_BIT)
2515                 {
2516 #ifdef USE_GLES2
2517                         qglClearDepthf(depthvalue);CHECKGLERROR
2518 #else
2519                         qglClearDepth(depthvalue);CHECKGLERROR
2520 #endif
2521                 }
2522                 if (mask & GL_STENCIL_BUFFER_BIT)
2523                 {
2524                         qglClearStencil(stencilvalue);CHECKGLERROR
2525                 }
2526                 qglClear(mask);CHECKGLERROR
2527                 break;
2528         case RENDERPATH_D3D9:
2529 #ifdef SUPPORTD3D
2530                 IDirect3DDevice9_Clear(vid_d3d9dev, 0, NULL, ((mask & GL_COLOR_BUFFER_BIT) ? D3DCLEAR_TARGET : 0) | ((mask & GL_STENCIL_BUFFER_BIT) ? D3DCLEAR_STENCIL : 0) | ((mask & GL_DEPTH_BUFFER_BIT) ? D3DCLEAR_ZBUFFER : 0), D3DCOLOR_COLORVALUE(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]), depthvalue, stencilvalue);
2531 #endif
2532                 break;
2533         case RENDERPATH_D3D10:
2534                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2535                 break;
2536         case RENDERPATH_D3D11:
2537                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2538                 break;
2539         case RENDERPATH_SOFT:
2540                 if (mask & GL_COLOR_BUFFER_BIT)
2541                         DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2542                 if (mask & GL_DEPTH_BUFFER_BIT)
2543                         DPSOFTRAST_ClearDepth(depthvalue);
2544                 break;
2545         }
2546 }
2547
2548 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2549 {
2550         switch(vid.renderpath)
2551         {
2552         case RENDERPATH_GL11:
2553         case RENDERPATH_GL13:
2554         case RENDERPATH_GL20:
2555         case RENDERPATH_GLES1:
2556         case RENDERPATH_GLES2:
2557                 CHECKGLERROR
2558                 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2559                 break;
2560         case RENDERPATH_D3D9:
2561 #ifdef SUPPORTD3D
2562                 {
2563                         // LordHavoc: we can't directly download the backbuffer because it may be
2564                         // multisampled, and it may not be lockable, so we blit it to a lockable
2565                         // surface of the same dimensions (but without multisample) to resolve the
2566                         // multisample buffer to a normal image, and then lock that...
2567                         IDirect3DSurface9 *stretchsurface = NULL;
2568                         if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2569                         {
2570                                 D3DLOCKED_RECT lockedrect;
2571                                 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2572                                 {
2573                                         if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2574                                         {
2575                                                 int line;
2576                                                 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2577                                                 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2578                                                         memcpy(outpixels + line * width * 4, row, width * 4);
2579                                                 IDirect3DSurface9_UnlockRect(stretchsurface);
2580                                         }
2581                                 }
2582                                 IDirect3DSurface9_Release(stretchsurface);
2583                         }
2584                         // code scraps
2585                         //IDirect3DSurface9 *syssurface = NULL;
2586                         //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2587                         //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2588                         //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2589                         //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2590                         //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2591                         //IDirect3DSurface9_UnlockRect(syssurface);
2592                         //IDirect3DSurface9_Release(syssurface);
2593                 }
2594 #endif
2595                 break;
2596         case RENDERPATH_D3D10:
2597                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2598                 break;
2599         case RENDERPATH_D3D11:
2600                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2601                 break;
2602         case RENDERPATH_SOFT:
2603                 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2604                 break;
2605         }
2606 }
2607
2608 // called at beginning of frame
2609 void R_Mesh_Start(void)
2610 {
2611         BACKENDACTIVECHECK
2612         R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
2613         R_Mesh_SetUseVBO();
2614         if (gl_printcheckerror.integer && !gl_paranoid.integer)
2615         {
2616                 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2617                 Cvar_SetValueQuick(&gl_paranoid, 1);
2618         }
2619 }
2620
2621 static qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2622 {
2623         int shaderobject;
2624         int shadercompiled;
2625         char compilelog[MAX_INPUTLINE];
2626         shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2627         if (!shaderobject)
2628                 return false;
2629         qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2630         qglCompileShader(shaderobject);CHECKGLERROR
2631         qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2632         qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2633         if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning") || developer_extra.integer))
2634         {
2635                 int i, j, pretextlines = 0;
2636                 for (i = 0;i < numstrings - 1;i++)
2637                         for (j = 0;strings[i][j];j++)
2638                                 if (strings[i][j] == '\n')
2639                                         pretextlines++;
2640                 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2641         }
2642         if (!shadercompiled)
2643         {
2644                 qglDeleteShader(shaderobject);CHECKGLERROR
2645                 return false;
2646         }
2647         qglAttachShader(programobject, shaderobject);CHECKGLERROR
2648         qglDeleteShader(shaderobject);CHECKGLERROR
2649         return true;
2650 }
2651
2652 unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int geometrystrings_count, const char **geometrystrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
2653 {
2654         GLint programlinked;
2655         GLuint programobject = 0;
2656         char linklog[MAX_INPUTLINE];
2657         CHECKGLERROR
2658
2659         programobject = qglCreateProgram();CHECKGLERROR
2660         if (!programobject)
2661                 return 0;
2662
2663         qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2664         qglBindAttribLocation(programobject, GLSLATTRIB_COLOR    , "Attrib_Color"    );
2665         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2666         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2667         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2668         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2669         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2670         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2671         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2672         qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2673 #ifndef USE_GLES2
2674         if(vid.support.gl20shaders130)
2675                 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2676 #endif
2677
2678         if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2679                 goto cleanup;
2680
2681 #ifdef GL_GEOMETRY_SHADER
2682         if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2683                 goto cleanup;
2684 #endif
2685
2686         if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2687                 goto cleanup;
2688
2689         qglLinkProgram(programobject);CHECKGLERROR
2690         qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2691         qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2692         if (linklog[0])
2693         {
2694                 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer)
2695                         Con_DPrintf("program link log:\n%s\n", linklog);
2696                 // software vertex shader is ok but software fragment shader is WAY
2697                 // too slow, fail program if so.
2698                 // NOTE: this string might be ATI specific, but that's ok because the
2699                 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2700                 // software fragment shader due to low instruction and dependent
2701                 // texture limits.
2702                 if (strstr(linklog, "fragment shader will run in software"))
2703                         programlinked = false;
2704         }
2705         if (!programlinked)
2706                 goto cleanup;
2707         return programobject;
2708 cleanup:
2709         qglDeleteProgram(programobject);CHECKGLERROR
2710         return 0;
2711 }
2712
2713 void GL_Backend_FreeProgram(unsigned int prog)
2714 {
2715         CHECKGLERROR
2716         qglDeleteProgram(prog);
2717         CHECKGLERROR
2718 }
2719
2720 // renders triangles using vertices from the active arrays
2721 int paranoidblah = 0;
2722 void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset)
2723 {
2724         unsigned int numelements = numtriangles * 3;
2725         int bufferobject3i;
2726         size_t bufferoffset3i;
2727         int bufferobject3s;
2728         size_t bufferoffset3s;
2729         if (numvertices < 3 || numtriangles < 1)
2730         {
2731                 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2732                         Con_DPrintf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %8x, %8p, %8p, %8x);\n", firstvertex, numvertices, firsttriangle, numtriangles, (void *)element3i, (void *)element3i_indexbuffer, (int)element3i_bufferoffset, (void *)element3s, (void *)element3s_indexbuffer, (int)element3s_bufferoffset);
2733                 return;
2734         }
2735         if (!gl_mesh_prefer_short_elements.integer)
2736         {
2737                 if (element3i)
2738                         element3s = NULL;
2739                 if (element3i_indexbuffer)
2740                         element3i_indexbuffer = NULL;
2741         }
2742         // adjust the pointers for firsttriangle
2743         if (element3i)
2744                 element3i += firsttriangle * 3;
2745         if (element3i_indexbuffer)
2746                 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2747         if (element3s)
2748                 element3s += firsttriangle * 3;
2749         if (element3s_indexbuffer)
2750                 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2751         switch(vid.renderpath)
2752         {
2753         case RENDERPATH_GL11:
2754         case RENDERPATH_GL13:
2755         case RENDERPATH_GL20:
2756         case RENDERPATH_GLES1:
2757         case RENDERPATH_GLES2:
2758                 // check if the user specified to ignore static index buffers
2759                 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2760                 {
2761                         element3i_indexbuffer = NULL;
2762                         element3s_indexbuffer = NULL;
2763                 }
2764                 break;
2765         case RENDERPATH_D3D9:
2766         case RENDERPATH_D3D10:
2767         case RENDERPATH_D3D11:
2768                 break;
2769         case RENDERPATH_SOFT:
2770                 break;
2771         }
2772         // upload a dynamic index buffer if needed
2773         if (element3s)
2774         {
2775                 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2776                 {
2777                         if (gl_state.draw_dynamicindexbuffer)
2778                                 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2779                         else
2780                                 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2781                         element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2782                         element3s_bufferoffset = 0;
2783                 }
2784         }
2785         else if (element3i)
2786         {
2787                 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2788                 {
2789                         if (gl_state.draw_dynamicindexbuffer)
2790                                 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2791                         else
2792                                 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2793                         element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2794                         element3i_bufferoffset = 0;
2795                 }
2796         }
2797         bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2798         bufferoffset3i = element3i_bufferoffset;
2799         bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2800         bufferoffset3s = element3s_bufferoffset;
2801         r_refdef.stats.draws++;
2802         r_refdef.stats.draws_vertices += numvertices;
2803         r_refdef.stats.draws_elements += numelements;
2804         if (gl_paranoid.integer)
2805         {
2806                 unsigned int i;
2807                 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2808 #if 0
2809                 unsigned int j, size;
2810                 const int *p;
2811                 // note: there's no validation done here on buffer objects because it
2812                 // is somewhat difficult to get at the data, and gl_paranoid can be
2813                 // used without buffer objects if the need arises
2814                 // (the data could be gotten using glMapBuffer but it would be very
2815                 //  slow due to uncachable video memory reads)
2816                 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2817                         Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2818                 CHECKGLERROR
2819                 if (gl_state.pointer_vertex_pointer)
2820                         for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2821                                 paranoidblah += *p;
2822                 if (gl_state.pointer_color_enabled)
2823                 {
2824                         if (!qglIsEnabled(GL_COLOR_ARRAY))
2825                                 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2826                         CHECKGLERROR
2827                         if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2828                                 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2829                                         paranoidblah += *p;
2830                 }
2831                 for (i = 0;i < vid.texarrayunits;i++)
2832                 {
2833                         if (gl_state.units[i].arrayenabled)
2834                         {
2835                                 GL_ClientActiveTexture(i);
2836                                 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2837                                         Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2838                                 CHECKGLERROR
2839                                 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2840                                         for (j = 0, size = numvertices * gl_state.units[i].arraycomponents, p = (int *)((float *)gl_state.units[i].pointer_texcoord + firstvertex * gl_state.units[i].arraycomponents);j < size;j++, p++)
2841                                                 paranoidblah += *p;
2842                         }
2843                 }
2844 #endif
2845                 if (element3i)
2846                 {
2847                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2848                         {
2849                                 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2850                                 {
2851                                         Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2852                                         return;
2853                                 }
2854                         }
2855                 }
2856                 if (element3s)
2857                 {
2858                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2859                         {
2860                                 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2861                                 {
2862                                         Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2863                                         return;
2864                                 }
2865                         }
2866                 }
2867         }
2868         if (r_render.integer || r_refdef.draw2dstage)
2869         {
2870                 switch(vid.renderpath)
2871                 {
2872                 case RENDERPATH_GL11:
2873                 case RENDERPATH_GL13:
2874                 case RENDERPATH_GL20:
2875                         CHECKGLERROR
2876                         if (gl_mesh_testmanualfeeding.integer)
2877                         {
2878 #ifndef USE_GLES2
2879                                 unsigned int i, j, element;
2880                                 const GLfloat *p;
2881                                 qglBegin(GL_TRIANGLES);
2882                                 if(vid.renderpath == RENDERPATH_GL20)
2883                                 {
2884                                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2885                                         {
2886                                                 if (element3i)
2887                                                         element = element3i[i];
2888                                                 else if (element3s)
2889                                                         element = element3s[i];
2890                                                 else
2891                                                         element = firstvertex + i;
2892                                                 for (j = 0;j < vid.texarrayunits;j++)
2893                                                 {
2894                                                         if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2895                                                         {
2896                                                                 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2897                                                                 {
2898                                                                         p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2899                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2900                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2], p[3]);
2901                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2902                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2]);
2903                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2904                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1]);
2905                                                                         else
2906                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, p[0]);
2907                                                                 }
2908                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2909                                                                 {
2910                                                                         const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2911                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2912                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2], s[3]);
2913                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2914                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2]);
2915                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2916                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1]);
2917                                                                         else if (gl_state.units[j].pointer_texcoord_components == 1)
2918                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, s[0]);
2919                                                                 }
2920                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2921                                                                 {
2922                                                                         const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2923                                                                         if (gl_state.units[j].pointer_texcoord_components == 4)
2924                                                                                 qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2], sb[3]);
2925                                                                         else if (gl_state.units[j].pointer_texcoord_components == 3)
2926                                                                                 qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2]);
2927                                                                         else if (gl_state.units[j].pointer_texcoord_components == 2)
2928                                                                                 qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1]);
2929                                                                         else if (gl_state.units[j].pointer_texcoord_components == 1)
2930                                                                                 qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0]);
2931                                                                 }
2932                                                         }
2933                                                 }
2934                                                 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2935                                                 {
2936                                                         if (gl_state.pointer_color_gltype == GL_FLOAT)
2937                                                         {
2938                                                                 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2939                                                                 qglVertexAttrib4f(GLSLATTRIB_COLOR, p[0], p[1], p[2], p[3]);
2940                                                         }
2941                                                         else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2942                                                         {
2943                                                                 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2944                                                                 qglVertexAttrib4Nub(GLSLATTRIB_COLOR, ub[0], ub[1], ub[2], ub[3]);
2945                                                         }
2946                                                 }
2947                                                 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2948                                                 {
2949                                                         p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2950                                                         if (gl_state.pointer_vertex_components == 4)
2951                                                                 qglVertexAttrib4f(GLSLATTRIB_POSITION, p[0], p[1], p[2], p[3]);
2952                                                         else if (gl_state.pointer_vertex_components == 3)
2953                                                                 qglVertexAttrib3f(GLSLATTRIB_POSITION, p[0], p[1], p[2]);
2954                                                         else
2955                                                                 qglVertexAttrib2f(GLSLATTRIB_POSITION, p[0], p[1]);
2956                                                 }
2957                                         }
2958                                 }
2959                                 else
2960                                 {
2961                                         for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2962                                         {
2963                                                 if (element3i)
2964                                                         element = element3i[i];
2965                                                 else if (element3s)
2966                                                         element = element3s[i];
2967                                                 else
2968                                                         element = firstvertex + i;
2969                                                 for (j = 0;j < vid.texarrayunits;j++)
2970                                                 {
2971                                                         if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2972                                                         {
2973                                                                 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2974                                                                 {
2975                                                                         p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2976                                                                         if (vid.texarrayunits > 1)
2977                                                                         {
2978                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2979                                                                                         qglMultiTexCoord4f(GL_TEXTURE0 + j, p[0], p[1], p[2], p[3]);
2980                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2981                                                                                         qglMultiTexCoord3f(GL_TEXTURE0 + j, p[0], p[1], p[2]);
2982                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2983                                                                                         qglMultiTexCoord2f(GL_TEXTURE0 + j, p[0], p[1]);
2984                                                                                 else
2985                                                                                         qglMultiTexCoord1f(GL_TEXTURE0 + j, p[0]);
2986                                                                         }
2987                                                                         else
2988                                                                         {
2989                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
2990                                                                                         qglTexCoord4f(p[0], p[1], p[2], p[3]);
2991                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
2992                                                                                         qglTexCoord3f(p[0], p[1], p[2]);
2993                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
2994                                                                                         qglTexCoord2f(p[0], p[1]);
2995                                                                                 else
2996                                                                                         qglTexCoord1f(p[0]);
2997                                                                         }
2998                                                                 }
2999                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
3000                                                                 {
3001                                                                         const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
3002                                                                         if (vid.texarrayunits > 1)
3003                                                                         {
3004                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
3005                                                                                         qglMultiTexCoord4f(GL_TEXTURE0 + j, s[0], s[1], s[2], s[3]);
3006                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
3007                                                                                         qglMultiTexCoord3f(GL_TEXTURE0 + j, s[0], s[1], s[2]);
3008                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
3009                                                                                         qglMultiTexCoord2f(GL_TEXTURE0 + j, s[0], s[1]);
3010                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
3011                                                                                         qglMultiTexCoord1f(GL_TEXTURE0 + j, s[0]);
3012                                                                         }
3013                                                                         else
3014                                                                         {
3015                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
3016                                                                                         qglTexCoord4f(s[0], s[1], s[2], s[3]);
3017                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
3018                                                                                         qglTexCoord3f(s[0], s[1], s[2]);
3019                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
3020                                                                                         qglTexCoord2f(s[0], s[1]);
3021                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 1)
3022                                                                                         qglTexCoord1f(s[0]);
3023                                                                         }
3024                                                                 }
3025                                                                 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
3026                                                                 {
3027                                                                         const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
3028                                                                         if (vid.texarrayunits > 1)
3029                                                                         {
3030                                                                                 if (gl_state.units[j].pointer_texcoord_components == 4)
3031                                                                                         qglMultiTexCoord4f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2], sb[3]);
3032                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 3)
3033                                                                                         qglMultiTexCoord3f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2]);
3034                                                                                 else if (gl_state.units[j].pointer_texcoord_components == 2)
3035                   &nbs