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