3 #include "cl_collision.h"
4 #include "dpsoftrast.h"
7 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
8 extern D3DCAPS9 vid_d3d9caps;
11 #define MAX_RENDERTARGETS 4
13 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
14 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
15 cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
16 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
17 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
19 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
20 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
21 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
22 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
23 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
24 cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
25 cvar_t gl_vbo_dynamicvertex = {CVAR_SAVE, "gl_vbo_dynamicvertex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
26 cvar_t gl_vbo_dynamicindex = {CVAR_SAVE, "gl_vbo_dynamicindex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
27 cvar_t gl_fbo = {CVAR_SAVE, "gl_fbo", "1", "make use of GL_ARB_framebuffer_object extension to enable shadowmaps and other features using pixel formats different from the framebuffer"};
29 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
30 qboolean v_flipped_state = false;
32 r_viewport_t gl_viewport;
33 matrix4x4_t gl_modelmatrix;
34 matrix4x4_t gl_viewmatrix;
35 matrix4x4_t gl_modelviewmatrix;
36 matrix4x4_t gl_projectionmatrix;
37 matrix4x4_t gl_modelviewprojectionmatrix;
38 float gl_modelview16f[16];
39 float gl_modelviewprojection16f[16];
40 qboolean gl_modelmatrixchanged;
42 int gl_maxdrawrangeelementsvertices;
43 int gl_maxdrawrangeelementsindices;
48 void GL_PrintError(int errornumber, const char *filename, int linenumber)
52 #ifdef GL_INVALID_ENUM
54 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
57 #ifdef GL_INVALID_VALUE
58 case GL_INVALID_VALUE:
59 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
62 #ifdef GL_INVALID_OPERATION
63 case GL_INVALID_OPERATION:
64 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
67 #ifdef GL_STACK_OVERFLOW
68 case GL_STACK_OVERFLOW:
69 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
72 #ifdef GL_STACK_UNDERFLOW
73 case GL_STACK_UNDERFLOW:
74 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
77 #ifdef GL_OUT_OF_MEMORY
78 case GL_OUT_OF_MEMORY:
79 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
82 #ifdef GL_TABLE_TOO_LARGE
83 case GL_TABLE_TOO_LARGE:
84 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
87 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
88 case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
89 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
93 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
99 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
101 void SCR_ScreenShot_f (void);
103 typedef struct gltextureunit_s
105 int pointer_texcoord_components;
106 int pointer_texcoord_gltype;
107 size_t pointer_texcoord_stride;
108 const void *pointer_texcoord_pointer;
109 const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
110 size_t pointer_texcoord_offset;
113 int t2d, t3d, tcubemap;
115 int rgbscale, alphascale;
117 int combinergb, combinealpha;
118 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
119 int texmatrixenabled;
124 typedef struct gl_state_s
132 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
136 float polygonoffset[2];
139 float alphafuncvalue;
142 unsigned int clientunit;
143 gltextureunit_t units[MAX_TEXTUREUNITS];
147 int vertexbufferobject;
148 int elementbufferobject;
149 int framebufferobject;
150 int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
151 qboolean pointer_color_enabled;
153 int pointer_vertex_components;
154 int pointer_vertex_gltype;
155 size_t pointer_vertex_stride;
156 const void *pointer_vertex_pointer;
157 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
158 size_t pointer_vertex_offset;
160 int pointer_color_components;
161 int pointer_color_gltype;
162 size_t pointer_color_stride;
163 const void *pointer_color_pointer;
164 const r_meshbuffer_t *pointer_color_vertexbuffer;
165 size_t pointer_color_offset;
167 void *preparevertices_tempdata;
168 size_t preparevertices_tempdatamaxsize;
169 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
170 r_vertexgeneric_t *preparevertices_vertexgeneric;
171 r_vertexmesh_t *preparevertices_vertexmesh;
172 int preparevertices_numvertices;
174 r_meshbuffer_t *draw_dynamicindexbuffer;
176 qboolean usevbo_staticvertex;
177 qboolean usevbo_staticindex;
178 qboolean usevbo_dynamicvertex;
179 qboolean usevbo_dynamicindex;
181 memexpandablearray_t meshbufferarray;
186 // rtexture_t *d3drt_depthtexture;
187 // rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
188 IDirect3DSurface9 *d3drt_depthsurface;
189 IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
190 IDirect3DSurface9 *d3drt_backbufferdepthsurface;
191 IDirect3DSurface9 *d3drt_backbuffercolorsurface;
192 void *d3dvertexbuffer;
194 size_t d3dvertexsize;
199 static gl_state_t gl_state;
203 note: here's strip order for a terrain row:
210 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
212 *elements++ = i + row;
214 *elements++ = i + row + 1;
217 *elements++ = i + row + 1;
220 for (y = 0;y < rows - 1;y++)
222 for (x = 0;x < columns - 1;x++)
225 *elements++ = i + columns;
227 *elements++ = i + columns + 1;
230 *elements++ = i + columns + 1;
241 for (y = 0;y < rows - 1;y++)
243 for (x = 0;x < columns - 1;x++)
247 *elements++ = i + columns;
248 *elements++ = i + columns + 1;
249 *elements++ = i + columns;
250 *elements++ = i + columns + 1;
256 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
257 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
258 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
259 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
261 void GL_VBOStats_f(void)
263 GL_Mesh_ListVBOs(true);
266 static void GL_Backend_ResetState(void);
268 static void R_Mesh_InitVertexDeclarations(void);
269 static void R_Mesh_DestroyVertexDeclarations(void);
271 static void R_Mesh_SetUseVBO(void)
273 switch(vid.renderpath)
275 case RENDERPATH_GL11:
276 case RENDERPATH_GL13:
277 case RENDERPATH_GL20:
278 case RENDERPATH_GLES1:
279 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
280 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
281 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
282 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
284 case RENDERPATH_D3D9:
285 gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
286 gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo;
288 case RENDERPATH_D3D10:
289 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
291 case RENDERPATH_D3D11:
292 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
294 case RENDERPATH_SOFT:
295 gl_state.usevbo_staticvertex = false;
296 gl_state.usevbo_staticindex = false;
297 gl_state.usevbo_dynamicvertex = false;
298 gl_state.usevbo_dynamicindex = false;
300 case RENDERPATH_GLES2:
301 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
302 gl_state.usevbo_staticindex = false;
303 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
304 gl_state.usevbo_dynamicindex = false;
309 static void gl_backend_start(void)
311 memset(&gl_state, 0, sizeof(gl_state));
313 R_Mesh_InitVertexDeclarations();
316 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
318 Con_DPrintf("OpenGL backend started.\n");
322 GL_Backend_ResetState();
324 switch(vid.renderpath)
326 case RENDERPATH_GL11:
327 case RENDERPATH_GL13:
328 case RENDERPATH_GL20:
329 case RENDERPATH_GLES1:
330 case RENDERPATH_GLES2:
331 // fetch current fbo here (default fbo is not 0 on some GLES devices)
332 if (vid.support.ext_framebuffer_object)
333 qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
335 case RENDERPATH_D3D9:
337 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
338 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
341 case RENDERPATH_D3D10:
342 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
344 case RENDERPATH_D3D11:
345 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
347 case RENDERPATH_SOFT:
352 static void gl_backend_shutdown(void)
354 Con_DPrint("OpenGL Backend shutting down\n");
356 switch(vid.renderpath)
358 case RENDERPATH_GL11:
359 case RENDERPATH_GL13:
360 case RENDERPATH_GL20:
361 case RENDERPATH_SOFT:
362 case RENDERPATH_GLES1:
363 case RENDERPATH_GLES2:
365 case RENDERPATH_D3D9:
367 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
368 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
371 case RENDERPATH_D3D10:
372 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
374 case RENDERPATH_D3D11:
375 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
379 if (gl_state.preparevertices_tempdata)
380 Mem_Free(gl_state.preparevertices_tempdata);
381 if (gl_state.preparevertices_dynamicvertexbuffer)
382 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
384 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
386 R_Mesh_DestroyVertexDeclarations();
388 memset(&gl_state, 0, sizeof(gl_state));
391 static void gl_backend_newmap(void)
395 static void gl_backend_devicelost(void)
398 r_meshbuffer_t *buffer;
400 gl_state.d3dvertexbuffer = NULL;
402 switch(vid.renderpath)
404 case RENDERPATH_GL11:
405 case RENDERPATH_GL13:
406 case RENDERPATH_GL20:
407 case RENDERPATH_SOFT:
408 case RENDERPATH_GLES1:
409 case RENDERPATH_GLES2:
411 case RENDERPATH_D3D9:
413 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
414 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
417 case RENDERPATH_D3D10:
418 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
420 case RENDERPATH_D3D11:
421 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
424 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
425 for (i = 0;i < endindex;i++)
427 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
428 if (!buffer || !buffer->isdynamic)
430 switch(vid.renderpath)
432 case RENDERPATH_GL11:
433 case RENDERPATH_GL13:
434 case RENDERPATH_GL20:
435 case RENDERPATH_SOFT:
436 case RENDERPATH_GLES1:
437 case RENDERPATH_GLES2:
439 case RENDERPATH_D3D9:
441 if (buffer->devicebuffer)
443 if (buffer->isindexbuffer)
444 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
446 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
447 buffer->devicebuffer = NULL;
451 case RENDERPATH_D3D10:
452 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
454 case RENDERPATH_D3D11:
455 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
461 static void gl_backend_devicerestored(void)
463 switch(vid.renderpath)
465 case RENDERPATH_GL11:
466 case RENDERPATH_GL13:
467 case RENDERPATH_GL20:
468 case RENDERPATH_SOFT:
469 case RENDERPATH_GLES1:
470 case RENDERPATH_GLES2:
472 case RENDERPATH_D3D9:
474 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
475 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
478 case RENDERPATH_D3D10:
479 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
481 case RENDERPATH_D3D11:
482 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
487 void gl_backend_init(void)
491 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
493 polygonelement3s[i * 3 + 0] = 0;
494 polygonelement3s[i * 3 + 1] = i + 1;
495 polygonelement3s[i * 3 + 2] = i + 2;
497 // elements for rendering a series of quads as triangles
498 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
500 quadelement3s[i * 6 + 0] = i * 4;
501 quadelement3s[i * 6 + 1] = i * 4 + 1;
502 quadelement3s[i * 6 + 2] = i * 4 + 2;
503 quadelement3s[i * 6 + 3] = i * 4;
504 quadelement3s[i * 6 + 4] = i * 4 + 2;
505 quadelement3s[i * 6 + 5] = i * 4 + 3;
508 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
509 polygonelement3i[i] = polygonelement3s[i];
510 for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
511 quadelement3i[i] = quadelement3s[i];
513 Cvar_RegisterVariable(&r_render);
514 Cvar_RegisterVariable(&r_renderview);
515 Cvar_RegisterVariable(&r_waterwarp);
516 Cvar_RegisterVariable(&gl_polyblend);
517 Cvar_RegisterVariable(&v_flipped);
518 Cvar_RegisterVariable(&gl_dither);
519 Cvar_RegisterVariable(&gl_vbo);
520 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
521 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
522 Cvar_RegisterVariable(&gl_paranoid);
523 Cvar_RegisterVariable(&gl_printcheckerror);
525 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
526 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
527 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
529 Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
531 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
534 void GL_SetMirrorState(qboolean state);
536 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
540 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
541 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
543 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
545 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
546 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
547 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
549 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
554 switch(vid.renderpath)
556 case RENDERPATH_GL11:
557 case RENDERPATH_GL13:
558 case RENDERPATH_GL20:
559 case RENDERPATH_GLES1:
560 case RENDERPATH_GLES2:
563 case RENDERPATH_D3D9:
564 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
566 case RENDERPATH_D3D10:
567 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
569 case RENDERPATH_D3D11:
570 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
572 case RENDERPATH_SOFT:
578 static int bboxedges[12][2] =
597 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
599 int i, ix1, iy1, ix2, iy2;
600 float x1, y1, x2, y2;
611 scissor[0] = r_refdef.view.viewport.x;
612 scissor[1] = r_refdef.view.viewport.y;
613 scissor[2] = r_refdef.view.viewport.width;
614 scissor[3] = r_refdef.view.viewport.height;
616 // if view is inside the box, just say yes it's visible
617 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
620 x1 = y1 = x2 = y2 = 0;
622 // transform all corners that are infront of the nearclip plane
623 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
624 plane4f[3] = r_refdef.view.frustum[4].dist;
626 for (i = 0;i < 8;i++)
628 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
629 dist[i] = DotProduct4(corner[i], plane4f);
630 sign[i] = dist[i] > 0;
633 VectorCopy(corner[i], vertex[numvertices]);
637 // if some points are behind the nearclip, add clipped edge points to make
638 // sure that the scissor boundary is complete
639 if (numvertices > 0 && numvertices < 8)
641 // add clipped edge points
642 for (i = 0;i < 12;i++)
646 if (sign[j] != sign[k])
648 f = dist[j] / (dist[j] - dist[k]);
649 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
655 // if we have no points to check, it is behind the view plane
659 // if we have some points to transform, check what screen area is covered
660 x1 = y1 = x2 = y2 = 0;
662 //Con_Printf("%i vertices to transform...\n", numvertices);
663 for (i = 0;i < numvertices;i++)
665 VectorCopy(vertex[i], v);
666 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
667 //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]);
670 if (x1 > v2[0]) x1 = v2[0];
671 if (x2 < v2[0]) x2 = v2[0];
672 if (y1 > v2[1]) y1 = v2[1];
673 if (y2 < v2[1]) y2 = v2[1];
682 // now convert the scissor rectangle to integer screen coordinates
683 ix1 = (int)(x1 - 1.0f);
684 //iy1 = vid.height - (int)(y2 - 1.0f);
685 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
686 iy1 = (int)(y1 - 1.0f);
687 ix2 = (int)(x2 + 1.0f);
688 //iy2 = vid.height - (int)(y1 + 1.0f);
689 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
690 iy2 = (int)(y2 + 1.0f);
691 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
693 // clamp it to the screen
694 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
695 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
696 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
697 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
699 // if it is inside out, it's not visible
700 if (ix2 <= ix1 || iy2 <= iy1)
703 // the light area is visible, set up the scissor rectangle
706 scissor[2] = ix2 - ix1;
707 scissor[3] = iy2 - iy1;
709 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
710 switch(vid.renderpath)
712 case RENDERPATH_D3D9:
713 case RENDERPATH_D3D10:
714 case RENDERPATH_D3D11:
715 scissor[1] = vid.height - scissor[1] - scissor[3];
717 case RENDERPATH_GL11:
718 case RENDERPATH_GL13:
719 case RENDERPATH_GL20:
720 case RENDERPATH_SOFT:
721 case RENDERPATH_GLES1:
722 case RENDERPATH_GLES2:
730 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
734 float clipPlane[4], v3[3], v4[3];
737 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
739 VectorSet(normal, normalx, normaly, normalz);
740 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
741 VectorScale(normal, -dist, v3);
742 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
743 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
744 clipPlane[3] = -DotProduct(v4, clipPlane);
748 // testing code for comparing results
750 VectorCopy4(clipPlane, clipPlane2);
751 R_EntityMatrix(&identitymatrix);
752 VectorSet(q, normal[0], normal[1], normal[2], -dist);
753 qglClipPlane(GL_CLIP_PLANE0, q);
754 qglGetClipPlane(GL_CLIP_PLANE0, q);
755 VectorCopy4(q, clipPlane);
759 // Calculate the clip-space corner point opposite the clipping plane
760 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
761 // transform it into camera space by multiplying it
762 // by the inverse of the projection matrix
763 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
764 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
766 q[3] = (1.0f + m[10]) / m[14];
768 // Calculate the scaled plane vector
769 d = 2.0f / DotProduct4(clipPlane, q);
771 // Replace the third row of the projection matrix
772 m[2] = clipPlane[0] * d;
773 m[6] = clipPlane[1] * d;
774 m[10] = clipPlane[2] * d + 1.0f;
775 m[14] = clipPlane[3] * d;
778 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)
780 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
782 memset(v, 0, sizeof(*v));
783 v->type = R_VIEWPORTTYPE_ORTHO;
784 v->cameramatrix = *cameramatrix;
791 memset(m, 0, sizeof(m));
792 m[0] = 2/(right - left);
793 m[5] = 2/(top - bottom);
794 m[10] = -2/(zFar - zNear);
795 m[12] = - (right + left)/(right - left);
796 m[13] = - (top + bottom)/(top - bottom);
797 m[14] = - (zFar + zNear)/(zFar - zNear);
799 switch(vid.renderpath)
801 case RENDERPATH_GL11:
802 case RENDERPATH_GL13:
803 case RENDERPATH_GL20:
804 case RENDERPATH_SOFT:
805 case RENDERPATH_GLES1:
806 case RENDERPATH_GLES2:
808 case RENDERPATH_D3D9:
809 case RENDERPATH_D3D10:
810 case RENDERPATH_D3D11:
811 m[10] = -1/(zFar - zNear);
812 m[14] = -zNear/(zFar-zNear);
815 v->screentodepth[0] = -farclip / (farclip - nearclip);
816 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
818 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
821 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
823 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
829 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
830 R_Viewport_TransformToScreen(v, test1, test2);
831 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
836 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)
838 matrix4x4_t tempmatrix, basematrix;
840 memset(v, 0, sizeof(*v));
842 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
843 v->cameramatrix = *cameramatrix;
850 memset(m, 0, sizeof(m));
851 m[0] = 1.0 / frustumx;
852 m[5] = 1.0 / frustumy;
853 m[10] = -(farclip + nearclip) / (farclip - nearclip);
855 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
856 v->screentodepth[0] = -farclip / (farclip - nearclip);
857 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
859 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
860 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
861 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
862 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
865 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
867 if(v_flipped.integer)
875 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
878 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)
880 matrix4x4_t tempmatrix, basematrix;
881 const float nudge = 1.0 - 1.0 / (1<<23);
883 memset(v, 0, sizeof(*v));
885 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
886 v->cameramatrix = *cameramatrix;
893 memset(m, 0, sizeof(m));
894 m[ 0] = 1.0 / frustumx;
895 m[ 5] = 1.0 / frustumy;
898 m[14] = -2 * nearclip * nudge;
899 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
900 v->screentodepth[1] = m[14] * -0.5;
902 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
903 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
904 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
905 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
908 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
910 if(v_flipped.integer)
918 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
921 float cubeviewmatrix[6][16] =
923 // standard cubemap projections
961 float rectviewmatrix[6][16] =
963 // sign-preserving cubemap projections
1002 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
1004 matrix4x4_t tempmatrix, basematrix;
1006 memset(v, 0, sizeof(*v));
1007 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1008 v->cameramatrix = *cameramatrix;
1012 memset(m, 0, sizeof(m));
1014 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1016 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1018 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
1019 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1020 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1023 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1025 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1028 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)
1030 matrix4x4_t tempmatrix, basematrix;
1032 memset(v, 0, sizeof(*v));
1033 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1034 v->cameramatrix = *cameramatrix;
1035 v->x = (side & 1) * size;
1036 v->y = (side >> 1) * size;
1040 memset(m, 0, sizeof(m));
1041 m[0] = m[5] = 1.0f * ((float)size - border) / size;
1042 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1044 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1046 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1047 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1048 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1050 switch(vid.renderpath)
1052 case RENDERPATH_GL20:
1053 case RENDERPATH_GL13:
1054 case RENDERPATH_GL11:
1055 case RENDERPATH_SOFT:
1056 case RENDERPATH_GLES1:
1057 case RENDERPATH_GLES2:
1059 case RENDERPATH_D3D9:
1062 case RENDERPATH_D3D10:
1063 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1065 case RENDERPATH_D3D11:
1066 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1071 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1073 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1076 void R_SetViewport(const r_viewport_t *v)
1081 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1082 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1084 // copy over the matrices to our state
1085 gl_viewmatrix = v->viewmatrix;
1086 gl_projectionmatrix = v->projectmatrix;
1088 switch(vid.renderpath)
1090 case RENDERPATH_GL13:
1091 case RENDERPATH_GL11:
1092 case RENDERPATH_GLES1:
1094 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1095 // Load the projection matrix into OpenGL
1096 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1097 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1098 qglLoadMatrixf(m);CHECKGLERROR
1099 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1101 case RENDERPATH_D3D9:
1104 D3DVIEWPORT9 d3dviewport;
1105 d3dviewport.X = gl_viewport.x;
1106 d3dviewport.Y = gl_viewport.y;
1107 d3dviewport.Width = gl_viewport.width;
1108 d3dviewport.Height = gl_viewport.height;
1109 d3dviewport.MinZ = gl_state.depthrange[0];
1110 d3dviewport.MaxZ = gl_state.depthrange[1];
1111 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1115 case RENDERPATH_D3D10:
1116 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1118 case RENDERPATH_D3D11:
1119 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1121 case RENDERPATH_SOFT:
1122 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1124 case RENDERPATH_GL20:
1125 case RENDERPATH_GLES2:
1127 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1131 // force an update of the derived matrices
1132 gl_modelmatrixchanged = true;
1133 R_EntityMatrix(&gl_modelmatrix);
1136 void R_GetViewport(r_viewport_t *v)
1141 static void GL_BindVBO(int bufferobject)
1143 if (gl_state.vertexbufferobject != bufferobject)
1145 gl_state.vertexbufferobject = bufferobject;
1147 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1151 static void GL_BindEBO(int bufferobject)
1153 if (gl_state.elementbufferobject != bufferobject)
1155 gl_state.elementbufferobject = bufferobject;
1157 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1161 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1164 switch(vid.renderpath)
1166 case RENDERPATH_GL11:
1167 case RENDERPATH_GL13:
1168 case RENDERPATH_GL20:
1169 case RENDERPATH_GLES1:
1170 case RENDERPATH_GLES2:
1171 if (!vid.support.ext_framebuffer_object)
1173 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1174 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1175 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1176 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1177 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1178 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1179 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1181 case RENDERPATH_D3D9:
1182 case RENDERPATH_D3D10:
1183 case RENDERPATH_D3D11:
1185 case RENDERPATH_SOFT:
1191 void R_Mesh_DestroyFramebufferObject(int fbo)
1193 switch(vid.renderpath)
1195 case RENDERPATH_GL11:
1196 case RENDERPATH_GL13:
1197 case RENDERPATH_GL20:
1198 case RENDERPATH_GLES1:
1199 case RENDERPATH_GLES2:
1201 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1203 case RENDERPATH_D3D9:
1204 case RENDERPATH_D3D10:
1205 case RENDERPATH_D3D11:
1207 case RENDERPATH_SOFT:
1213 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1215 // LordHavoc: for some weird reason the redundant SetDepthStencilSurface calls are necessary (otherwise the lights fail depth test, as if they were using the shadowmap depth surface and render target still)
1216 if (gl_state.d3drt_depthsurface == depthsurface && gl_state.d3drt_colorsurfaces[0] == colorsurface0 && gl_state.d3drt_colorsurfaces[1] == colorsurface1 && gl_state.d3drt_colorsurfaces[2] == colorsurface2 && gl_state.d3drt_colorsurfaces[3] == colorsurface3)
1219 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1220 if (gl_state.d3drt_depthsurface != depthsurface)
1222 gl_state.d3drt_depthsurface = depthsurface;
1223 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1225 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1227 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1228 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1230 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1232 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1233 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1235 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1237 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1238 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1240 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1242 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1243 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1248 void R_Mesh_ResetRenderTargets(void)
1250 switch(vid.renderpath)
1252 case RENDERPATH_GL11:
1253 case RENDERPATH_GL13:
1254 case RENDERPATH_GL20:
1255 case RENDERPATH_GLES1:
1256 case RENDERPATH_GLES2:
1257 if (gl_state.framebufferobject)
1259 gl_state.framebufferobject = 0;
1260 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1263 case RENDERPATH_D3D9:
1265 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1268 case RENDERPATH_D3D10:
1269 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1271 case RENDERPATH_D3D11:
1272 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1274 case RENDERPATH_SOFT:
1275 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1280 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1284 rtexture_t *textures[5];
1285 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1286 textures[4] = depthtexture;
1287 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1288 for (j = 0;j < 5;j++)
1290 for (i = 0;i < vid.teximageunits;i++)
1291 if (gl_state.units[i].texture == textures[j])
1292 R_Mesh_TexBind(i, NULL);
1293 // set up framebuffer object or render targets for the active rendering API
1294 switch(vid.renderpath)
1296 case RENDERPATH_GL11:
1297 case RENDERPATH_GL13:
1298 case RENDERPATH_GL20:
1299 case RENDERPATH_GLES1:
1300 case RENDERPATH_GLES2:
1301 if (gl_state.framebufferobject != fbo)
1303 gl_state.framebufferobject = fbo;
1304 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1307 case RENDERPATH_D3D9:
1309 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1310 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1313 IDirect3DSurface9 *colorsurfaces[4];
1314 for (i = 0;i < 4;i++)
1316 colorsurfaces[i] = NULL;
1318 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1320 // set the render targets for real
1321 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1322 // release the texture surface levels (they won't be lost while bound...)
1323 for (i = 0;i < 4;i++)
1325 IDirect3DSurface9_Release(colorsurfaces[i]);
1328 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1331 case RENDERPATH_D3D10:
1332 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1334 case RENDERPATH_D3D11:
1335 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1337 case RENDERPATH_SOFT:
1341 unsigned int *pointers[5];
1342 memset(pointers, 0, sizeof(pointers));
1343 for (i = 0;i < 5;i++)
1344 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1345 width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1346 height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1347 DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1350 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1356 static int d3dcmpforglfunc(int f)
1360 case GL_NEVER: return D3DCMP_NEVER;
1361 case GL_LESS: return D3DCMP_LESS;
1362 case GL_EQUAL: return D3DCMP_EQUAL;
1363 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1364 case GL_GREATER: return D3DCMP_GREATER;
1365 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1366 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1367 case GL_ALWAYS: return D3DCMP_ALWAYS;
1368 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1372 static int d3dstencilopforglfunc(int f)
1376 case GL_KEEP: return D3DSTENCILOP_KEEP;
1377 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1378 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1379 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1384 extern cvar_t r_transparent_alphatocoverage;
1386 static void GL_Backend_ResetState(void)
1389 gl_state.active = true;
1390 gl_state.depthtest = true;
1391 gl_state.alphatest = false;
1392 gl_state.alphafunc = GL_GEQUAL;
1393 gl_state.alphafuncvalue = 0.5f;
1394 gl_state.blendfunc1 = GL_ONE;
1395 gl_state.blendfunc2 = GL_ZERO;
1396 gl_state.blend = false;
1397 gl_state.depthmask = GL_TRUE;
1398 gl_state.colormask = 15;
1399 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1400 gl_state.lockrange_first = 0;
1401 gl_state.lockrange_count = 0;
1402 gl_state.cullface = GL_FRONT;
1403 gl_state.cullfaceenable = false;
1404 gl_state.polygonoffset[0] = 0;
1405 gl_state.polygonoffset[1] = 0;
1406 gl_state.framebufferobject = 0;
1407 gl_state.depthfunc = GL_LEQUAL;
1409 switch(vid.renderpath)
1411 case RENDERPATH_D3D9:
1414 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1415 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1416 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1417 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1418 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1419 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1420 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1421 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1422 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1423 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1427 case RENDERPATH_D3D10:
1428 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1430 case RENDERPATH_D3D11:
1431 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1433 case RENDERPATH_GL11:
1434 case RENDERPATH_GL13:
1435 case RENDERPATH_GLES1:
1438 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1439 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1440 qglDisable((r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
1441 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1442 qglDisable(GL_BLEND);CHECKGLERROR
1443 qglCullFace(gl_state.cullface);CHECKGLERROR
1444 qglDisable(GL_CULL_FACE);CHECKGLERROR
1445 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1446 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1447 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1448 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1450 if (vid.support.arb_vertex_buffer_object)
1452 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1453 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1456 if (vid.support.ext_framebuffer_object)
1458 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1459 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1462 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1463 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1465 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1466 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1467 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1469 if (vid.support.ext_framebuffer_object)
1470 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1472 gl_state.unit = MAX_TEXTUREUNITS;
1473 gl_state.clientunit = MAX_TEXTUREUNITS;
1474 for (i = 0;i < vid.texunits;i++)
1476 GL_ActiveTexture(i);
1477 GL_ClientActiveTexture(i);
1478 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1479 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1480 if (vid.support.ext_texture_3d)
1482 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1483 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1485 if (vid.support.arb_texture_cube_map)
1487 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1488 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1491 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1492 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1493 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1494 qglLoadIdentity();CHECKGLERROR
1495 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1496 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1500 case RENDERPATH_SOFT:
1501 DPSOFTRAST_ColorMask(1,1,1,1);
1502 DPSOFTRAST_AlphaTest(gl_state.alphatest);
1503 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1504 DPSOFTRAST_CullFace(gl_state.cullface);
1505 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1506 DPSOFTRAST_DepthMask(gl_state.depthmask);
1507 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1508 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1509 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1511 case RENDERPATH_GL20:
1512 case RENDERPATH_GLES2:
1514 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1515 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1516 qglDisable(GL_BLEND);CHECKGLERROR
1517 qglCullFace(gl_state.cullface);CHECKGLERROR
1518 qglDisable(GL_CULL_FACE);CHECKGLERROR
1519 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1520 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1521 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1522 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1523 // if (vid.renderpath == RENDERPATH_GL20)
1525 // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1526 // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1528 if (vid.support.arb_vertex_buffer_object)
1530 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1531 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1533 if (vid.support.ext_framebuffer_object)
1534 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1535 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1536 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1537 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1538 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1539 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1540 gl_state.unit = MAX_TEXTUREUNITS;
1541 gl_state.clientunit = MAX_TEXTUREUNITS;
1542 for (i = 0;i < vid.teximageunits;i++)
1544 GL_ActiveTexture(i);
1545 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1546 if (vid.support.ext_texture_3d)
1548 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1550 if (vid.support.arb_texture_cube_map)
1552 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1555 for (i = 0;i < vid.texarrayunits;i++)
1558 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1559 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1566 void GL_ActiveTexture(unsigned int num)
1568 if (gl_state.unit != num)
1570 gl_state.unit = num;
1571 switch(vid.renderpath)
1573 case RENDERPATH_GL11:
1574 case RENDERPATH_GL13:
1575 case RENDERPATH_GL20:
1576 case RENDERPATH_GLES1:
1577 case RENDERPATH_GLES2:
1578 if (qglActiveTexture)
1581 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1585 case RENDERPATH_D3D9:
1586 case RENDERPATH_D3D10:
1587 case RENDERPATH_D3D11:
1589 case RENDERPATH_SOFT:
1595 void GL_ClientActiveTexture(unsigned int num)
1597 if (gl_state.clientunit != num)
1599 gl_state.clientunit = num;
1600 switch(vid.renderpath)
1602 case RENDERPATH_GL11:
1603 case RENDERPATH_GL13:
1604 case RENDERPATH_GLES1:
1605 if (qglActiveTexture)
1608 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1612 case RENDERPATH_D3D9:
1613 case RENDERPATH_D3D10:
1614 case RENDERPATH_D3D11:
1616 case RENDERPATH_SOFT:
1618 case RENDERPATH_GL20:
1619 case RENDERPATH_GLES2:
1625 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1627 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1629 qboolean blendenable;
1630 gl_state.blendfunc1 = blendfunc1;
1631 gl_state.blendfunc2 = blendfunc2;
1632 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1633 switch(vid.renderpath)
1635 case RENDERPATH_GL11:
1636 case RENDERPATH_GL13:
1637 case RENDERPATH_GL20:
1638 case RENDERPATH_GLES1:
1639 case RENDERPATH_GLES2:
1641 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1642 if (gl_state.blend != blendenable)
1644 gl_state.blend = blendenable;
1645 if (!gl_state.blend)
1647 qglDisable(GL_BLEND);CHECKGLERROR
1651 qglEnable(GL_BLEND);CHECKGLERROR
1655 case RENDERPATH_D3D9:
1660 D3DBLEND d3dblendfunc[2];
1661 glblendfunc[0] = gl_state.blendfunc1;
1662 glblendfunc[1] = gl_state.blendfunc2;
1663 for (i = 0;i < 2;i++)
1665 switch(glblendfunc[i])
1667 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1668 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1669 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1670 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1671 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1672 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1673 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1674 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1675 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1676 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1679 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1680 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1681 if (gl_state.blend != blendenable)
1683 gl_state.blend = blendenable;
1684 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1689 case RENDERPATH_D3D10:
1690 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1692 case RENDERPATH_D3D11:
1693 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1695 case RENDERPATH_SOFT:
1696 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1702 void GL_DepthMask(int state)
1704 if (gl_state.depthmask != state)
1706 gl_state.depthmask = state;
1707 switch(vid.renderpath)
1709 case RENDERPATH_GL11:
1710 case RENDERPATH_GL13:
1711 case RENDERPATH_GL20:
1712 case RENDERPATH_GLES1:
1713 case RENDERPATH_GLES2:
1715 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1717 case RENDERPATH_D3D9:
1719 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1722 case RENDERPATH_D3D10:
1723 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1725 case RENDERPATH_D3D11:
1726 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1728 case RENDERPATH_SOFT:
1729 DPSOFTRAST_DepthMask(gl_state.depthmask);
1735 void GL_DepthTest(int state)
1737 if (gl_state.depthtest != state)
1739 gl_state.depthtest = state;
1740 switch(vid.renderpath)
1742 case RENDERPATH_GL11:
1743 case RENDERPATH_GL13:
1744 case RENDERPATH_GL20:
1745 case RENDERPATH_GLES1:
1746 case RENDERPATH_GLES2:
1748 if (gl_state.depthtest)
1750 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1754 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1757 case RENDERPATH_D3D9:
1759 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1762 case RENDERPATH_D3D10:
1763 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1765 case RENDERPATH_D3D11:
1766 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1768 case RENDERPATH_SOFT:
1769 DPSOFTRAST_DepthTest(gl_state.depthtest);
1775 void GL_DepthFunc(int state)
1777 if (gl_state.depthfunc != state)
1779 gl_state.depthfunc = state;
1780 switch(vid.renderpath)
1782 case RENDERPATH_GL11:
1783 case RENDERPATH_GL13:
1784 case RENDERPATH_GL20:
1785 case RENDERPATH_GLES1:
1786 case RENDERPATH_GLES2:
1788 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1790 case RENDERPATH_D3D9:
1792 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1795 case RENDERPATH_D3D10:
1796 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1798 case RENDERPATH_D3D11:
1799 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1801 case RENDERPATH_SOFT:
1802 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1808 void GL_DepthRange(float nearfrac, float farfrac)
1810 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1812 gl_state.depthrange[0] = nearfrac;
1813 gl_state.depthrange[1] = farfrac;
1814 switch(vid.renderpath)
1816 case RENDERPATH_GL11:
1817 case RENDERPATH_GL13:
1818 case RENDERPATH_GL20:
1819 case RENDERPATH_GLES1:
1820 case RENDERPATH_GLES2:
1821 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1823 case RENDERPATH_D3D9:
1826 D3DVIEWPORT9 d3dviewport;
1827 d3dviewport.X = gl_viewport.x;
1828 d3dviewport.Y = gl_viewport.y;
1829 d3dviewport.Width = gl_viewport.width;
1830 d3dviewport.Height = gl_viewport.height;
1831 d3dviewport.MinZ = gl_state.depthrange[0];
1832 d3dviewport.MaxZ = gl_state.depthrange[1];
1833 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1837 case RENDERPATH_D3D10:
1838 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840 case RENDERPATH_D3D11:
1841 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1843 case RENDERPATH_SOFT:
1844 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1850 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)
1852 switch (vid.renderpath)
1854 case RENDERPATH_GL11:
1855 case RENDERPATH_GL13:
1856 case RENDERPATH_GL20:
1857 case RENDERPATH_GLES1:
1858 case RENDERPATH_GLES2:
1862 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1866 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1868 if (vid.support.ati_separate_stencil)
1870 qglStencilMask(writemask);CHECKGLERROR
1871 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1872 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1873 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1875 else if (vid.support.ext_stencil_two_side)
1877 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1878 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1879 qglStencilMask(writemask);CHECKGLERROR
1880 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1881 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1882 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1883 qglStencilMask(writemask);CHECKGLERROR
1884 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1885 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1888 case RENDERPATH_D3D9:
1890 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1891 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1892 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1893 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1894 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1895 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1896 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1897 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1898 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1899 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1900 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1901 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1902 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1905 case RENDERPATH_D3D10:
1906 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1908 case RENDERPATH_D3D11:
1909 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1911 case RENDERPATH_SOFT:
1912 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1919 switch (vid.renderpath)
1921 case RENDERPATH_GL11:
1922 case RENDERPATH_GL13:
1923 case RENDERPATH_GL20:
1924 case RENDERPATH_GLES1:
1925 case RENDERPATH_GLES2:
1929 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1933 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1935 if (vid.support.ext_stencil_two_side)
1937 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1939 qglStencilMask(writemask);CHECKGLERROR
1940 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1941 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1944 case RENDERPATH_D3D9:
1946 if (vid.support.ati_separate_stencil)
1947 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1948 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1949 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1950 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1951 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1952 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1953 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1954 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1955 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1958 case RENDERPATH_D3D10:
1959 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_D3D11:
1962 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964 case RENDERPATH_SOFT:
1965 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1970 void GL_PolygonOffset(float planeoffset, float depthoffset)
1972 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1974 gl_state.polygonoffset[0] = planeoffset;
1975 gl_state.polygonoffset[1] = depthoffset;
1976 switch(vid.renderpath)
1978 case RENDERPATH_GL11:
1979 case RENDERPATH_GL13:
1980 case RENDERPATH_GL20:
1981 case RENDERPATH_GLES1:
1982 case RENDERPATH_GLES2:
1983 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1985 case RENDERPATH_D3D9:
1987 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1988 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1991 case RENDERPATH_D3D10:
1992 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994 case RENDERPATH_D3D11:
1995 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1997 case RENDERPATH_SOFT:
1998 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2004 void GL_SetMirrorState(qboolean state)
2006 if (v_flipped_state != state)
2008 v_flipped_state = state;
2009 if (gl_state.cullface == GL_BACK)
2010 gl_state.cullface = GL_FRONT;
2011 else if (gl_state.cullface == GL_FRONT)
2012 gl_state.cullface = GL_BACK;
2015 switch(vid.renderpath)
2017 case RENDERPATH_GL11:
2018 case RENDERPATH_GL13:
2019 case RENDERPATH_GL20:
2020 case RENDERPATH_GLES1:
2021 case RENDERPATH_GLES2:
2022 qglCullFace(gl_state.cullface);CHECKGLERROR
2024 case RENDERPATH_D3D9:
2026 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2029 case RENDERPATH_D3D10:
2030 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2032 case RENDERPATH_D3D11:
2033 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2035 case RENDERPATH_SOFT:
2036 DPSOFTRAST_CullFace(gl_state.cullface);
2042 void GL_CullFace(int state)
2046 if(state == GL_FRONT)
2048 else if(state == GL_BACK)
2052 switch(vid.renderpath)
2054 case RENDERPATH_GL11:
2055 case RENDERPATH_GL13:
2056 case RENDERPATH_GL20:
2057 case RENDERPATH_GLES1:
2058 case RENDERPATH_GLES2:
2061 if (state != GL_NONE)
2063 if (!gl_state.cullfaceenable)
2065 gl_state.cullfaceenable = true;
2066 qglEnable(GL_CULL_FACE);CHECKGLERROR
2068 if (gl_state.cullface != state)
2070 gl_state.cullface = state;
2071 qglCullFace(gl_state.cullface);CHECKGLERROR
2076 if (gl_state.cullfaceenable)
2078 gl_state.cullfaceenable = false;
2079 qglDisable(GL_CULL_FACE);CHECKGLERROR
2083 case RENDERPATH_D3D9:
2085 if (gl_state.cullface != state)
2087 gl_state.cullface = state;
2088 switch(gl_state.cullface)
2091 gl_state.cullfaceenable = false;
2092 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2095 gl_state.cullfaceenable = true;
2096 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2099 gl_state.cullfaceenable = true;
2100 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2106 case RENDERPATH_D3D10:
2107 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2109 case RENDERPATH_D3D11:
2110 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2112 case RENDERPATH_SOFT:
2113 if (gl_state.cullface != state)
2115 gl_state.cullface = state;
2116 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2117 DPSOFTRAST_CullFace(gl_state.cullface);
2123 void GL_MultiSampling(qboolean state)
2125 switch(vid.renderpath)
2127 case RENDERPATH_GL11:
2128 case RENDERPATH_GL13:
2129 case RENDERPATH_GLES1:
2130 case RENDERPATH_GL20:
2131 case RENDERPATH_GLES2:
2132 if (vid.support.arb_multisample)
2135 qglEnable(GL_MULTISAMPLE_ARB);
2137 qglDisable(GL_MULTISAMPLE_ARB);
2141 case RENDERPATH_D3D9:
2143 case RENDERPATH_D3D10:
2145 case RENDERPATH_D3D11:
2147 case RENDERPATH_SOFT:
2152 void GL_AlphaTest(int state)
2154 if (gl_state.alphatest != state)
2156 gl_state.alphatest = state;
2157 switch(vid.renderpath)
2159 case RENDERPATH_GL11:
2160 case RENDERPATH_GL13:
2161 case RENDERPATH_GLES1:
2162 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2164 if (gl_state.alphatest)
2166 qglEnable((r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
2170 qglDisable((r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
2173 case RENDERPATH_D3D9:
2175 // IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2178 case RENDERPATH_D3D10:
2180 case RENDERPATH_D3D11:
2182 case RENDERPATH_SOFT:
2183 DPSOFTRAST_AlphaTest(gl_state.alphatest);
2185 case RENDERPATH_GL20:
2186 case RENDERPATH_GLES2:
2187 if (vid_multisampling.integer)
2189 if (gl_state.alphatest && r_transparent_alphatocoverage.integer)
2190 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
2192 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
2200 void GL_ColorMask(int r, int g, int b, int a)
2202 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2203 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2204 if (gl_state.colormask != state)
2206 gl_state.colormask = state;
2207 switch(vid.renderpath)
2209 case RENDERPATH_GL11:
2210 case RENDERPATH_GL13:
2211 case RENDERPATH_GL20:
2212 case RENDERPATH_GLES1:
2213 case RENDERPATH_GLES2:
2215 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2217 case RENDERPATH_D3D9:
2219 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2222 case RENDERPATH_D3D10:
2223 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2225 case RENDERPATH_D3D11:
2226 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2228 case RENDERPATH_SOFT:
2229 DPSOFTRAST_ColorMask(r, g, b, a);
2235 void GL_Color(float cr, float cg, float cb, float ca)
2237 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)
2239 gl_state.color4f[0] = cr;
2240 gl_state.color4f[1] = cg;
2241 gl_state.color4f[2] = cb;
2242 gl_state.color4f[3] = ca;
2243 switch(vid.renderpath)
2245 case RENDERPATH_GL11:
2246 case RENDERPATH_GL13:
2247 case RENDERPATH_GLES1:
2249 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2252 case RENDERPATH_D3D9:
2253 case RENDERPATH_D3D10:
2254 case RENDERPATH_D3D11:
2255 // no equivalent in D3D
2257 case RENDERPATH_SOFT:
2258 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2260 case RENDERPATH_GL20:
2261 case RENDERPATH_GLES2:
2262 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2268 void GL_Scissor (int x, int y, int width, int height)
2270 switch(vid.renderpath)
2272 case RENDERPATH_GL11:
2273 case RENDERPATH_GL13:
2274 case RENDERPATH_GL20:
2275 case RENDERPATH_GLES1:
2276 case RENDERPATH_GLES2:
2278 qglScissor(x, y,width,height);
2281 case RENDERPATH_D3D9:
2287 d3drect.right = x + width;
2288 d3drect.bottom = y + height;
2289 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2293 case RENDERPATH_D3D10:
2294 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2296 case RENDERPATH_D3D11:
2297 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2299 case RENDERPATH_SOFT:
2300 DPSOFTRAST_Scissor(x, y, width, height);
2305 void GL_ScissorTest(int state)
2307 if (gl_state.scissortest != state)
2309 gl_state.scissortest = state;
2310 switch(vid.renderpath)
2312 case RENDERPATH_GL11:
2313 case RENDERPATH_GL13:
2314 case RENDERPATH_GL20:
2315 case RENDERPATH_GLES1:
2316 case RENDERPATH_GLES2:
2318 if(gl_state.scissortest)
2319 qglEnable(GL_SCISSOR_TEST);
2321 qglDisable(GL_SCISSOR_TEST);
2324 case RENDERPATH_D3D9:
2326 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2329 case RENDERPATH_D3D10:
2330 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2332 case RENDERPATH_D3D11:
2333 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2335 case RENDERPATH_SOFT:
2336 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2342 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2344 static const float blackcolor[4] = {0, 0, 0, 0};
2345 // prevent warnings when trying to clear a buffer that does not exist
2347 colorvalue = blackcolor;
2350 mask &= ~GL_STENCIL_BUFFER_BIT;
2353 switch(vid.renderpath)
2355 case RENDERPATH_GL11:
2356 case RENDERPATH_GL13:
2357 case RENDERPATH_GL20:
2358 case RENDERPATH_GLES1:
2359 case RENDERPATH_GLES2:
2361 if (mask & GL_COLOR_BUFFER_BIT)
2363 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2365 if (mask & GL_DEPTH_BUFFER_BIT)
2367 qglClearDepth(depthvalue);CHECKGLERROR
2369 if (mask & GL_STENCIL_BUFFER_BIT)
2371 qglClearStencil(stencilvalue);CHECKGLERROR
2373 qglClear(mask);CHECKGLERROR
2375 case RENDERPATH_D3D9:
2377 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);
2380 case RENDERPATH_D3D10:
2381 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2383 case RENDERPATH_D3D11:
2384 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2386 case RENDERPATH_SOFT:
2387 if (mask & GL_COLOR_BUFFER_BIT)
2388 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2389 if (mask & GL_DEPTH_BUFFER_BIT)
2390 DPSOFTRAST_ClearDepth(depthvalue);
2395 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2397 switch(vid.renderpath)
2399 case RENDERPATH_GL11:
2400 case RENDERPATH_GL13:
2401 case RENDERPATH_GL20:
2402 case RENDERPATH_GLES1:
2403 case RENDERPATH_GLES2:
2405 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2407 case RENDERPATH_D3D9:
2410 // LordHavoc: we can't directly download the backbuffer because it may be
2411 // multisampled, and it may not be lockable, so we blit it to a lockable
2412 // surface of the same dimensions (but without multisample) to resolve the
2413 // multisample buffer to a normal image, and then lock that...
2414 IDirect3DSurface9 *stretchsurface = NULL;
2415 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2417 D3DLOCKED_RECT lockedrect;
2418 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2420 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2423 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2424 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2425 memcpy(outpixels + line * width * 4, row, width * 4);
2426 IDirect3DSurface9_UnlockRect(stretchsurface);
2429 IDirect3DSurface9_Release(stretchsurface);
2432 //IDirect3DSurface9 *syssurface = NULL;
2433 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2434 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2435 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2436 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2437 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2438 //IDirect3DSurface9_UnlockRect(syssurface);
2439 //IDirect3DSurface9_Release(syssurface);
2443 case RENDERPATH_D3D10:
2444 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2446 case RENDERPATH_D3D11:
2447 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2449 case RENDERPATH_SOFT:
2450 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2455 // called at beginning of frame
2456 void R_Mesh_Start(void)
2459 R_Mesh_ResetRenderTargets();
2461 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2463 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2464 Cvar_SetValueQuick(&gl_paranoid, 1);
2468 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2472 char compilelog[MAX_INPUTLINE];
2473 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2476 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2477 qglCompileShader(shaderobject);CHECKGLERROR
2478 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2479 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2480 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2482 int i, j, pretextlines = 0;
2483 for (i = 0;i < numstrings - 1;i++)
2484 for (j = 0;strings[i][j];j++)
2485 if (strings[i][j] == '\n')
2487 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2489 if (!shadercompiled)
2491 qglDeleteShader(shaderobject);CHECKGLERROR
2494 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2495 qglDeleteShader(shaderobject);CHECKGLERROR
2499 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)
2501 GLint programlinked;
2502 GLuint programobject = 0;
2503 char linklog[MAX_INPUTLINE];
2506 programobject = qglCreateProgram();CHECKGLERROR
2510 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2511 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2512 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2513 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2514 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2515 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2516 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2517 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2518 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2519 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2520 if(vid.support.gl20shaders130)
2521 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2523 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2526 #ifdef GL_GEOMETRY_SHADER
2527 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2531 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2534 qglLinkProgram(programobject);CHECKGLERROR
2535 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2536 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2539 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2540 Con_DPrintf("program link log:\n%s\n", linklog);
2541 // software vertex shader is ok but software fragment shader is WAY
2542 // too slow, fail program if so.
2543 // NOTE: this string might be ATI specific, but that's ok because the
2544 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2545 // software fragment shader due to low instruction and dependent
2547 if (strstr(linklog, "fragment shader will run in software"))
2548 programlinked = false;
2552 return programobject;
2554 qglDeleteProgram(programobject);CHECKGLERROR
2558 void GL_Backend_FreeProgram(unsigned int prog)
2561 qglDeleteProgram(prog);
2565 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2570 for (i = 0;i < count;i++)
2571 *out++ = *in++ + offset;
2574 memcpy(out, in, sizeof(*out) * count);
2577 // renders triangles using vertices from the active arrays
2578 int paranoidblah = 0;
2579 void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset)
2581 unsigned int numelements = numtriangles * 3;
2583 size_t bufferoffset3i;
2585 size_t bufferoffset3s;
2586 if (numvertices < 3 || numtriangles < 1)
2588 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2589 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);
2592 if (!gl_mesh_prefer_short_elements.integer)
2596 if (element3i_indexbuffer)
2597 element3i_indexbuffer = NULL;
2599 // adjust the pointers for firsttriangle
2601 element3i += firsttriangle * 3;
2602 if (element3i_indexbuffer)
2603 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2605 element3s += firsttriangle * 3;
2606 if (element3s_indexbuffer)
2607 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2608 switch(vid.renderpath)
2610 case RENDERPATH_GL11:
2611 case RENDERPATH_GL13:
2612 case RENDERPATH_GL20:
2613 case RENDERPATH_GLES1:
2614 case RENDERPATH_GLES2:
2615 // check if the user specified to ignore static index buffers
2616 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2618 element3i_indexbuffer = NULL;
2619 element3s_indexbuffer = NULL;
2622 case RENDERPATH_D3D9:
2623 case RENDERPATH_D3D10:
2624 case RENDERPATH_D3D11:
2626 case RENDERPATH_SOFT:
2629 // upload a dynamic index buffer if needed
2632 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2634 if (gl_state.draw_dynamicindexbuffer)
2635 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2637 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2638 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2639 element3s_bufferoffset = 0;
2644 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2646 if (gl_state.draw_dynamicindexbuffer)
2647 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2649 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2650 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2651 element3i_bufferoffset = 0;
2654 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2655 bufferoffset3i = element3i_bufferoffset;
2656 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2657 bufferoffset3s = element3s_bufferoffset;
2658 r_refdef.stats.draws++;
2659 r_refdef.stats.draws_vertices += numvertices;
2660 r_refdef.stats.draws_elements += numelements;
2661 if (gl_paranoid.integer)
2664 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2666 unsigned int j, size;
2668 // note: there's no validation done here on buffer objects because it
2669 // is somewhat difficult to get at the data, and gl_paranoid can be
2670 // used without buffer objects if the need arises
2671 // (the data could be gotten using glMapBuffer but it would be very
2672 // slow due to uncachable video memory reads)
2673 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2674 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2676 if (gl_state.pointer_vertex_pointer)
2677 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2679 if (gl_state.pointer_color_enabled)
2681 if (!qglIsEnabled(GL_COLOR_ARRAY))
2682 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2684 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2685 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2688 for (i = 0;i < vid.texarrayunits;i++)
2690 if (gl_state.units[i].arrayenabled)
2692 GL_ClientActiveTexture(i);
2693 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2694 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2696 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2697 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++)
2704 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2706 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2708 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2715 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2717 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2719 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2725 if (r_render.integer || r_refdef.draw2dstage)
2727 switch(vid.renderpath)
2729 case RENDERPATH_GL11:
2730 case RENDERPATH_GL13:
2731 case RENDERPATH_GL20:
2733 if (gl_mesh_testmanualfeeding.integer)
2735 unsigned int i, j, element;
2737 qglBegin(GL_TRIANGLES);
2738 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2741 element = element3i[i];
2743 element = element3s[i];
2745 element = firstvertex + i;
2746 for (j = 0;j < vid.texarrayunits;j++)
2748 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2750 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2752 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2753 if (vid.texarrayunits > 1)
2755 if (gl_state.units[j].pointer_texcoord_components == 4)
2756 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2757 else if (gl_state.units[j].pointer_texcoord_components == 3)
2758 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2759 else if (gl_state.units[j].pointer_texcoord_components == 2)
2760 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2762 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2766 if (gl_state.units[j].pointer_texcoord_components == 4)
2767 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2768 else if (gl_state.units[j].pointer_texcoord_components == 3)
2769 qglTexCoord3f(p[0], p[1], p[2]);
2770 else if (gl_state.units[j].pointer_texcoord_components == 2)
2771 qglTexCoord2f(p[0], p[1]);
2773 qglTexCoord1f(p[0]);
2776 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2778 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2779 if (vid.texarrayunits > 1)
2781 if (gl_state.units[j].pointer_texcoord_components == 4)
2782 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2783 else if (gl_state.units[j].pointer_texcoord_components == 3)
2784 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2785 else if (gl_state.units[j].pointer_texcoord_components == 2)
2786 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2787 else if (gl_state.units[j].pointer_texcoord_components == 1)
2788 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2792 if (gl_state.units[j].pointer_texcoord_components == 4)
2793 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2794 else if (gl_state.units[j].pointer_texcoord_components == 3)
2795 qglTexCoord3f(s[0], s[1], s[2]);
2796 else if (gl_state.units[j].pointer_texcoord_components == 2)
2797 qglTexCoord2f(s[0], s[1]);
2798 else if (gl_state.units[j].pointer_texcoord_components == 1)
2799 qglTexCoord1f(s[0]);
2802 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2804 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2805 if (vid.texarrayunits > 1)
2807 if (gl_state.units[j].pointer_texcoord_components == 4)
2808 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2809 else if (gl_state.units[j].pointer_texcoord_components == 3)
2810 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2811 else if (gl_state.units[j].pointer_texcoord_components == 2)
2812 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2813 else if (gl_state.units[j].pointer_texcoord_components == 1)
2814 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2818 if (gl_state.units[j].pointer_texcoord_components == 4)
2819 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2820 else if (gl_state.units[j].pointer_texcoord_components == 3)
2821 qglTexCoord3f(sb[0], sb[1], sb[2]);
2822 else if (gl_state.units[j].pointer_texcoord_components == 2)
2823 qglTexCoord2f(sb[0], sb[1]);
2824 else if (gl_state.units[j].pointer_texcoord_components == 1)
2825 qglTexCoord1f(sb[0]);
2830 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2832 if (gl_state.pointer_color_gltype == GL_FLOAT)
2834 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2835 qglColor4f(p[0], p[1], p[2], p[3]);
2837 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2839 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2840 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2843 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2845 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2846 if (gl_state.pointer_vertex_components == 4)
2847 qglVertex4f(p[0], p[1], p[2], p[3]);
2848 else if (gl_state.pointer_vertex_components == 3)
2849 qglVertex3f(p[0], p[1], p[2]);
2851 qglVertex2f(p[0], p[1]);
2857 else if (bufferobject3s)
2859 GL_BindEBO(bufferobject3s);
2860 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2862 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2867 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2871 else if (bufferobject3i)
2873 GL_BindEBO(bufferobject3i);
2874 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2876 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2881 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2888 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2890 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2895 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2902 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2904 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2909 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2915 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2919 case RENDERPATH_D3D9:
2921 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2923 if (element3s_indexbuffer)
2925 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2926 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2928 else if (element3i_indexbuffer)
2930 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2931 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2934 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2939 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2941 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2943 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2947 case RENDERPATH_D3D10:
2948 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2950 case RENDERPATH_D3D11:
2951 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2953 case RENDERPATH_SOFT:
2954 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2956 case RENDERPATH_GLES1:
2957 case RENDERPATH_GLES2:
2958 // GLES does not have glDrawRangeElements, and generally
2959 // underperforms with index buffers, so this code path is
2960 // relatively straightforward...
2962 if (gl_paranoid.integer)
2964 int r, prog, enabled, i;
2965 GLsizei attriblength;
2968 GLchar attribname[1024];
2969 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2970 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2971 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2972 #ifndef GL_CURRENT_PROGRAM
2973 #define GL_CURRENT_PROGRAM 0x8B8D
2975 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2976 if (r < 0 || r > 10000)
2977 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2979 for (i = 0;i < 8;i++)
2981 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2984 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2985 Con_DPrintf("prog %i position %i length %i size %04X type %i name \"%s\"\n", prog, i, (int)attriblength, (int)attribsize, (int)attribtype, (char *)attribname);
2991 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2996 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
3001 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
3009 // restores backend state, used when done with 3D rendering
3010 void R_Mesh_Finish(void)
3012 R_Mesh_ResetRenderTargets();
3015 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
3017 r_meshbuffer_t *buffer;
3018 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
3020 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
3021 memset(buffer, 0, sizeof(*buffer));
3022 buffer->bufferobject = 0;
3023 buffer->devicebuffer = NULL;
3025 buffer->isindexbuffer = isindexbuffer;
3026 buffer->isdynamic = isdynamic;
3027 buffer->isindex16 = isindex16;
3028 strlcpy(buffer->name, name, sizeof(buffer->name));
3029 R_Mesh_UpdateMeshBuffer(buffer, data, size);
3033 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
3037 if (buffer->isindexbuffer)
3039 r_refdef.stats.indexbufferuploadcount++;
3040 r_refdef.stats.indexbufferuploadsize += size;
3044 r_refdef.stats.vertexbufferuploadcount++;
3045 r_refdef.stats.vertexbufferuploadsize += size;
3047 switch(vid.renderpath)
3049 case RENDERPATH_GL11:
3050 case RENDERPATH_GL13:
3051 case RENDERPATH_GL20:
3052 case RENDERPATH_GLES1:
3053 case RENDERPATH_GLES2:
3054 if (!buffer->bufferobject)
3055 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3056 if (buffer->isindexbuffer)
3057 GL_BindEBO(buffer->bufferobject);
3059 GL_BindVBO(buffer->bufferobject);
3060 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
3062 case RENDERPATH_D3D9:
3066 void *datapointer = NULL;
3067 if (buffer->isindexbuffer)
3069 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3070 if (size > buffer->size || !buffer->devicebuffer)
3072 if (buffer->devicebuffer)
3073 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3074 buffer->devicebuffer = NULL;
3075 if (FAILED(result = IDirect3DDevice9_CreateIndexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9indexbuffer, NULL)))
3076 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);
3077 buffer->devicebuffer = (void *)d3d9indexbuffer;
3078 buffer->size = size;
3080 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3083 memcpy(datapointer, data, size);
3085 memset(datapointer, 0, size);
3086 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3091 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3092 if (size > buffer->size || !buffer->devicebuffer)
3094 if (buffer->devicebuffer)
3095 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3096 buffer->devicebuffer = NULL;
3097 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3098 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);
3099 buffer->devicebuffer = (void *)d3d9vertexbuffer;
3100 buffer->size = size;
3102 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3105 memcpy(datapointer, data, size);
3107 memset(datapointer, 0, size);
3108 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3114 case RENDERPATH_D3D10:
3115 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3117 case RENDERPATH_D3D11:
3118 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3120 case RENDERPATH_SOFT:
3125 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3129 switch(vid.renderpath)
3131 case RENDERPATH_GL11:
3132 case RENDERPATH_GL13:
3133 case RENDERPATH_GL20:
3134 case RENDERPATH_GLES1:
3135 case RENDERPATH_GLES2:
3136 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3138 case RENDERPATH_D3D9:
3140 if (gl_state.d3dvertexbuffer == (void *)buffer)
3141 gl_state.d3dvertexbuffer = NULL;
3142 if (buffer->devicebuffer)
3144 if (buffer->isindexbuffer)
3145 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3147 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3148 buffer->devicebuffer = NULL;
3152 case RENDERPATH_D3D10:
3153 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3155 case RENDERPATH_D3D11:
3156 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3158 case RENDERPATH_SOFT:
3161 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3164 void GL_Mesh_ListVBOs(qboolean printeach)
3167 size_t ebocount = 0, ebomemory = 0;
3168 size_t vbocount = 0, vbomemory = 0;
3169 r_meshbuffer_t *buffer;
3170 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3171 for (i = 0;i < endindex;i++)
3173 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3176 if (buffer->isindexbuffer) {ebocount++;ebomemory += buffer->size;if (printeach) Con_Printf("indexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
3177 else {vbocount++;vbomemory += buffer->size;if (printeach) Con_Printf("vertexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
3179 Con_Printf("vertex buffers: %i indexbuffers totalling %i bytes (%.3f MB), %i vertexbuffers totalling %i bytes (%.3f MB), combined %i bytes (%.3fMB)\n", (int)ebocount, (int)ebomemory, ebomemory / 1048576.0, (int)vbocount, (int)vbomemory, vbomemory / 1048576.0, (int)(ebomemory + vbomemory), (ebomemory + vbomemory) / 1048576.0);
3184 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3186 switch(vid.renderpath)
3188 case RENDERPATH_GL11:
3189 case RENDERPATH_GL13:
3190 case RENDERPATH_GLES1:
3191 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)
3193 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3194 gl_state.pointer_vertex_components = components;
3195 gl_state.pointer_vertex_gltype = gltype;
3196 gl_state.pointer_vertex_stride = stride;
3197 gl_state.pointer_vertex_pointer = pointer;
3198 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3199 gl_state.pointer_vertex_offset = bufferoffset;
3201 GL_BindVBO(bufferobject);
3202 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3205 case RENDERPATH_GL20:
3206 case RENDERPATH_GLES2:
3207 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)
3209 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3210 gl_state.pointer_vertex_components = components;
3211 gl_state.pointer_vertex_gltype = gltype;
3212 gl_state.pointer_vertex_stride = stride;
3213 gl_state.pointer_vertex_pointer = pointer;
3214 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3215 gl_state.pointer_vertex_offset = bufferoffset;
3217 GL_BindVBO(bufferobject);
3218 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3221 case RENDERPATH_D3D9:
3222 case RENDERPATH_D3D10:
3223 case RENDERPATH_D3D11:
3224 case RENDERPATH_SOFT:
3229 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3231 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3232 // the pointer only.
3233 switch(vid.renderpath)
3235 case RENDERPATH_GL11:
3236 case RENDERPATH_GL13:
3237 case RENDERPATH_GLES1:
3241 // caller wants color array enabled
3242 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3243 if (!gl_state.pointer_color_enabled)
3245 gl_state.pointer_color_enabled = true;
3247 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3249 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)
3251 gl_state.pointer_color_components = components;
3252 gl_state.pointer_color_gltype = gltype;
3253 gl_state.pointer_color_stride = stride;
3254 gl_state.pointer_color_pointer = pointer;
3255 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3256 gl_state.pointer_color_offset = bufferoffset;
3258 GL_BindVBO(bufferobject);
3259 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3264 // caller wants color array disabled
3265 if (gl_state.pointer_color_enabled)
3267 gl_state.pointer_color_enabled = false;
3269 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3270 // when color array is on the glColor gets trashed, set it again
3271 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3275 case RENDERPATH_GL20:
3276 case RENDERPATH_GLES2:
3280 // caller wants color array enabled
3281 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3282 if (!gl_state.pointer_color_enabled)
3284 gl_state.pointer_color_enabled = true;
3286 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3288 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)
3290 gl_state.pointer_color_components = components;
3291 gl_state.pointer_color_gltype = gltype;
3292 gl_state.pointer_color_stride = stride;
3293 gl_state.pointer_color_pointer = pointer;
3294 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3295 gl_state.pointer_color_offset = bufferoffset;
3297 GL_BindVBO(bufferobject);
3298 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3303 // caller wants color array disabled
3304 if (gl_state.pointer_color_enabled)
3306 gl_state.pointer_color_enabled = false;
3308 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3309 // when color array is on the glColor gets trashed, set it again
3310 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3314 case RENDERPATH_D3D9:
3315 case RENDERPATH_D3D10:
3316 case RENDERPATH_D3D11:
3317 case RENDERPATH_SOFT:
3322 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)
3324 gltextureunit_t *unit = gl_state.units + unitnum;
3325 // update array settings
3326 // note: there is no need to check bufferobject here because all cases
3327 // that involve a valid bufferobject also supply a texcoord array
3328 switch(vid.renderpath)
3330 case RENDERPATH_GL11:
3331 case RENDERPATH_GL13:
3332 case RENDERPATH_GLES1:
3336 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3337 // texture array unit is enabled, enable the array
3338 if (!unit->arrayenabled)
3340 unit->arrayenabled = true;
3341 GL_ClientActiveTexture(unitnum);
3342 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3345 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)
3347 unit->pointer_texcoord_components = components;
3348 unit->pointer_texcoord_gltype = gltype;
3349 unit->pointer_texcoord_stride = stride;
3350 unit->pointer_texcoord_pointer = pointer;
3351 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3352 unit->pointer_texcoord_offset = bufferoffset;
3353 GL_ClientActiveTexture(unitnum);
3354 GL_BindVBO(bufferobject);
3355 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3360 // texture array unit is disabled, disable the array
3361 if (unit->arrayenabled)
3363 unit->arrayenabled = false;
3364 GL_ClientActiveTexture(unitnum);
3365 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3369 case RENDERPATH_GL20:
3370 case RENDERPATH_GLES2:
3374 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3375 // texture array unit is enabled, enable the array
3376 if (!unit->arrayenabled)
3378 unit->arrayenabled = true;
3379 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3382 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)
3384 unit->pointer_texcoord_components = components;
3385 unit->pointer_texcoord_gltype = gltype;
3386 unit->pointer_texcoord_stride = stride;
3387 unit->pointer_texcoord_pointer = pointer;
3388 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3389 unit->pointer_texcoord_offset = bufferoffset;
3390 GL_BindVBO(bufferobject);
3391 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3396 // texture array unit is disabled, disable the array
3397 if (unit->arrayenabled)
3399 unit->arrayenabled = false;
3400 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3404 case RENDERPATH_D3D9:
3405 case RENDERPATH_D3D10:
3406 case RENDERPATH_D3D11:
3407 case RENDERPATH_SOFT:
3412 int R_Mesh_TexBound(unsigned int unitnum, int id)
3414 gltextureunit_t *unit = gl_state.units + unitnum;
3415 if (unitnum >= vid.teximageunits)
3417 if (id == GL_TEXTURE_2D)
3419 if (id == GL_TEXTURE_3D)
3421 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3422 return unit->tcubemap;
3426 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3428 switch(vid.renderpath)
3430 case RENDERPATH_GL11:
3431 case RENDERPATH_GL13:
3432 case RENDERPATH_GL20:
3433 case RENDERPATH_GLES1:
3434 case RENDERPATH_GLES2:
3435 R_Mesh_TexBind(0, tex);
3436 GL_ActiveTexture(0);CHECKGLERROR
3437 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3439 case RENDERPATH_D3D9:
3442 IDirect3DSurface9 *currentsurface = NULL;
3443 IDirect3DSurface9 *texturesurface = NULL;
3446 sourcerect.left = sx;
3447 sourcerect.top = sy;
3448 sourcerect.right = sx + width;
3449 sourcerect.bottom = sy + height;
3452 destrect.right = tx + width;
3453 destrect.bottom = ty + height;
3454 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3456 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3458 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3459 IDirect3DSurface9_Release(currentsurface);
3461 IDirect3DSurface9_Release(texturesurface);
3466 case RENDERPATH_D3D10:
3467 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3469 case RENDERPATH_D3D11:
3470 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3472 case RENDERPATH_SOFT:
3473 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3479 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};
3482 void R_Mesh_ClearBindingsForTexture(int texnum)
3484 gltextureunit_t *unit;
3485 unsigned int unitnum;
3486 // 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)
3487 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3489 unit = gl_state.units + unitnum;
3490 if (unit->t2d == texnum)
3492 if (unit->t3d == texnum)
3494 if (unit->tcubemap == texnum)
3495 unit->tcubemap = -1;
3499 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3501 gltextureunit_t *unit = gl_state.units + unitnum;
3502 int tex2d, tex3d, texcubemap, texnum;
3503 if (unitnum >= vid.teximageunits)
3505 // if (unit->texture == tex)
3507 switch(vid.renderpath)
3509 case RENDERPATH_GL20:
3510 case RENDERPATH_GLES2:
3513 tex = r_texture_white;
3514 // not initialized enough yet...
3518 unit->texture = tex;
3519 texnum = R_GetTexture(tex);
3520 switch(tex->gltexturetypeenum)
3522 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3523 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3524 case GL_TEXTURE_CUBE_MAP_ARB: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR}break;
3527 case RENDERPATH_GL11:
3528 case RENDERPATH_GL13:
3529 case RENDERPATH_GLES1:
3530 unit->texture = tex;
3536 texnum = R_GetTexture(tex);
3537 switch(tex->gltexturetypeenum)
3545 case GL_TEXTURE_CUBE_MAP_ARB:
3546 texcubemap = texnum;
3550 // update 2d texture binding
3551 if (unit->t2d != tex2d)
3553 GL_ActiveTexture(unitnum);
3558 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3565 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3569 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3571 // update 3d texture binding
3572 if (unit->t3d != tex3d)
3574 GL_ActiveTexture(unitnum);
3579 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3586 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3590 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3592 // update cubemap texture binding
3593 if (unit->tcubemap != texcubemap)
3595 GL_ActiveTexture(unitnum);
3598 if (unit->tcubemap == 0)
3600 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3607 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3610 unit->tcubemap = texcubemap;
3611 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3614 case RENDERPATH_D3D9:
3617 extern cvar_t gl_texture_anisotropy;
3620 tex = r_texture_white;
3621 // not initialized enough yet...
3625 // upload texture if needed
3627 if (unit->texture == tex)
3629 unit->texture = tex;
3630 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3631 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3632 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3633 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3634 if (tex->d3daddressw)
3635 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3636 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3637 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3638 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3639 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3640 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3641 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3645 case RENDERPATH_D3D10:
3646 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3648 case RENDERPATH_D3D11:
3649 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3651 case RENDERPATH_SOFT:
3654 tex = r_texture_white;
3655 // not initialized enough yet...
3659 texnum = R_GetTexture(tex);
3660 if (unit->texture == tex)
3662 unit->texture = tex;
3663 DPSOFTRAST_SetTexture(unitnum, texnum);
3668 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3670 gltextureunit_t *unit = gl_state.units + unitnum;
3671 switch(vid.renderpath)
3673 case RENDERPATH_GL11:
3674 case RENDERPATH_GL13:
3675 case RENDERPATH_GL20:
3676 case RENDERPATH_GLES1:
3677 case RENDERPATH_GLES2:
3678 if (matrix && matrix->m[3][3])
3680 // texmatrix specified, check if it is different
3681 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3684 unit->texmatrixenabled = true;
3685 unit->matrix = *matrix;
3687 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3688 GL_ActiveTexture(unitnum);
3689 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3690 qglLoadMatrixf(glmatrix);CHECKGLERROR
3691 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3696 // no texmatrix specified, revert to identity
3697 if (unit->texmatrixenabled)
3699 unit->texmatrixenabled = false;
3700 unit->matrix = identitymatrix;
3702 GL_ActiveTexture(unitnum);
3703 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3704 qglLoadIdentity();CHECKGLERROR
3705 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3709 case RENDERPATH_D3D9:
3710 case RENDERPATH_D3D10:
3711 case RENDERPATH_D3D11:
3713 case RENDERPATH_SOFT:
3718 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3720 gltextureunit_t *unit = gl_state.units + unitnum;
3722 switch(vid.renderpath)
3724 case RENDERPATH_GL20:
3725 case RENDERPATH_GLES2:
3728 case RENDERPATH_GL13:
3729 case RENDERPATH_GLES1:
3730 // GL_ARB_texture_env_combine
3732 combinergb = GL_MODULATE;
3734 combinealpha = GL_MODULATE;
3739 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3741 if (combinergb == GL_DECAL)
3742 combinergb = GL_INTERPOLATE_ARB;
3743 if (unit->combine != GL_COMBINE_ARB)
3745 unit->combine = GL_COMBINE_ARB;
3746 GL_ActiveTexture(unitnum);
3747 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3748 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3750 if (unit->combinergb != combinergb)
3752 unit->combinergb = combinergb;
3753 GL_ActiveTexture(unitnum);
3754 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3756 if (unit->combinealpha != combinealpha)
3758 unit->combinealpha = combinealpha;
3759 GL_ActiveTexture(unitnum);
3760 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3762 if (unit->rgbscale != rgbscale)
3764 unit->rgbscale = rgbscale;
3765 GL_ActiveTexture(unitnum);
3766 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3768 if (unit->alphascale != alphascale)
3770 unit->alphascale = alphascale;
3771 GL_ActiveTexture(unitnum);
3772 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3777 if (unit->combine != combinergb)
3779 unit->combine = combinergb;
3780 GL_ActiveTexture(unitnum);
3781 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3785 case RENDERPATH_GL11:
3788 combinergb = GL_MODULATE;
3789 if (unit->combine != combinergb)
3791 unit->combine = combinergb;
3792 GL_ActiveTexture(unitnum);
3793 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3796 case RENDERPATH_D3D9:
3797 case RENDERPATH_D3D10:
3798 case RENDERPATH_D3D11:
3800 case RENDERPATH_SOFT:
3805 void R_Mesh_ResetTextureState(void)
3807 unsigned int unitnum;
3811 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3812 R_Mesh_TexBind(unitnum, NULL);
3813 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3814 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3815 switch(vid.renderpath)
3817 case RENDERPATH_GL20:
3818 case RENDERPATH_GLES2:
3819 case RENDERPATH_D3D9:
3820 case RENDERPATH_D3D10:
3821 case RENDERPATH_D3D11:
3822 case RENDERPATH_SOFT:
3824 case RENDERPATH_GL11:
3825 case RENDERPATH_GL13:
3826 case RENDERPATH_GLES1:
3827 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3829 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3830 R_Mesh_TexMatrix(unitnum, NULL);
3839 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3840 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3841 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3843 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3845 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3849 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3851 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3852 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3853 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3857 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3859 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3860 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3861 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3862 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3863 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3864 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3865 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3869 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3870 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3871 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3874 static void R_Mesh_InitVertexDeclarations(void)
3877 r_vertex3f_d3d9decl = NULL;
3878 r_vertexgeneric_d3d9decl = NULL;
3879 r_vertexmesh_d3d9decl = NULL;
3880 switch(vid.renderpath)
3882 case RENDERPATH_GL20:
3883 case RENDERPATH_GL13:
3884 case RENDERPATH_GL11:
3885 case RENDERPATH_GLES1:
3886 case RENDERPATH_GLES2:
3888 case RENDERPATH_D3D9:
3889 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3890 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3891 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3893 case RENDERPATH_D3D10:
3894 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3896 case RENDERPATH_D3D11:
3897 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3899 case RENDERPATH_SOFT:
3905 static void R_Mesh_DestroyVertexDeclarations(void)
3908 if (r_vertex3f_d3d9decl)
3909 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3910 r_vertex3f_d3d9decl = NULL;
3911 if (r_vertexgeneric_d3d9decl)
3912 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3913 r_vertexgeneric_d3d9decl = NULL;
3914 if (r_vertexmesh_d3d9decl)
3915 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3916 r_vertexmesh_d3d9decl = NULL;
3920 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3922 // upload temporary vertexbuffer for this rendering
3923 if (!gl_state.usevbo_staticvertex)
3924 vertexbuffer = NULL;
3925 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3927 if (gl_state.preparevertices_dynamicvertexbuffer)
3928 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3930 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3931 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3933 switch(vid.renderpath)
3935 case RENDERPATH_GL20:
3936 case RENDERPATH_GLES2:
3939 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3940 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3941 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3942 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3943 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3944 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3945 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3949 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3950 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3951 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3952 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3953 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3954 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3955 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3958 case RENDERPATH_GL13:
3959 case RENDERPATH_GLES1:
3962 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3963 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3964 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3965 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3969 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3970 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3971 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3972 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3975 case RENDERPATH_GL11:
3978 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3979 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3980 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3984 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3985 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3986 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3989 case RENDERPATH_D3D9:
3991 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3993 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3995 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3996 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3997 gl_state.d3dvertexdata = (void *)vertex3f;
3998 gl_state.d3dvertexsize = sizeof(float[3]);
4001 case RENDERPATH_D3D10:
4002 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4004 case RENDERPATH_D3D11:
4005 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4007 case RENDERPATH_SOFT:
4008 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4009 DPSOFTRAST_SetColorPointer(NULL, 0);
4010 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
4011 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4012 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4013 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4014 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4021 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
4024 size = sizeof(r_vertexgeneric_t) * numvertices;
4025 if (gl_state.preparevertices_tempdatamaxsize < size)
4027 gl_state.preparevertices_tempdatamaxsize = size;
4028 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4030 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
4031 gl_state.preparevertices_numvertices = numvertices;
4032 return gl_state.preparevertices_vertexgeneric;
4035 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
4037 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4038 gl_state.preparevertices_vertexgeneric = NULL;
4039 gl_state.preparevertices_numvertices = 0;
4043 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4046 r_vertexgeneric_t *vertex;
4047 switch(vid.renderpath)
4049 case RENDERPATH_GL20:
4050 case RENDERPATH_GLES2:
4051 if (!vid.useinterleavedarrays)
4053 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4054 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4055 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4056 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4057 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4058 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4059 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4063 case RENDERPATH_GL11:
4064 case RENDERPATH_GL13:
4065 case RENDERPATH_GLES1:
4066 if (!vid.useinterleavedarrays)
4068 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4069 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4070 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4071 if (vid.texunits >= 2)
4072 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4073 if (vid.texunits >= 3)
4074 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4078 case RENDERPATH_D3D9:
4079 case RENDERPATH_D3D10:
4080 case RENDERPATH_D3D11:
4082 case RENDERPATH_SOFT:
4083 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4084 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4085 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4086 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4087 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4088 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4089 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4093 // no quick path for this case, convert to vertex structs
4094 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4095 for (i = 0;i < numvertices;i++)
4096 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4099 for (i = 0;i < numvertices;i++)
4100 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4104 for (i = 0;i < numvertices;i++)
4105 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4108 for (i = 0;i < numvertices;i++)
4109 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4110 R_Mesh_PrepareVertices_Generic_Unlock();
4111 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4114 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4116 // upload temporary vertexbuffer for this rendering
4117 if (!gl_state.usevbo_staticvertex)
4118 vertexbuffer = NULL;
4119 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4121 if (gl_state.preparevertices_dynamicvertexbuffer)
4122 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4124 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4125 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4127 switch(vid.renderpath)
4129 case RENDERPATH_GL20:
4130 case RENDERPATH_GLES2:
4133 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4134 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4135 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4136 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4137 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4138 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4139 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4143 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4144 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4145 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4146 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4147 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4148 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4149 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4152 case RENDERPATH_GL13:
4153 case RENDERPATH_GLES1:
4156 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4157 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4158 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4159 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4163 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4164 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4165 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4166 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4169 case RENDERPATH_GL11:
4172 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4173 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4174 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4178 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4179 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4180 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4183 case RENDERPATH_D3D9:
4185 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4187 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4189 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4190 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4191 gl_state.d3dvertexdata = (void *)vertex;
4192 gl_state.d3dvertexsize = sizeof(*vertex);
4195 case RENDERPATH_D3D10:
4196 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4198 case RENDERPATH_D3D11:
4199 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4201 case RENDERPATH_SOFT:
4202 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4203 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4204 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4205 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4206 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4207 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4208 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4215 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4218 size = sizeof(r_vertexmesh_t) * numvertices;
4219 if (gl_state.preparevertices_tempdatamaxsize < size)
4221 gl_state.preparevertices_tempdatamaxsize = size;
4222 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4224 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4225 gl_state.preparevertices_numvertices = numvertices;
4226 return gl_state.preparevertices_vertexmesh;
4229 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4231 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4232 gl_state.preparevertices_vertexmesh = NULL;
4233 gl_state.preparevertices_numvertices = 0;
4237 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)
4240 r_vertexmesh_t *vertex;
4241 switch(vid.renderpath)
4243 case RENDERPATH_GL20:
4244 case RENDERPATH_GLES2:
4245 if (!vid.useinterleavedarrays)
4247 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4248 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4249 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4250 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4251 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4252 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4253 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4257 case RENDERPATH_GL11:
4258 case RENDERPATH_GL13:
4259 case RENDERPATH_GLES1:
4260 if (!vid.useinterleavedarrays)
4262 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4263 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4264 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4265 if (vid.texunits >= 2)
4266 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4267 if (vid.texunits >= 3)
4268 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4272 case RENDERPATH_D3D9:
4273 case RENDERPATH_D3D10:
4274 case RENDERPATH_D3D11:
4276 case RENDERPATH_SOFT:
4277 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4278 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4279 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4280 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4281 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4282 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4283 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4287 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4288 for (i = 0;i < numvertices;i++)
4289 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4291 for (i = 0;i < numvertices;i++)
4292 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4294 for (i = 0;i < numvertices;i++)
4295 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4297 for (i = 0;i < numvertices;i++)
4298 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4301 for (i = 0;i < numvertices;i++)
4302 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4306 for (i = 0;i < numvertices;i++)
4307 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4309 if (texcoordtexture2f)
4310 for (i = 0;i < numvertices;i++)
4311 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4312 if (texcoordlightmap2f)
4313 for (i = 0;i < numvertices;i++)
4314 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4315 R_Mesh_PrepareVertices_Mesh_Unlock();
4316 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4319 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4321 // upload temporary vertexbuffer for this rendering
4322 if (!gl_state.usevbo_staticvertex)
4323 vertexbuffer = NULL;
4324 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4326 if (gl_state.preparevertices_dynamicvertexbuffer)
4327 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4329 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4330 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4332 switch(vid.renderpath)
4334 case RENDERPATH_GL20:
4335 case RENDERPATH_GLES2:
4338 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4339 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4340 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4341 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4342 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4343 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4344 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4348 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4349 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4350 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4351 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4352 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4353 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4354 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4357 case RENDERPATH_GL13:
4358 case RENDERPATH_GLES1:
4361 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4362 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4363 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4364 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4368 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4369 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4370 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4371 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4374 case RENDERPATH_GL11:
4377 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4378 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4379 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4383 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4384 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4385 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4388 case RENDERPATH_D3D9:
4390 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4392 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4394 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4395 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4396 gl_state.d3dvertexdata = (void *)vertex;
4397 gl_state.d3dvertexsize = sizeof(*vertex);
4400 case RENDERPATH_D3D10:
4401 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4403 case RENDERPATH_D3D11:
4404 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4406 case RENDERPATH_SOFT:
4407 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4408 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4409 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4410 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4411 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4412 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4413 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);