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