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 r_vertexbouncelight_t *preparevertices_vertexbouncelight;
173 int preparevertices_numvertices;
175 r_meshbuffer_t *draw_dynamicindexbuffer;
177 qboolean usevbo_staticvertex;
178 qboolean usevbo_staticindex;
179 qboolean usevbo_dynamicvertex;
180 qboolean usevbo_dynamicindex;
182 memexpandablearray_t meshbufferarray;
187 // rtexture_t *d3drt_depthtexture;
188 // rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
189 IDirect3DSurface9 *d3drt_depthsurface;
190 IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
191 IDirect3DSurface9 *d3drt_backbufferdepthsurface;
192 IDirect3DSurface9 *d3drt_backbuffercolorsurface;
193 void *d3dvertexbuffer;
195 size_t d3dvertexsize;
200 static gl_state_t gl_state;
204 note: here's strip order for a terrain row:
211 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
213 *elements++ = i + row;
215 *elements++ = i + row + 1;
218 *elements++ = i + row + 1;
221 for (y = 0;y < rows - 1;y++)
223 for (x = 0;x < columns - 1;x++)
226 *elements++ = i + columns;
228 *elements++ = i + columns + 1;
231 *elements++ = i + columns + 1;
242 for (y = 0;y < rows - 1;y++)
244 for (x = 0;x < columns - 1;x++)
248 *elements++ = i + columns;
249 *elements++ = i + columns + 1;
250 *elements++ = i + columns;
251 *elements++ = i + columns + 1;
257 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
258 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
259 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
260 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
262 void GL_VBOStats_f(void)
264 GL_Mesh_ListVBOs(true);
267 static void GL_Backend_ResetState(void);
269 static void R_Mesh_InitVertexDeclarations(void);
270 static void R_Mesh_DestroyVertexDeclarations(void);
272 static void R_Mesh_SetUseVBO(void)
274 switch(vid.renderpath)
276 case RENDERPATH_GL11:
277 case RENDERPATH_GL13:
278 case RENDERPATH_GL20:
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_GLES2:
330 // fetch current fbo here (default fbo is not 0 on some GLES devices)
331 if (vid.support.ext_framebuffer_object)
332 qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
334 case RENDERPATH_D3D9:
336 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
337 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
340 case RENDERPATH_D3D10:
341 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
343 case RENDERPATH_D3D11:
344 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
346 case RENDERPATH_SOFT:
351 static void gl_backend_shutdown(void)
353 Con_DPrint("OpenGL Backend shutting down\n");
355 switch(vid.renderpath)
357 case RENDERPATH_GL11:
358 case RENDERPATH_GL13:
359 case RENDERPATH_GL20:
360 case RENDERPATH_SOFT:
361 case RENDERPATH_GLES2:
363 case RENDERPATH_D3D9:
365 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
366 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
369 case RENDERPATH_D3D10:
370 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
372 case RENDERPATH_D3D11:
373 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
377 if (gl_state.preparevertices_tempdata)
378 Mem_Free(gl_state.preparevertices_tempdata);
379 if (gl_state.preparevertices_dynamicvertexbuffer)
380 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
382 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
384 R_Mesh_DestroyVertexDeclarations();
386 memset(&gl_state, 0, sizeof(gl_state));
389 static void gl_backend_newmap(void)
393 static void gl_backend_devicelost(void)
396 r_meshbuffer_t *buffer;
398 gl_state.d3dvertexbuffer = NULL;
400 switch(vid.renderpath)
402 case RENDERPATH_GL11:
403 case RENDERPATH_GL13:
404 case RENDERPATH_GL20:
405 case RENDERPATH_SOFT:
406 case RENDERPATH_GLES2:
408 case RENDERPATH_D3D9:
410 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
411 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
414 case RENDERPATH_D3D10:
415 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
417 case RENDERPATH_D3D11:
418 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
421 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
422 for (i = 0;i < endindex;i++)
424 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
425 if (!buffer || !buffer->isdynamic)
427 switch(vid.renderpath)
429 case RENDERPATH_GL11:
430 case RENDERPATH_GL13:
431 case RENDERPATH_GL20:
432 case RENDERPATH_SOFT:
433 case RENDERPATH_GLES2:
435 case RENDERPATH_D3D9:
437 if (buffer->devicebuffer)
439 if (buffer->isindexbuffer)
440 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
442 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
443 buffer->devicebuffer = NULL;
447 case RENDERPATH_D3D10:
448 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
450 case RENDERPATH_D3D11:
451 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
457 static void gl_backend_devicerestored(void)
459 switch(vid.renderpath)
461 case RENDERPATH_GL11:
462 case RENDERPATH_GL13:
463 case RENDERPATH_GL20:
464 case RENDERPATH_SOFT:
465 case RENDERPATH_GLES2:
467 case RENDERPATH_D3D9:
469 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
470 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
473 case RENDERPATH_D3D10:
474 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
476 case RENDERPATH_D3D11:
477 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
482 void gl_backend_init(void)
486 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
488 polygonelement3s[i * 3 + 0] = 0;
489 polygonelement3s[i * 3 + 1] = i + 1;
490 polygonelement3s[i * 3 + 2] = i + 2;
492 // elements for rendering a series of quads as triangles
493 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
495 quadelement3s[i * 6 + 0] = i * 4;
496 quadelement3s[i * 6 + 1] = i * 4 + 1;
497 quadelement3s[i * 6 + 2] = i * 4 + 2;
498 quadelement3s[i * 6 + 3] = i * 4;
499 quadelement3s[i * 6 + 4] = i * 4 + 2;
500 quadelement3s[i * 6 + 5] = i * 4 + 3;
503 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
504 polygonelement3i[i] = polygonelement3s[i];
505 for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
506 quadelement3i[i] = quadelement3s[i];
508 Cvar_RegisterVariable(&r_render);
509 Cvar_RegisterVariable(&r_renderview);
510 Cvar_RegisterVariable(&r_waterwarp);
511 Cvar_RegisterVariable(&gl_polyblend);
512 Cvar_RegisterVariable(&v_flipped);
513 Cvar_RegisterVariable(&gl_dither);
514 Cvar_RegisterVariable(&gl_vbo);
515 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
516 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
517 Cvar_RegisterVariable(&gl_paranoid);
518 Cvar_RegisterVariable(&gl_printcheckerror);
520 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
521 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
522 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
524 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");
526 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
529 void GL_SetMirrorState(qboolean state);
531 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
535 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
536 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
538 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
540 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
541 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
542 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
544 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
547 static int bboxedges[12][2] =
566 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
568 int i, ix1, iy1, ix2, iy2;
569 float x1, y1, x2, y2;
580 scissor[0] = r_refdef.view.viewport.x;
581 scissor[1] = r_refdef.view.viewport.y;
582 scissor[2] = r_refdef.view.viewport.width;
583 scissor[3] = r_refdef.view.viewport.height;
585 // if view is inside the box, just say yes it's visible
586 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
589 x1 = y1 = x2 = y2 = 0;
591 // transform all corners that are infront of the nearclip plane
592 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
593 plane4f[3] = r_refdef.view.frustum[4].dist;
595 for (i = 0;i < 8;i++)
597 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
598 dist[i] = DotProduct4(corner[i], plane4f);
599 sign[i] = dist[i] > 0;
602 VectorCopy(corner[i], vertex[numvertices]);
606 // if some points are behind the nearclip, add clipped edge points to make
607 // sure that the scissor boundary is complete
608 if (numvertices > 0 && numvertices < 8)
610 // add clipped edge points
611 for (i = 0;i < 12;i++)
615 if (sign[j] != sign[k])
617 f = dist[j] / (dist[j] - dist[k]);
618 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
624 // if we have no points to check, it is behind the view plane
628 // if we have some points to transform, check what screen area is covered
629 x1 = y1 = x2 = y2 = 0;
631 //Con_Printf("%i vertices to transform...\n", numvertices);
632 for (i = 0;i < numvertices;i++)
634 VectorCopy(vertex[i], v);
635 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
636 //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]);
639 if (x1 > v2[0]) x1 = v2[0];
640 if (x2 < v2[0]) x2 = v2[0];
641 if (y1 > v2[1]) y1 = v2[1];
642 if (y2 < v2[1]) y2 = v2[1];
651 // now convert the scissor rectangle to integer screen coordinates
652 ix1 = (int)(x1 - 1.0f);
653 //iy1 = vid.height - (int)(y2 - 1.0f);
654 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
655 iy1 = (int)(y1 - 1.0f);
656 ix2 = (int)(x2 + 1.0f);
657 //iy2 = vid.height - (int)(y1 + 1.0f);
658 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
659 iy2 = (int)(y2 + 1.0f);
660 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
662 // clamp it to the screen
663 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
664 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
665 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
666 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
668 // if it is inside out, it's not visible
669 if (ix2 <= ix1 || iy2 <= iy1)
672 // the light area is visible, set up the scissor rectangle
675 scissor[2] = ix2 - ix1;
676 scissor[3] = iy2 - iy1;
678 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
679 switch(vid.renderpath)
681 case RENDERPATH_D3D9:
682 case RENDERPATH_D3D10:
683 case RENDERPATH_D3D11:
684 scissor[1] = vid.height - scissor[1] - scissor[3];
686 case RENDERPATH_GL11:
687 case RENDERPATH_GL13:
688 case RENDERPATH_GL20:
689 case RENDERPATH_SOFT:
690 case RENDERPATH_GLES2:
698 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
702 float clipPlane[4], v3[3], v4[3];
705 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
707 VectorSet(normal, normalx, normaly, normalz);
708 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
709 VectorScale(normal, dist, v3);
710 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
711 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
712 clipPlane[3] = -DotProduct(v4, clipPlane);
716 // testing code for comparing results
718 VectorCopy4(clipPlane, clipPlane2);
719 R_EntityMatrix(&identitymatrix);
720 VectorSet(q, normal[0], normal[1], normal[2], -dist);
721 qglClipPlane(GL_CLIP_PLANE0, q);
722 qglGetClipPlane(GL_CLIP_PLANE0, q);
723 VectorCopy4(q, clipPlane);
727 // Calculate the clip-space corner point opposite the clipping plane
728 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
729 // transform it into camera space by multiplying it
730 // by the inverse of the projection matrix
731 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
732 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
734 q[3] = (1.0f + m[10]) / m[14];
736 // Calculate the scaled plane vector
737 d = 2.0f / DotProduct4(clipPlane, q);
739 // Replace the third row of the projection matrix
740 m[2] = clipPlane[0] * d;
741 m[6] = clipPlane[1] * d;
742 m[10] = clipPlane[2] * d + 1.0f;
743 m[14] = clipPlane[3] * d;
746 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)
748 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
750 memset(v, 0, sizeof(*v));
751 v->type = R_VIEWPORTTYPE_ORTHO;
752 v->cameramatrix = *cameramatrix;
759 memset(m, 0, sizeof(m));
760 m[0] = 2/(right - left);
761 m[5] = 2/(top - bottom);
762 m[10] = -2/(zFar - zNear);
763 m[12] = - (right + left)/(right - left);
764 m[13] = - (top + bottom)/(top - bottom);
765 m[14] = - (zFar + zNear)/(zFar - zNear);
767 switch(vid.renderpath)
769 case RENDERPATH_GL11:
770 case RENDERPATH_GL13:
771 case RENDERPATH_GL20:
772 case RENDERPATH_SOFT:
773 case RENDERPATH_GLES2:
775 case RENDERPATH_D3D9:
776 case RENDERPATH_D3D10:
777 case RENDERPATH_D3D11:
778 m[10] = -1/(zFar - zNear);
779 m[14] = -zNear/(zFar-zNear);
782 v->screentodepth[0] = -farclip / (farclip - nearclip);
783 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
785 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
788 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
790 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
796 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
797 R_Viewport_TransformToScreen(v, test1, test2);
798 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
803 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)
805 matrix4x4_t tempmatrix, basematrix;
807 memset(v, 0, sizeof(*v));
809 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
810 v->cameramatrix = *cameramatrix;
817 memset(m, 0, sizeof(m));
818 m[0] = 1.0 / frustumx;
819 m[5] = 1.0 / frustumy;
820 m[10] = -(farclip + nearclip) / (farclip - nearclip);
822 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
823 v->screentodepth[0] = -farclip / (farclip - nearclip);
824 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
826 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
827 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
828 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
829 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
832 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
834 if(v_flipped.integer)
842 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
845 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)
847 matrix4x4_t tempmatrix, basematrix;
848 const float nudge = 1.0 - 1.0 / (1<<23);
850 memset(v, 0, sizeof(*v));
852 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
853 v->cameramatrix = *cameramatrix;
860 memset(m, 0, sizeof(m));
861 m[ 0] = 1.0 / frustumx;
862 m[ 5] = 1.0 / frustumy;
865 m[14] = -2 * nearclip * nudge;
866 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
867 v->screentodepth[1] = m[14] * -0.5;
869 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
870 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
871 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
872 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
875 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
877 if(v_flipped.integer)
885 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
888 float cubeviewmatrix[6][16] =
890 // standard cubemap projections
928 float rectviewmatrix[6][16] =
930 // sign-preserving cubemap projections
969 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
971 matrix4x4_t tempmatrix, basematrix;
973 memset(v, 0, sizeof(*v));
974 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
975 v->cameramatrix = *cameramatrix;
979 memset(m, 0, sizeof(m));
981 m[10] = -(farclip + nearclip) / (farclip - nearclip);
983 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
985 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
986 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
987 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
990 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
992 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
995 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)
997 matrix4x4_t tempmatrix, basematrix;
999 memset(v, 0, sizeof(*v));
1000 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1001 v->cameramatrix = *cameramatrix;
1002 v->x = (side & 1) * size;
1003 v->y = (side >> 1) * size;
1007 memset(m, 0, sizeof(m));
1008 m[0] = m[5] = 1.0f * ((float)size - border) / size;
1009 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1011 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1013 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1014 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1015 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1017 switch(vid.renderpath)
1019 case RENDERPATH_GL20:
1020 case RENDERPATH_GL13:
1021 case RENDERPATH_GL11:
1022 case RENDERPATH_SOFT:
1023 case RENDERPATH_GLES2:
1025 case RENDERPATH_D3D9:
1028 case RENDERPATH_D3D10:
1029 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1031 case RENDERPATH_D3D11:
1032 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1037 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1039 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1042 void R_SetViewport(const r_viewport_t *v)
1047 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1048 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1050 // copy over the matrices to our state
1051 gl_viewmatrix = v->viewmatrix;
1052 gl_projectionmatrix = v->projectmatrix;
1054 switch(vid.renderpath)
1056 case RENDERPATH_GL13:
1057 case RENDERPATH_GL11:
1059 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1060 // Load the projection matrix into OpenGL
1061 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1062 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1063 qglLoadMatrixf(m);CHECKGLERROR
1064 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1066 case RENDERPATH_D3D9:
1069 D3DVIEWPORT9 d3dviewport;
1070 d3dviewport.X = gl_viewport.x;
1071 d3dviewport.Y = gl_viewport.y;
1072 d3dviewport.Width = gl_viewport.width;
1073 d3dviewport.Height = gl_viewport.height;
1074 d3dviewport.MinZ = gl_state.depthrange[0];
1075 d3dviewport.MaxZ = gl_state.depthrange[1];
1076 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1080 case RENDERPATH_D3D10:
1081 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1083 case RENDERPATH_D3D11:
1084 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1086 case RENDERPATH_SOFT:
1087 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1089 case RENDERPATH_GL20:
1090 case RENDERPATH_GLES2:
1092 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1096 // force an update of the derived matrices
1097 gl_modelmatrixchanged = true;
1098 R_EntityMatrix(&gl_modelmatrix);
1101 void R_GetViewport(r_viewport_t *v)
1106 static void GL_BindVBO(int bufferobject)
1108 if (gl_state.vertexbufferobject != bufferobject)
1110 gl_state.vertexbufferobject = bufferobject;
1112 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1116 static void GL_BindEBO(int bufferobject)
1118 if (gl_state.elementbufferobject != bufferobject)
1120 gl_state.elementbufferobject = bufferobject;
1122 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1126 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1129 switch(vid.renderpath)
1131 case RENDERPATH_GL11:
1132 case RENDERPATH_GL13:
1133 case RENDERPATH_GL20:
1134 case RENDERPATH_GLES2:
1135 if (!vid.support.ext_framebuffer_object)
1137 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1138 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1139 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1140 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1141 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1142 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1143 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1145 case RENDERPATH_D3D9:
1146 case RENDERPATH_D3D10:
1147 case RENDERPATH_D3D11:
1149 case RENDERPATH_SOFT:
1155 void R_Mesh_DestroyFramebufferObject(int fbo)
1157 switch(vid.renderpath)
1159 case RENDERPATH_GL11:
1160 case RENDERPATH_GL13:
1161 case RENDERPATH_GL20:
1162 case RENDERPATH_GLES2:
1164 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1166 case RENDERPATH_D3D9:
1167 case RENDERPATH_D3D10:
1168 case RENDERPATH_D3D11:
1170 case RENDERPATH_SOFT:
1176 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1178 // 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)
1179 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)
1182 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1183 if (gl_state.d3drt_depthsurface != depthsurface)
1185 gl_state.d3drt_depthsurface = depthsurface;
1186 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1188 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1190 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1191 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1193 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1195 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1196 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1198 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1200 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1201 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1203 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1205 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1206 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1211 void R_Mesh_ResetRenderTargets(void)
1213 switch(vid.renderpath)
1215 case RENDERPATH_GL11:
1216 case RENDERPATH_GL13:
1217 case RENDERPATH_GL20:
1218 case RENDERPATH_GLES2:
1219 if (gl_state.framebufferobject)
1221 gl_state.framebufferobject = 0;
1222 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1225 case RENDERPATH_D3D9:
1227 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1230 case RENDERPATH_D3D10:
1231 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1233 case RENDERPATH_D3D11:
1234 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1236 case RENDERPATH_SOFT:
1237 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1242 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1246 rtexture_t *textures[5];
1247 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1248 textures[4] = depthtexture;
1249 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1250 for (j = 0;j < 5;j++)
1252 for (i = 0;i < vid.teximageunits;i++)
1253 if (gl_state.units[i].texture == textures[j])
1254 R_Mesh_TexBind(i, NULL);
1255 // set up framebuffer object or render targets for the active rendering API
1256 switch(vid.renderpath)
1258 case RENDERPATH_GL11:
1259 case RENDERPATH_GL13:
1260 case RENDERPATH_GL20:
1261 case RENDERPATH_GLES2:
1262 if (gl_state.framebufferobject != fbo)
1264 gl_state.framebufferobject = fbo;
1265 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1268 case RENDERPATH_D3D9:
1270 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1271 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1274 IDirect3DSurface9 *colorsurfaces[4];
1275 for (i = 0;i < 4;i++)
1277 colorsurfaces[i] = NULL;
1279 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1281 // set the render targets for real
1282 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1283 // release the texture surface levels (they won't be lost while bound...)
1284 for (i = 0;i < 4;i++)
1286 IDirect3DSurface9_Release(colorsurfaces[i]);
1289 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1292 case RENDERPATH_D3D10:
1293 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1295 case RENDERPATH_D3D11:
1296 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1298 case RENDERPATH_SOFT:
1302 unsigned int *pointers[5];
1303 memset(pointers, 0, sizeof(pointers));
1304 for (i = 0;i < 5;i++)
1305 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1306 width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1307 height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1308 DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1311 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1317 static int d3dcmpforglfunc(int f)
1321 case GL_NEVER: return D3DCMP_NEVER;
1322 case GL_LESS: return D3DCMP_LESS;
1323 case GL_EQUAL: return D3DCMP_EQUAL;
1324 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1325 case GL_GREATER: return D3DCMP_GREATER;
1326 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1327 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1328 case GL_ALWAYS: return D3DCMP_ALWAYS;
1329 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1333 static int d3dstencilopforglfunc(int f)
1337 case GL_KEEP: return D3DSTENCILOP_KEEP;
1338 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1339 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1340 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1346 static void GL_Backend_ResetState(void)
1349 gl_state.active = true;
1350 gl_state.depthtest = true;
1351 gl_state.alphatest = false;
1352 gl_state.alphafunc = GL_GEQUAL;
1353 gl_state.alphafuncvalue = 0.5f;
1354 gl_state.blendfunc1 = GL_ONE;
1355 gl_state.blendfunc2 = GL_ZERO;
1356 gl_state.blend = false;
1357 gl_state.depthmask = GL_TRUE;
1358 gl_state.colormask = 15;
1359 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1360 gl_state.lockrange_first = 0;
1361 gl_state.lockrange_count = 0;
1362 gl_state.cullface = GL_FRONT;
1363 gl_state.cullfaceenable = false;
1364 gl_state.polygonoffset[0] = 0;
1365 gl_state.polygonoffset[1] = 0;
1366 gl_state.framebufferobject = 0;
1367 gl_state.depthfunc = GL_LEQUAL;
1369 switch(vid.renderpath)
1371 case RENDERPATH_D3D9:
1374 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1375 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1376 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1377 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1378 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1379 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1380 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1381 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1382 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1383 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1387 case RENDERPATH_D3D10:
1388 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1390 case RENDERPATH_D3D11:
1391 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1393 case RENDERPATH_GL13:
1394 case RENDERPATH_GL11:
1397 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1398 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1399 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1400 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1401 qglDisable(GL_BLEND);CHECKGLERROR
1402 qglCullFace(gl_state.cullface);CHECKGLERROR
1403 qglDisable(GL_CULL_FACE);CHECKGLERROR
1404 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1405 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1406 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1407 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1409 if (vid.support.arb_vertex_buffer_object)
1411 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1412 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1415 if (vid.support.ext_framebuffer_object)
1417 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1418 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1421 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1422 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1424 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1425 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1426 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1428 if (vid.support.ext_framebuffer_object)
1429 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1431 gl_state.unit = MAX_TEXTUREUNITS;
1432 gl_state.clientunit = MAX_TEXTUREUNITS;
1433 for (i = 0;i < vid.texunits;i++)
1435 GL_ActiveTexture(i);
1436 GL_ClientActiveTexture(i);
1437 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1438 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1439 if (vid.support.ext_texture_3d)
1441 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1442 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1444 if (vid.support.arb_texture_cube_map)
1446 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1447 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1450 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1451 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1452 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1453 qglLoadIdentity();CHECKGLERROR
1454 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1455 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1459 case RENDERPATH_SOFT:
1460 DPSOFTRAST_ColorMask(1,1,1,1);
1461 DPSOFTRAST_AlphaTest(gl_state.alphatest);
1462 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1463 DPSOFTRAST_CullFace(gl_state.cullface);
1464 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1465 DPSOFTRAST_DepthMask(gl_state.depthmask);
1466 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1467 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1468 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1470 case RENDERPATH_GL20:
1471 case RENDERPATH_GLES2:
1473 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1474 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1475 qglDisable(GL_BLEND);CHECKGLERROR
1476 qglCullFace(gl_state.cullface);CHECKGLERROR
1477 qglDisable(GL_CULL_FACE);CHECKGLERROR
1478 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1479 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1480 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1481 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1482 // if (vid.renderpath == RENDERPATH_GL20)
1484 // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1485 // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1487 if (vid.support.arb_vertex_buffer_object)
1489 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1490 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1492 if (vid.support.ext_framebuffer_object)
1493 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1494 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1495 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1496 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1497 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1498 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1499 gl_state.unit = MAX_TEXTUREUNITS;
1500 gl_state.clientunit = MAX_TEXTUREUNITS;
1501 for (i = 0;i < vid.teximageunits;i++)
1503 GL_ActiveTexture(i);
1504 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1505 if (vid.support.ext_texture_3d)
1507 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1509 if (vid.support.arb_texture_cube_map)
1511 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1514 for (i = 0;i < vid.texarrayunits;i++)
1517 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1518 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1525 void GL_ActiveTexture(unsigned int num)
1527 if (gl_state.unit != num)
1529 gl_state.unit = num;
1530 switch(vid.renderpath)
1532 case RENDERPATH_GL11:
1533 case RENDERPATH_GL13:
1534 case RENDERPATH_GL20:
1535 case RENDERPATH_GLES2:
1536 if (qglActiveTexture)
1539 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1543 case RENDERPATH_D3D9:
1544 case RENDERPATH_D3D10:
1545 case RENDERPATH_D3D11:
1547 case RENDERPATH_SOFT:
1553 void GL_ClientActiveTexture(unsigned int num)
1555 if (gl_state.clientunit != num)
1557 gl_state.clientunit = num;
1558 switch(vid.renderpath)
1560 case RENDERPATH_GL11:
1561 case RENDERPATH_GL13:
1562 if (qglActiveTexture)
1565 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1569 case RENDERPATH_D3D9:
1570 case RENDERPATH_D3D10:
1571 case RENDERPATH_D3D11:
1573 case RENDERPATH_SOFT:
1575 case RENDERPATH_GL20:
1576 case RENDERPATH_GLES2:
1582 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1584 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1586 qboolean blendenable;
1587 gl_state.blendfunc1 = blendfunc1;
1588 gl_state.blendfunc2 = blendfunc2;
1589 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1590 switch(vid.renderpath)
1592 case RENDERPATH_GL11:
1593 case RENDERPATH_GL13:
1594 case RENDERPATH_GL20:
1595 case RENDERPATH_GLES2:
1597 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1598 if (gl_state.blend != blendenable)
1600 gl_state.blend = blendenable;
1601 if (!gl_state.blend)
1603 qglDisable(GL_BLEND);CHECKGLERROR
1607 qglEnable(GL_BLEND);CHECKGLERROR
1611 case RENDERPATH_D3D9:
1616 D3DBLEND d3dblendfunc[2];
1617 glblendfunc[0] = gl_state.blendfunc1;
1618 glblendfunc[1] = gl_state.blendfunc2;
1619 for (i = 0;i < 2;i++)
1621 switch(glblendfunc[i])
1623 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1624 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1625 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1626 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1627 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1628 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1629 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1630 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1631 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1632 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1635 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1636 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1637 if (gl_state.blend != blendenable)
1639 gl_state.blend = blendenable;
1640 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1645 case RENDERPATH_D3D10:
1646 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1648 case RENDERPATH_D3D11:
1649 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1651 case RENDERPATH_SOFT:
1652 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1658 void GL_DepthMask(int state)
1660 if (gl_state.depthmask != state)
1662 gl_state.depthmask = state;
1663 switch(vid.renderpath)
1665 case RENDERPATH_GL11:
1666 case RENDERPATH_GL13:
1667 case RENDERPATH_GL20:
1668 case RENDERPATH_GLES2:
1670 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1672 case RENDERPATH_D3D9:
1674 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1677 case RENDERPATH_D3D10:
1678 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1680 case RENDERPATH_D3D11:
1681 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1683 case RENDERPATH_SOFT:
1684 DPSOFTRAST_DepthMask(gl_state.depthmask);
1690 void GL_DepthTest(int state)
1692 if (gl_state.depthtest != state)
1694 gl_state.depthtest = state;
1695 switch(vid.renderpath)
1697 case RENDERPATH_GL11:
1698 case RENDERPATH_GL13:
1699 case RENDERPATH_GL20:
1700 case RENDERPATH_GLES2:
1702 if (gl_state.depthtest)
1704 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1708 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1711 case RENDERPATH_D3D9:
1713 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1716 case RENDERPATH_D3D10:
1717 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1719 case RENDERPATH_D3D11:
1720 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1722 case RENDERPATH_SOFT:
1723 DPSOFTRAST_DepthTest(gl_state.depthtest);
1729 void GL_DepthFunc(int state)
1731 if (gl_state.depthfunc != state)
1733 gl_state.depthfunc = state;
1734 switch(vid.renderpath)
1736 case RENDERPATH_GL11:
1737 case RENDERPATH_GL13:
1738 case RENDERPATH_GL20:
1739 case RENDERPATH_GLES2:
1741 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1743 case RENDERPATH_D3D9:
1745 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1748 case RENDERPATH_D3D10:
1749 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1751 case RENDERPATH_D3D11:
1752 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1754 case RENDERPATH_SOFT:
1755 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1761 void GL_DepthRange(float nearfrac, float farfrac)
1763 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1765 gl_state.depthrange[0] = nearfrac;
1766 gl_state.depthrange[1] = farfrac;
1767 switch(vid.renderpath)
1769 case RENDERPATH_GL11:
1770 case RENDERPATH_GL13:
1771 case RENDERPATH_GL20:
1772 case RENDERPATH_GLES2:
1773 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1775 case RENDERPATH_D3D9:
1778 D3DVIEWPORT9 d3dviewport;
1779 d3dviewport.X = gl_viewport.x;
1780 d3dviewport.Y = gl_viewport.y;
1781 d3dviewport.Width = gl_viewport.width;
1782 d3dviewport.Height = gl_viewport.height;
1783 d3dviewport.MinZ = gl_state.depthrange[0];
1784 d3dviewport.MaxZ = gl_state.depthrange[1];
1785 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1789 case RENDERPATH_D3D10:
1790 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1792 case RENDERPATH_D3D11:
1793 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1795 case RENDERPATH_SOFT:
1796 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1802 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)
1804 switch (vid.renderpath)
1806 case RENDERPATH_GL11:
1807 case RENDERPATH_GL13:
1808 case RENDERPATH_GL20:
1809 case RENDERPATH_GLES2:
1813 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1817 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1819 if (vid.support.ati_separate_stencil)
1821 qglStencilMask(writemask);CHECKGLERROR
1822 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1823 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1824 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1826 else if (vid.support.ext_stencil_two_side)
1828 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1829 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1830 qglStencilMask(writemask);CHECKGLERROR
1831 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1832 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1833 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1834 qglStencilMask(writemask);CHECKGLERROR
1835 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1836 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1839 case RENDERPATH_D3D9:
1841 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1842 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1843 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1844 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1845 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1846 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1847 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1848 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1849 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1850 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1851 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1852 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1853 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1856 case RENDERPATH_D3D10:
1857 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1859 case RENDERPATH_D3D11:
1860 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1862 case RENDERPATH_SOFT:
1863 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1868 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1870 switch (vid.renderpath)
1872 case RENDERPATH_GL11:
1873 case RENDERPATH_GL13:
1874 case RENDERPATH_GL20:
1875 case RENDERPATH_GLES2:
1879 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1883 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1885 if (vid.support.ext_stencil_two_side)
1887 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1889 qglStencilMask(writemask);CHECKGLERROR
1890 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1891 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1894 case RENDERPATH_D3D9:
1896 if (vid.support.ati_separate_stencil)
1897 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1898 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1899 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1900 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1901 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1902 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1903 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1904 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1905 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1908 case RENDERPATH_D3D10:
1909 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1911 case RENDERPATH_D3D11:
1912 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1914 case RENDERPATH_SOFT:
1915 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920 void GL_PolygonOffset(float planeoffset, float depthoffset)
1922 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1924 gl_state.polygonoffset[0] = planeoffset;
1925 gl_state.polygonoffset[1] = depthoffset;
1926 switch(vid.renderpath)
1928 case RENDERPATH_GL11:
1929 case RENDERPATH_GL13:
1930 case RENDERPATH_GL20:
1931 case RENDERPATH_GLES2:
1932 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1934 case RENDERPATH_D3D9:
1936 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1937 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1940 case RENDERPATH_D3D10:
1941 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1943 case RENDERPATH_D3D11:
1944 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1946 case RENDERPATH_SOFT:
1947 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1953 void GL_SetMirrorState(qboolean state)
1955 if (v_flipped_state != state)
1957 v_flipped_state = state;
1958 if (gl_state.cullface == GL_BACK)
1959 gl_state.cullface = GL_FRONT;
1960 else if (gl_state.cullface == GL_FRONT)
1961 gl_state.cullface = GL_BACK;
1964 switch(vid.renderpath)
1966 case RENDERPATH_GL11:
1967 case RENDERPATH_GL13:
1968 case RENDERPATH_GL20:
1969 case RENDERPATH_GLES2:
1970 qglCullFace(gl_state.cullface);CHECKGLERROR
1972 case RENDERPATH_D3D9:
1974 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
1977 case RENDERPATH_D3D10:
1978 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1980 case RENDERPATH_D3D11:
1981 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1983 case RENDERPATH_SOFT:
1984 DPSOFTRAST_CullFace(gl_state.cullface);
1990 void GL_CullFace(int state)
1994 if(state == GL_FRONT)
1996 else if(state == GL_BACK)
2000 switch(vid.renderpath)
2002 case RENDERPATH_GL11:
2003 case RENDERPATH_GL13:
2004 case RENDERPATH_GL20:
2005 case RENDERPATH_GLES2:
2008 if (state != GL_NONE)
2010 if (!gl_state.cullfaceenable)
2012 gl_state.cullfaceenable = true;
2013 qglEnable(GL_CULL_FACE);CHECKGLERROR
2015 if (gl_state.cullface != state)
2017 gl_state.cullface = state;
2018 qglCullFace(gl_state.cullface);CHECKGLERROR
2023 if (gl_state.cullfaceenable)
2025 gl_state.cullfaceenable = false;
2026 qglDisable(GL_CULL_FACE);CHECKGLERROR
2030 case RENDERPATH_D3D9:
2032 if (gl_state.cullface != state)
2034 gl_state.cullface = state;
2035 switch(gl_state.cullface)
2038 gl_state.cullfaceenable = false;
2039 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2042 gl_state.cullfaceenable = true;
2043 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2046 gl_state.cullfaceenable = true;
2047 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2053 case RENDERPATH_D3D10:
2054 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056 case RENDERPATH_D3D11:
2057 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2059 case RENDERPATH_SOFT:
2060 if (gl_state.cullface != state)
2062 gl_state.cullface = state;
2063 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2064 DPSOFTRAST_CullFace(gl_state.cullface);
2070 void GL_AlphaTest(int state)
2072 if (gl_state.alphatest != state)
2074 gl_state.alphatest = state;
2075 switch(vid.renderpath)
2077 case RENDERPATH_GL11:
2078 case RENDERPATH_GL13:
2079 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2081 if (gl_state.alphatest)
2083 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2087 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2090 case RENDERPATH_D3D9:
2092 // IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2095 case RENDERPATH_D3D10:
2097 case RENDERPATH_D3D11:
2099 case RENDERPATH_SOFT:
2100 // DPSOFTRAST_AlphaTest(gl_state.alphatest);
2102 case RENDERPATH_GL20:
2103 case RENDERPATH_GLES2:
2109 void GL_ColorMask(int r, int g, int b, int a)
2111 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2112 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2113 if (gl_state.colormask != state)
2115 gl_state.colormask = state;
2116 switch(vid.renderpath)
2118 case RENDERPATH_GL11:
2119 case RENDERPATH_GL13:
2120 case RENDERPATH_GL20:
2121 case RENDERPATH_GLES2:
2123 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2125 case RENDERPATH_D3D9:
2127 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2130 case RENDERPATH_D3D10:
2131 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2133 case RENDERPATH_D3D11:
2134 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2136 case RENDERPATH_SOFT:
2137 DPSOFTRAST_ColorMask(r, g, b, a);
2143 void GL_Color(float cr, float cg, float cb, float ca)
2145 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)
2147 gl_state.color4f[0] = cr;
2148 gl_state.color4f[1] = cg;
2149 gl_state.color4f[2] = cb;
2150 gl_state.color4f[3] = ca;
2151 switch(vid.renderpath)
2153 case RENDERPATH_GL11:
2154 case RENDERPATH_GL13:
2156 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2159 case RENDERPATH_D3D9:
2160 case RENDERPATH_D3D10:
2161 case RENDERPATH_D3D11:
2162 // no equivalent in D3D
2164 case RENDERPATH_SOFT:
2165 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2167 case RENDERPATH_GL20:
2168 case RENDERPATH_GLES2:
2169 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2175 void GL_Scissor (int x, int y, int width, int height)
2177 switch(vid.renderpath)
2179 case RENDERPATH_GL11:
2180 case RENDERPATH_GL13:
2181 case RENDERPATH_GL20:
2182 case RENDERPATH_GLES2:
2184 qglScissor(x, y,width,height);
2187 case RENDERPATH_D3D9:
2193 d3drect.right = x + width;
2194 d3drect.bottom = y + height;
2195 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2199 case RENDERPATH_D3D10:
2200 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2202 case RENDERPATH_D3D11:
2203 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2205 case RENDERPATH_SOFT:
2206 DPSOFTRAST_Scissor(x, y, width, height);
2211 void GL_ScissorTest(int state)
2213 if (gl_state.scissortest != state)
2215 gl_state.scissortest = state;
2216 switch(vid.renderpath)
2218 case RENDERPATH_GL11:
2219 case RENDERPATH_GL13:
2220 case RENDERPATH_GL20:
2221 case RENDERPATH_GLES2:
2223 if(gl_state.scissortest)
2224 qglEnable(GL_SCISSOR_TEST);
2226 qglDisable(GL_SCISSOR_TEST);
2229 case RENDERPATH_D3D9:
2231 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2234 case RENDERPATH_D3D10:
2235 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2237 case RENDERPATH_D3D11:
2238 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2240 case RENDERPATH_SOFT:
2241 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2247 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2249 static const float blackcolor[4] = {0, 0, 0, 0};
2250 // prevent warnings when trying to clear a buffer that does not exist
2252 colorvalue = blackcolor;
2255 mask &= ~GL_STENCIL_BUFFER_BIT;
2258 switch(vid.renderpath)
2260 case RENDERPATH_GL11:
2261 case RENDERPATH_GL13:
2262 case RENDERPATH_GL20:
2263 case RENDERPATH_GLES2:
2265 if (mask & GL_COLOR_BUFFER_BIT)
2267 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2269 if (mask & GL_DEPTH_BUFFER_BIT)
2271 qglClearDepth(depthvalue);CHECKGLERROR
2273 if (mask & GL_STENCIL_BUFFER_BIT)
2275 qglClearStencil(stencilvalue);CHECKGLERROR
2277 qglClear(mask);CHECKGLERROR
2279 case RENDERPATH_D3D9:
2281 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);
2284 case RENDERPATH_D3D10:
2285 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2287 case RENDERPATH_D3D11:
2288 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2290 case RENDERPATH_SOFT:
2291 if (mask & GL_COLOR_BUFFER_BIT)
2292 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2293 if (mask & GL_DEPTH_BUFFER_BIT)
2294 DPSOFTRAST_ClearDepth(depthvalue);
2299 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2301 switch(vid.renderpath)
2303 case RENDERPATH_GL11:
2304 case RENDERPATH_GL13:
2305 case RENDERPATH_GL20:
2306 case RENDERPATH_GLES2:
2308 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2310 case RENDERPATH_D3D9:
2313 // LordHavoc: we can't directly download the backbuffer because it may be
2314 // multisampled, and it may not be lockable, so we blit it to a lockable
2315 // surface of the same dimensions (but without multisample) to resolve the
2316 // multisample buffer to a normal image, and then lock that...
2317 IDirect3DSurface9 *stretchsurface = NULL;
2318 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2320 D3DLOCKED_RECT lockedrect;
2321 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2323 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2326 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2327 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2328 memcpy(outpixels + line * width * 4, row, width * 4);
2329 IDirect3DSurface9_UnlockRect(stretchsurface);
2332 IDirect3DSurface9_Release(stretchsurface);
2335 //IDirect3DSurface9 *syssurface = NULL;
2336 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2337 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2338 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2339 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2340 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2341 //IDirect3DSurface9_UnlockRect(syssurface);
2342 //IDirect3DSurface9_Release(syssurface);
2346 case RENDERPATH_D3D10:
2347 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2349 case RENDERPATH_D3D11:
2350 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2352 case RENDERPATH_SOFT:
2353 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2358 // called at beginning of frame
2359 void R_Mesh_Start(void)
2362 R_Mesh_ResetRenderTargets();
2364 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2366 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2367 Cvar_SetValueQuick(&gl_paranoid, 1);
2371 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2375 char compilelog[MAX_INPUTLINE];
2376 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2379 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2380 qglCompileShader(shaderobject);CHECKGLERROR
2381 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2382 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2383 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2385 int i, j, pretextlines = 0;
2386 for (i = 0;i < numstrings - 1;i++)
2387 for (j = 0;strings[i][j];j++)
2388 if (strings[i][j] == '\n')
2390 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2392 if (!shadercompiled)
2394 qglDeleteShader(shaderobject);CHECKGLERROR
2397 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2398 qglDeleteShader(shaderobject);CHECKGLERROR
2402 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)
2404 GLint programlinked;
2405 GLuint programobject = 0;
2406 char linklog[MAX_INPUTLINE];
2409 programobject = qglCreateProgram();CHECKGLERROR
2413 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2414 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2415 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2416 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2417 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2418 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2419 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2420 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2421 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2422 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2424 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2427 #ifdef GL_GEOMETRY_SHADER
2428 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2432 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2435 qglLinkProgram(programobject);CHECKGLERROR
2436 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2437 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2440 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2441 Con_DPrintf("program link log:\n%s\n", linklog);
2442 // software vertex shader is ok but software fragment shader is WAY
2443 // too slow, fail program if so.
2444 // NOTE: this string might be ATI specific, but that's ok because the
2445 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2446 // software fragment shader due to low instruction and dependent
2448 if (strstr(linklog, "fragment shader will run in software"))
2449 programlinked = false;
2453 return programobject;
2455 qglDeleteProgram(programobject);CHECKGLERROR
2459 void GL_Backend_FreeProgram(unsigned int prog)
2462 qglDeleteProgram(prog);
2466 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2471 for (i = 0;i < count;i++)
2472 *out++ = *in++ + offset;
2475 memcpy(out, in, sizeof(*out) * count);
2478 // renders triangles using vertices from the active arrays
2479 int paranoidblah = 0;
2480 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)
2482 unsigned int numelements = numtriangles * 3;
2484 size_t bufferoffset3i;
2486 size_t bufferoffset3s;
2487 if (numvertices < 3 || numtriangles < 1)
2489 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2490 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);
2493 if (!gl_mesh_prefer_short_elements.integer)
2497 if (element3i_indexbuffer)
2498 element3i_indexbuffer = NULL;
2500 // adjust the pointers for firsttriangle
2502 element3i += firsttriangle * 3;
2503 if (element3i_indexbuffer)
2504 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2506 element3s += firsttriangle * 3;
2507 if (element3s_indexbuffer)
2508 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2509 switch(vid.renderpath)
2511 case RENDERPATH_GL11:
2512 case RENDERPATH_GL13:
2513 case RENDERPATH_GL20:
2514 case RENDERPATH_GLES2:
2515 // check if the user specified to ignore static index buffers
2516 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2518 element3i_indexbuffer = NULL;
2519 element3s_indexbuffer = NULL;
2522 case RENDERPATH_D3D9:
2523 case RENDERPATH_D3D10:
2524 case RENDERPATH_D3D11:
2526 case RENDERPATH_SOFT:
2529 // upload a dynamic index buffer if needed
2532 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2534 if (gl_state.draw_dynamicindexbuffer)
2535 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2537 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2538 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2539 element3s_bufferoffset = 0;
2544 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2546 if (gl_state.draw_dynamicindexbuffer)
2547 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2549 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2550 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2551 element3i_bufferoffset = 0;
2554 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2555 bufferoffset3i = element3i_bufferoffset;
2556 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2557 bufferoffset3s = element3s_bufferoffset;
2558 r_refdef.stats.draws++;
2559 r_refdef.stats.draws_vertices += numvertices;
2560 r_refdef.stats.draws_elements += numelements;
2561 if (gl_paranoid.integer)
2564 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2566 unsigned int j, size;
2568 // note: there's no validation done here on buffer objects because it
2569 // is somewhat difficult to get at the data, and gl_paranoid can be
2570 // used without buffer objects if the need arises
2571 // (the data could be gotten using glMapBuffer but it would be very
2572 // slow due to uncachable video memory reads)
2573 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2574 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2576 if (gl_state.pointer_vertex_pointer)
2577 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2579 if (gl_state.pointer_color_enabled)
2581 if (!qglIsEnabled(GL_COLOR_ARRAY))
2582 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2584 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2585 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2588 for (i = 0;i < vid.texarrayunits;i++)
2590 if (gl_state.units[i].arrayenabled)
2592 GL_ClientActiveTexture(i);
2593 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2594 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2596 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2597 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++)
2604 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2606 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2608 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2615 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2617 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2619 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2625 if (r_render.integer || r_refdef.draw2dstage)
2627 switch(vid.renderpath)
2629 case RENDERPATH_GL11:
2630 case RENDERPATH_GL13:
2631 case RENDERPATH_GL20:
2633 if (gl_mesh_testmanualfeeding.integer)
2635 unsigned int i, j, element;
2637 qglBegin(GL_TRIANGLES);
2638 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2641 element = element3i[i];
2643 element = element3s[i];
2645 element = firstvertex + i;
2646 for (j = 0;j < vid.texarrayunits;j++)
2648 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2650 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2652 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2653 if (vid.texarrayunits > 1)
2655 if (gl_state.units[j].pointer_texcoord_components == 4)
2656 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2657 else if (gl_state.units[j].pointer_texcoord_components == 3)
2658 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2659 else if (gl_state.units[j].pointer_texcoord_components == 2)
2660 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2662 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2666 if (gl_state.units[j].pointer_texcoord_components == 4)
2667 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2668 else if (gl_state.units[j].pointer_texcoord_components == 3)
2669 qglTexCoord3f(p[0], p[1], p[2]);
2670 else if (gl_state.units[j].pointer_texcoord_components == 2)
2671 qglTexCoord2f(p[0], p[1]);
2673 qglTexCoord1f(p[0]);
2676 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2678 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2679 if (vid.texarrayunits > 1)
2681 if (gl_state.units[j].pointer_texcoord_components == 4)
2682 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2683 else if (gl_state.units[j].pointer_texcoord_components == 3)
2684 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2685 else if (gl_state.units[j].pointer_texcoord_components == 2)
2686 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2687 else if (gl_state.units[j].pointer_texcoord_components == 1)
2688 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2692 if (gl_state.units[j].pointer_texcoord_components == 4)
2693 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2694 else if (gl_state.units[j].pointer_texcoord_components == 3)
2695 qglTexCoord3f(s[0], s[1], s[2]);
2696 else if (gl_state.units[j].pointer_texcoord_components == 2)
2697 qglTexCoord2f(s[0], s[1]);
2698 else if (gl_state.units[j].pointer_texcoord_components == 1)
2699 qglTexCoord1f(s[0]);
2702 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2704 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2705 if (vid.texarrayunits > 1)
2707 if (gl_state.units[j].pointer_texcoord_components == 4)
2708 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2709 else if (gl_state.units[j].pointer_texcoord_components == 3)
2710 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2711 else if (gl_state.units[j].pointer_texcoord_components == 2)
2712 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2713 else if (gl_state.units[j].pointer_texcoord_components == 1)
2714 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2718 if (gl_state.units[j].pointer_texcoord_components == 4)
2719 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2720 else if (gl_state.units[j].pointer_texcoord_components == 3)
2721 qglTexCoord3f(sb[0], sb[1], sb[2]);
2722 else if (gl_state.units[j].pointer_texcoord_components == 2)
2723 qglTexCoord2f(sb[0], sb[1]);
2724 else if (gl_state.units[j].pointer_texcoord_components == 1)
2725 qglTexCoord1f(sb[0]);
2730 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2732 if (gl_state.pointer_color_gltype == GL_FLOAT)
2734 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2735 qglColor4f(p[0], p[1], p[2], p[3]);
2737 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2739 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2740 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2743 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2745 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2746 if (gl_state.pointer_vertex_components == 4)
2747 qglVertex4f(p[0], p[1], p[2], p[3]);
2748 else if (gl_state.pointer_vertex_components == 3)
2749 qglVertex3f(p[0], p[1], p[2]);
2751 qglVertex2f(p[0], p[1]);
2757 else if (bufferobject3s)
2759 GL_BindEBO(bufferobject3s);
2760 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2762 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2767 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2771 else if (bufferobject3i)
2773 GL_BindEBO(bufferobject3i);
2774 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2776 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2781 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2788 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2790 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2795 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2802 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2804 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2809 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2815 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2819 case RENDERPATH_D3D9:
2821 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2823 if (element3s_indexbuffer)
2825 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2826 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2828 else if (element3i_indexbuffer)
2830 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2831 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2834 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2839 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2841 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2843 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2847 case RENDERPATH_D3D10:
2848 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2850 case RENDERPATH_D3D11:
2851 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2853 case RENDERPATH_SOFT:
2854 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2856 case RENDERPATH_GLES2:
2857 // GLES does not have glDrawRangeElements, and generally
2858 // underperforms with index buffers, so this code path is
2859 // relatively straightforward...
2861 if (gl_paranoid.integer)
2863 int r, prog, enabled, i;
2864 GLsizei attriblength;
2867 GLchar attribname[1024];
2868 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2869 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2870 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2871 #ifndef GL_CURRENT_PROGRAM
2872 #define GL_CURRENT_PROGRAM 0x8B8D
2874 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2875 if (r < 0 || r > 10000)
2876 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2878 for (i = 0;i < 8;i++)
2880 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2883 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2884 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);
2890 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2895 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2900 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2908 // restores backend state, used when done with 3D rendering
2909 void R_Mesh_Finish(void)
2911 R_Mesh_ResetRenderTargets();
2914 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2916 r_meshbuffer_t *buffer;
2917 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2919 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2920 memset(buffer, 0, sizeof(*buffer));
2921 buffer->bufferobject = 0;
2922 buffer->devicebuffer = NULL;
2924 buffer->isindexbuffer = isindexbuffer;
2925 buffer->isdynamic = isdynamic;
2926 buffer->isindex16 = isindex16;
2927 strlcpy(buffer->name, name, sizeof(buffer->name));
2928 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2932 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
2936 if (buffer->isindexbuffer)
2938 r_refdef.stats.indexbufferuploadcount++;
2939 r_refdef.stats.indexbufferuploadsize += size;
2943 r_refdef.stats.vertexbufferuploadcount++;
2944 r_refdef.stats.vertexbufferuploadsize += size;
2946 switch(vid.renderpath)
2948 case RENDERPATH_GL11:
2949 case RENDERPATH_GL13:
2950 case RENDERPATH_GL20:
2951 case RENDERPATH_GLES2:
2952 if (!buffer->bufferobject)
2953 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
2954 if (buffer->isindexbuffer)
2955 GL_BindEBO(buffer->bufferobject);
2957 GL_BindVBO(buffer->bufferobject);
2958 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
2960 case RENDERPATH_D3D9:
2964 void *datapointer = NULL;
2965 if (buffer->isindexbuffer)
2967 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
2968 if (size > buffer->size || !buffer->devicebuffer)
2970 if (buffer->devicebuffer)
2971 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
2972 buffer->devicebuffer = NULL;
2973 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)))
2974 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);
2975 buffer->devicebuffer = (void *)d3d9indexbuffer;
2976 buffer->size = size;
2978 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2981 memcpy(datapointer, data, size);
2983 memset(datapointer, 0, size);
2984 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
2989 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
2990 if (size > buffer->size || !buffer->devicebuffer)
2992 if (buffer->devicebuffer)
2993 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
2994 buffer->devicebuffer = NULL;
2995 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
2996 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);
2997 buffer->devicebuffer = (void *)d3d9vertexbuffer;
2998 buffer->size = size;
3000 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3003 memcpy(datapointer, data, size);
3005 memset(datapointer, 0, size);
3006 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3012 case RENDERPATH_D3D10:
3013 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3015 case RENDERPATH_D3D11:
3016 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3018 case RENDERPATH_SOFT:
3023 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3027 switch(vid.renderpath)
3029 case RENDERPATH_GL11:
3030 case RENDERPATH_GL13:
3031 case RENDERPATH_GL20:
3032 case RENDERPATH_GLES2:
3033 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3035 case RENDERPATH_D3D9:
3037 if (gl_state.d3dvertexbuffer == (void *)buffer)
3038 gl_state.d3dvertexbuffer = NULL;
3039 if (buffer->devicebuffer)
3041 if (buffer->isindexbuffer)
3042 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3044 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3045 buffer->devicebuffer = NULL;
3049 case RENDERPATH_D3D10:
3050 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3052 case RENDERPATH_D3D11:
3053 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3055 case RENDERPATH_SOFT:
3058 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3061 void GL_Mesh_ListVBOs(qboolean printeach)
3064 size_t ebocount = 0, ebomemory = 0;
3065 size_t vbocount = 0, vbomemory = 0;
3066 r_meshbuffer_t *buffer;
3067 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3068 for (i = 0;i < endindex;i++)
3070 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3073 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)");}
3074 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)");}
3076 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);
3081 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3083 switch(vid.renderpath)
3085 case RENDERPATH_GL11:
3086 case RENDERPATH_GL13:
3087 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)
3089 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3090 gl_state.pointer_vertex_components = components;
3091 gl_state.pointer_vertex_gltype = gltype;
3092 gl_state.pointer_vertex_stride = stride;
3093 gl_state.pointer_vertex_pointer = pointer;
3094 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3095 gl_state.pointer_vertex_offset = bufferoffset;
3097 GL_BindVBO(bufferobject);
3098 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3101 case RENDERPATH_GL20:
3102 case RENDERPATH_GLES2:
3103 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)
3105 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3106 gl_state.pointer_vertex_components = components;
3107 gl_state.pointer_vertex_gltype = gltype;
3108 gl_state.pointer_vertex_stride = stride;
3109 gl_state.pointer_vertex_pointer = pointer;
3110 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3111 gl_state.pointer_vertex_offset = bufferoffset;
3113 GL_BindVBO(bufferobject);
3114 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3117 case RENDERPATH_D3D9:
3118 case RENDERPATH_D3D10:
3119 case RENDERPATH_D3D11:
3120 case RENDERPATH_SOFT:
3125 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3127 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3128 // the pointer only.
3129 switch(vid.renderpath)
3131 case RENDERPATH_GL11:
3132 case RENDERPATH_GL13:
3136 // caller wants color array enabled
3137 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3138 if (!gl_state.pointer_color_enabled)
3140 gl_state.pointer_color_enabled = true;
3142 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3144 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)
3146 gl_state.pointer_color_components = components;
3147 gl_state.pointer_color_gltype = gltype;
3148 gl_state.pointer_color_stride = stride;
3149 gl_state.pointer_color_pointer = pointer;
3150 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3151 gl_state.pointer_color_offset = bufferoffset;
3153 GL_BindVBO(bufferobject);
3154 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3159 // caller wants color array disabled
3160 if (gl_state.pointer_color_enabled)
3162 gl_state.pointer_color_enabled = false;
3164 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3165 // when color array is on the glColor gets trashed, set it again
3166 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3170 case RENDERPATH_GL20:
3171 case RENDERPATH_GLES2:
3175 // caller wants color array enabled
3176 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3177 if (!gl_state.pointer_color_enabled)
3179 gl_state.pointer_color_enabled = true;
3181 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3183 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)
3185 gl_state.pointer_color_components = components;
3186 gl_state.pointer_color_gltype = gltype;
3187 gl_state.pointer_color_stride = stride;
3188 gl_state.pointer_color_pointer = pointer;
3189 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3190 gl_state.pointer_color_offset = bufferoffset;
3192 GL_BindVBO(bufferobject);
3193 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3198 // caller wants color array disabled
3199 if (gl_state.pointer_color_enabled)
3201 gl_state.pointer_color_enabled = false;
3203 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3204 // when color array is on the glColor gets trashed, set it again
3205 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3209 case RENDERPATH_D3D9:
3210 case RENDERPATH_D3D10:
3211 case RENDERPATH_D3D11:
3212 case RENDERPATH_SOFT:
3217 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)
3219 gltextureunit_t *unit = gl_state.units + unitnum;
3220 // update array settings
3221 // note: there is no need to check bufferobject here because all cases
3222 // that involve a valid bufferobject also supply a texcoord array
3223 switch(vid.renderpath)
3225 case RENDERPATH_GL11:
3226 case RENDERPATH_GL13:
3230 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3231 // texture array unit is enabled, enable the array
3232 if (!unit->arrayenabled)
3234 unit->arrayenabled = true;
3235 GL_ClientActiveTexture(unitnum);
3236 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3239 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)
3241 unit->pointer_texcoord_components = components;
3242 unit->pointer_texcoord_gltype = gltype;
3243 unit->pointer_texcoord_stride = stride;
3244 unit->pointer_texcoord_pointer = pointer;
3245 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3246 unit->pointer_texcoord_offset = bufferoffset;
3247 GL_ClientActiveTexture(unitnum);
3248 GL_BindVBO(bufferobject);
3249 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3254 // texture array unit is disabled, disable the array
3255 if (unit->arrayenabled)
3257 unit->arrayenabled = false;
3258 GL_ClientActiveTexture(unitnum);
3259 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3263 case RENDERPATH_GL20:
3264 case RENDERPATH_GLES2:
3268 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3269 // texture array unit is enabled, enable the array
3270 if (!unit->arrayenabled)
3272 unit->arrayenabled = true;
3273 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3276 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)
3278 unit->pointer_texcoord_components = components;
3279 unit->pointer_texcoord_gltype = gltype;
3280 unit->pointer_texcoord_stride = stride;
3281 unit->pointer_texcoord_pointer = pointer;
3282 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3283 unit->pointer_texcoord_offset = bufferoffset;
3284 GL_BindVBO(bufferobject);
3285 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3290 // texture array unit is disabled, disable the array
3291 if (unit->arrayenabled)
3293 unit->arrayenabled = false;
3294 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3298 case RENDERPATH_D3D9:
3299 case RENDERPATH_D3D10:
3300 case RENDERPATH_D3D11:
3301 case RENDERPATH_SOFT:
3306 int R_Mesh_TexBound(unsigned int unitnum, int id)
3308 gltextureunit_t *unit = gl_state.units + unitnum;
3309 if (unitnum >= vid.teximageunits)
3311 if (id == GL_TEXTURE_2D)
3313 if (id == GL_TEXTURE_3D)
3315 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3316 return unit->tcubemap;
3320 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3322 switch(vid.renderpath)
3324 case RENDERPATH_GL11:
3325 case RENDERPATH_GL13:
3326 case RENDERPATH_GL20:
3327 case RENDERPATH_GLES2:
3328 R_Mesh_TexBind(0, tex);
3329 GL_ActiveTexture(0);CHECKGLERROR
3330 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3332 case RENDERPATH_D3D9:
3335 IDirect3DSurface9 *currentsurface = NULL;
3336 IDirect3DSurface9 *texturesurface = NULL;
3339 sourcerect.left = sx;
3340 sourcerect.top = sy;
3341 sourcerect.right = sx + width;
3342 sourcerect.bottom = sy + height;
3345 destrect.right = tx + width;
3346 destrect.bottom = ty + height;
3347 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3349 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3351 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3352 IDirect3DSurface9_Release(currentsurface);
3354 IDirect3DSurface9_Release(texturesurface);
3359 case RENDERPATH_D3D10:
3360 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3362 case RENDERPATH_D3D11:
3363 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3365 case RENDERPATH_SOFT:
3366 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3372 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};
3375 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3377 gltextureunit_t *unit = gl_state.units + unitnum;
3378 int tex2d, tex3d, texcubemap, texnum;
3379 if (unitnum >= vid.teximageunits)
3381 // if (unit->texture == tex)
3383 switch(vid.renderpath)
3385 case RENDERPATH_GL20:
3386 case RENDERPATH_GLES2:
3389 tex = r_texture_white;
3390 // not initialized enough yet...
3394 unit->texture = tex;
3395 texnum = R_GetTexture(tex);
3396 switch(tex->gltexturetypeenum)
3398 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3399 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3400 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;
3403 case RENDERPATH_GL13:
3404 case RENDERPATH_GL11:
3405 unit->texture = tex;
3411 texnum = R_GetTexture(tex);
3412 switch(tex->gltexturetypeenum)
3420 case GL_TEXTURE_CUBE_MAP_ARB:
3421 texcubemap = texnum;
3425 // update 2d texture binding
3426 if (unit->t2d != tex2d)
3428 GL_ActiveTexture(unitnum);
3433 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3440 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3444 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3446 // update 3d texture binding
3447 if (unit->t3d != tex3d)
3449 GL_ActiveTexture(unitnum);
3454 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3461 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3465 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3467 // update cubemap texture binding
3468 if (unit->tcubemap != texcubemap)
3470 GL_ActiveTexture(unitnum);
3473 if (unit->tcubemap == 0)
3475 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3482 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3485 unit->tcubemap = texcubemap;
3486 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3489 case RENDERPATH_D3D9:
3492 extern cvar_t gl_texture_anisotropy;
3495 tex = r_texture_white;
3496 // not initialized enough yet...
3500 // upload texture if needed
3502 if (unit->texture == tex)
3504 unit->texture = tex;
3505 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3506 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3507 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3508 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3509 if (tex->d3daddressw)
3510 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3511 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3512 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3513 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3514 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3515 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3516 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3520 case RENDERPATH_D3D10:
3521 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3523 case RENDERPATH_D3D11:
3524 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3526 case RENDERPATH_SOFT:
3529 tex = r_texture_white;
3530 // not initialized enough yet...
3534 texnum = R_GetTexture(tex);
3535 if (unit->texture == tex)
3537 unit->texture = tex;
3538 DPSOFTRAST_SetTexture(unitnum, texnum);
3543 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3545 gltextureunit_t *unit = gl_state.units + unitnum;
3546 switch(vid.renderpath)
3548 case RENDERPATH_GL11:
3549 case RENDERPATH_GL13:
3550 case RENDERPATH_GL20:
3551 case RENDERPATH_GLES2:
3552 if (matrix && matrix->m[3][3])
3554 // texmatrix specified, check if it is different
3555 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3558 unit->texmatrixenabled = true;
3559 unit->matrix = *matrix;
3561 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3562 GL_ActiveTexture(unitnum);
3563 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3564 qglLoadMatrixf(glmatrix);CHECKGLERROR
3565 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3570 // no texmatrix specified, revert to identity
3571 if (unit->texmatrixenabled)
3573 unit->texmatrixenabled = false;
3574 unit->matrix = identitymatrix;
3576 GL_ActiveTexture(unitnum);
3577 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3578 qglLoadIdentity();CHECKGLERROR
3579 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3583 case RENDERPATH_D3D9:
3584 case RENDERPATH_D3D10:
3585 case RENDERPATH_D3D11:
3587 case RENDERPATH_SOFT:
3592 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3594 gltextureunit_t *unit = gl_state.units + unitnum;
3596 switch(vid.renderpath)
3598 case RENDERPATH_GL20:
3599 case RENDERPATH_GLES2:
3602 case RENDERPATH_GL13:
3603 // GL_ARB_texture_env_combine
3605 combinergb = GL_MODULATE;
3607 combinealpha = GL_MODULATE;
3612 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3614 if (combinergb == GL_DECAL)
3615 combinergb = GL_INTERPOLATE_ARB;
3616 if (unit->combine != GL_COMBINE_ARB)
3618 unit->combine = GL_COMBINE_ARB;
3619 GL_ActiveTexture(unitnum);
3620 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3621 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3623 if (unit->combinergb != combinergb)
3625 unit->combinergb = combinergb;
3626 GL_ActiveTexture(unitnum);
3627 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3629 if (unit->combinealpha != combinealpha)
3631 unit->combinealpha = combinealpha;
3632 GL_ActiveTexture(unitnum);
3633 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3635 if (unit->rgbscale != rgbscale)
3637 unit->rgbscale = rgbscale;
3638 GL_ActiveTexture(unitnum);
3639 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3641 if (unit->alphascale != alphascale)
3643 unit->alphascale = alphascale;
3644 GL_ActiveTexture(unitnum);
3645 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3650 if (unit->combine != combinergb)
3652 unit->combine = combinergb;
3653 GL_ActiveTexture(unitnum);
3654 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3658 case RENDERPATH_GL11:
3661 combinergb = GL_MODULATE;
3662 if (unit->combine != combinergb)
3664 unit->combine = combinergb;
3665 GL_ActiveTexture(unitnum);
3666 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3669 case RENDERPATH_D3D9:
3670 case RENDERPATH_D3D10:
3671 case RENDERPATH_D3D11:
3673 case RENDERPATH_SOFT:
3678 void R_Mesh_ResetTextureState(void)
3680 unsigned int unitnum;
3684 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3685 R_Mesh_TexBind(unitnum, NULL);
3686 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3687 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3688 switch(vid.renderpath)
3690 case RENDERPATH_GL20:
3691 case RENDERPATH_GLES2:
3692 case RENDERPATH_D3D9:
3693 case RENDERPATH_D3D10:
3694 case RENDERPATH_D3D11:
3695 case RENDERPATH_SOFT:
3697 case RENDERPATH_GL13:
3698 case RENDERPATH_GL11:
3699 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3701 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3702 R_Mesh_TexMatrix(unitnum, NULL);
3711 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3712 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3713 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3715 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3717 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3721 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3723 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3724 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3725 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3729 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3731 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3732 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3733 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3734 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3735 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3736 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3737 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3741 D3DVERTEXELEMENT9 r_vertexbouncelight_d3d9elements[] =
3743 {0, (int)((size_t)&((r_vertexbouncelight_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3744 {0, (int)((size_t)&((r_vertexbouncelight_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3745 {0, (int)((size_t)&((r_vertexbouncelight_t *)0)->texcoord4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3749 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3750 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3751 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3752 IDirect3DVertexDeclaration9 *r_vertexbouncelight_d3d9decl;
3755 static void R_Mesh_InitVertexDeclarations(void)
3758 r_vertex3f_d3d9decl = NULL;
3759 r_vertexgeneric_d3d9decl = NULL;
3760 r_vertexmesh_d3d9decl = NULL;
3761 r_vertexbouncelight_d3d9decl = NULL;
3762 switch(vid.renderpath)
3764 case RENDERPATH_GL20:
3765 case RENDERPATH_GL13:
3766 case RENDERPATH_GL11:
3767 case RENDERPATH_GLES2:
3769 case RENDERPATH_D3D9:
3770 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3771 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3772 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3773 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexbouncelight_d3d9elements, &r_vertexbouncelight_d3d9decl);
3775 case RENDERPATH_D3D10:
3776 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3778 case RENDERPATH_D3D11:
3779 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3781 case RENDERPATH_SOFT:
3787 static void R_Mesh_DestroyVertexDeclarations(void)
3790 if (r_vertex3f_d3d9decl)
3791 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3792 r_vertex3f_d3d9decl = NULL;
3793 if (r_vertexgeneric_d3d9decl)
3794 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3795 r_vertexgeneric_d3d9decl = NULL;
3796 if (r_vertexmesh_d3d9decl)
3797 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3798 r_vertexmesh_d3d9decl = NULL;
3799 if (r_vertexbouncelight_d3d9decl)
3800 IDirect3DVertexDeclaration9_Release(r_vertexbouncelight_d3d9decl);
3801 r_vertexbouncelight_d3d9decl = NULL;
3805 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3807 // upload temporary vertexbuffer for this rendering
3808 if (!gl_state.usevbo_staticvertex)
3809 vertexbuffer = NULL;
3810 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3812 if (gl_state.preparevertices_dynamicvertexbuffer)
3813 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3815 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3816 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3818 switch(vid.renderpath)
3820 case RENDERPATH_GL20:
3821 case RENDERPATH_GLES2:
3824 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3825 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3826 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3827 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3828 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3829 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3830 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3834 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3835 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3836 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3837 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3838 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3839 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3840 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3843 case RENDERPATH_GL13:
3846 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3847 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3848 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3849 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3853 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3854 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3855 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3856 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3859 case RENDERPATH_GL11:
3862 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3863 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3864 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3868 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3869 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3870 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3873 case RENDERPATH_D3D9:
3875 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3877 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3879 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3880 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3881 gl_state.d3dvertexdata = (void *)vertex3f;
3882 gl_state.d3dvertexsize = sizeof(float[3]);
3885 case RENDERPATH_D3D10:
3886 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3888 case RENDERPATH_D3D11:
3889 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3891 case RENDERPATH_SOFT:
3892 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3893 DPSOFTRAST_SetColorPointer(NULL, 0);
3894 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3895 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3896 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3897 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3898 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3905 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3908 size = sizeof(r_vertexgeneric_t) * numvertices;
3909 if (gl_state.preparevertices_tempdatamaxsize < size)
3911 gl_state.preparevertices_tempdatamaxsize = size;
3912 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3914 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3915 gl_state.preparevertices_numvertices = numvertices;
3916 return gl_state.preparevertices_vertexgeneric;
3919 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
3921 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
3922 gl_state.preparevertices_vertexgeneric = NULL;
3923 gl_state.preparevertices_numvertices = 0;
3927 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
3930 r_vertexgeneric_t *vertex;
3931 switch(vid.renderpath)
3933 case RENDERPATH_GL20:
3934 case RENDERPATH_GLES2:
3935 if (!vid.useinterleavedarrays)
3937 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3938 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3939 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3940 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3941 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3942 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3943 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3947 case RENDERPATH_GL13:
3948 case RENDERPATH_GL11:
3949 if (!vid.useinterleavedarrays)
3951 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3952 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3953 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3954 if (vid.texunits >= 2)
3955 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3956 if (vid.texunits >= 3)
3957 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3961 case RENDERPATH_D3D9:
3962 case RENDERPATH_D3D10:
3963 case RENDERPATH_D3D11:
3965 case RENDERPATH_SOFT:
3966 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3967 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
3968 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
3969 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3970 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3971 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3972 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3976 // no quick path for this case, convert to vertex structs
3977 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
3978 for (i = 0;i < numvertices;i++)
3979 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3982 for (i = 0;i < numvertices;i++)
3983 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
3987 float tempcolor4f[4];
3988 unsigned char tempcolor4ub[4];
3989 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
3990 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
3991 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
3992 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
3993 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
3994 for (i = 0;i < numvertices;i++)
3995 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
3998 for (i = 0;i < numvertices;i++)
3999 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4000 R_Mesh_PrepareVertices_Generic_Unlock();
4001 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4004 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4006 // upload temporary vertexbuffer for this rendering
4007 if (!gl_state.usevbo_staticvertex)
4008 vertexbuffer = NULL;
4009 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4011 if (gl_state.preparevertices_dynamicvertexbuffer)
4012 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4014 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4015 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4017 switch(vid.renderpath)
4019 case RENDERPATH_GL20:
4020 case RENDERPATH_GLES2:
4023 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4024 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4025 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4026 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4027 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4028 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4029 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4033 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4034 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4035 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4036 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4037 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4038 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4039 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4042 case RENDERPATH_GL13:
4045 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4046 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4047 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4048 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4052 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4053 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4054 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4055 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4058 case RENDERPATH_GL11:
4061 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4062 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4063 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4067 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4068 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4069 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4072 case RENDERPATH_D3D9:
4074 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4076 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4078 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4079 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4080 gl_state.d3dvertexdata = (void *)vertex;
4081 gl_state.d3dvertexsize = sizeof(*vertex);
4084 case RENDERPATH_D3D10:
4085 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4087 case RENDERPATH_D3D11:
4088 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4090 case RENDERPATH_SOFT:
4091 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4092 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4093 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4094 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4095 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4096 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4097 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4104 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4107 size = sizeof(r_vertexmesh_t) * numvertices;
4108 if (gl_state.preparevertices_tempdatamaxsize < size)
4110 gl_state.preparevertices_tempdatamaxsize = size;
4111 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4113 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4114 gl_state.preparevertices_numvertices = numvertices;
4115 return gl_state.preparevertices_vertexmesh;
4118 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4120 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4121 gl_state.preparevertices_vertexmesh = NULL;
4122 gl_state.preparevertices_numvertices = 0;
4126 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)
4129 r_vertexmesh_t *vertex;
4130 switch(vid.renderpath)
4132 case RENDERPATH_GL20:
4133 case RENDERPATH_GLES2:
4134 if (!vid.useinterleavedarrays)
4136 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4137 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4138 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4139 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4140 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4141 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4142 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4146 case RENDERPATH_GL13:
4147 case RENDERPATH_GL11:
4148 if (!vid.useinterleavedarrays)
4150 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4151 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4152 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4153 if (vid.texunits >= 2)
4154 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4155 if (vid.texunits >= 3)
4156 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4160 case RENDERPATH_D3D9:
4161 case RENDERPATH_D3D10:
4162 case RENDERPATH_D3D11:
4164 case RENDERPATH_SOFT:
4165 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4166 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4167 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4168 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4169 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4170 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4171 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4175 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4176 for (i = 0;i < numvertices;i++)
4177 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4179 for (i = 0;i < numvertices;i++)
4180 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4182 for (i = 0;i < numvertices;i++)
4183 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4185 for (i = 0;i < numvertices;i++)
4186 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4189 for (i = 0;i < numvertices;i++)
4190 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
4194 float tempcolor4f[4];
4195 unsigned char tempcolor4ub[4];
4196 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
4197 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
4198 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
4199 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
4200 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
4201 for (i = 0;i < numvertices;i++)
4202 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
4204 if (texcoordtexture2f)
4205 for (i = 0;i < numvertices;i++)
4206 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4207 if (texcoordlightmap2f)
4208 for (i = 0;i < numvertices;i++)
4209 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4210 R_Mesh_PrepareVertices_Mesh_Unlock();
4211 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4214 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4216 // upload temporary vertexbuffer for this rendering
4217 if (!gl_state.usevbo_staticvertex)
4218 vertexbuffer = NULL;
4219 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4221 if (gl_state.preparevertices_dynamicvertexbuffer)
4222 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4224 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4225 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4227 switch(vid.renderpath)
4229 case RENDERPATH_GL20:
4230 case RENDERPATH_GLES2:
4233 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4234 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4235 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4236 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4237 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4238 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4239 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4243 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4244 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4245 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4246 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4247 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4248 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4249 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4252 case RENDERPATH_GL13:
4255 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4256 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4257 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4258 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4262 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4263 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4264 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4265 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4268 case RENDERPATH_GL11:
4271 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4272 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4273 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4277 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4278 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4279 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4282 case RENDERPATH_D3D9:
4284 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4286 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4288 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4289 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4290 gl_state.d3dvertexdata = (void *)vertex;
4291 gl_state.d3dvertexsize = sizeof(*vertex);
4294 case RENDERPATH_D3D10:
4295 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4297 case RENDERPATH_D3D11:
4298 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4300 case RENDERPATH_SOFT:
4301 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4302 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4303 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4304 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4305 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4306 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4307 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);
4314 r_vertexbouncelight_t *R_Mesh_PrepareVertices_BounceLight_Lock(int numvertices)
4317 size = sizeof(r_vertexbouncelight_t) * numvertices;
4318 if (gl_state.preparevertices_tempdatamaxsize < size)
4320 gl_state.preparevertices_tempdatamaxsize = size;
4321 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4323 gl_state.preparevertices_vertexbouncelight = (r_vertexbouncelight_t *)gl_state.preparevertices_tempdata;
4324 gl_state.preparevertices_numvertices = numvertices;
4325 return gl_state.preparevertices_vertexbouncelight;
4328 qboolean R_Mesh_PrepareVertices_BounceLight_Unlock(void)
4330 R_Mesh_PrepareVertices_BounceLight(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexbouncelight, NULL);
4331 gl_state.preparevertices_vertexbouncelight = NULL;
4332 gl_state.preparevertices_numvertices = 0;
4336 void R_Mesh_PrepareVertices_BounceLight_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord4f)
4339 r_vertexbouncelight_t *vertex;
4340 switch(vid.renderpath)
4342 case RENDERPATH_GL20:
4343 case RENDERPATH_GLES2:
4344 if (!vid.useinterleavedarrays)
4346 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4347 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4348 R_Mesh_TexCoordPointer(0, 4, GL_FLOAT, sizeof(float[4]), texcoord4f, NULL, 0);
4349 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4350 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4351 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4352 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4356 case RENDERPATH_GL13:
4357 case RENDERPATH_GL11:
4358 if (!vid.useinterleavedarrays)
4360 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4361 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4362 R_Mesh_TexCoordPointer(0, 4, GL_FLOAT, sizeof(float[4]), texcoord4f, NULL, 0);
4363 if (vid.texunits >= 2)
4364 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4365 if (vid.texunits >= 3)
4366 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4370 case RENDERPATH_D3D9:
4371 case RENDERPATH_D3D10:
4372 case RENDERPATH_D3D11:
4374 case RENDERPATH_SOFT:
4375 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4376 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4377 DPSOFTRAST_SetTexCoordPointer(0, 4, sizeof(float[4]), texcoord4f);
4378 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4379 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4380 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4381 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4385 // no quick path for this case, convert to vertex structs
4386 vertex = R_Mesh_PrepareVertices_BounceLight_Lock(numvertices);
4387 for (i = 0;i < numvertices;i++)
4388 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4391 for (i = 0;i < numvertices;i++)
4392 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
4396 float tempcolor4f[4];
4397 unsigned char tempcolor4ub[4];
4398 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
4399 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
4400 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
4401 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
4402 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
4403 for (i = 0;i < numvertices;i++)
4404 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
4407 for (i = 0;i < numvertices;i++)
4408 Vector4Copy(texcoord4f + 4*i, vertex[i].texcoord4f);
4409 R_Mesh_PrepareVertices_BounceLight_Unlock();
4410 R_Mesh_PrepareVertices_BounceLight(numvertices, vertex, NULL);
4413 void R_Mesh_PrepareVertices_BounceLight(int numvertices, const r_vertexbouncelight_t *vertex, const r_meshbuffer_t *vertexbuffer)
4415 // upload temporary vertexbuffer for this rendering
4416 if (!gl_state.usevbo_staticvertex)
4417 vertexbuffer = NULL;
4418 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4420 if (gl_state.preparevertices_dynamicvertexbuffer)
4421 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4423 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4424 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4426 switch(vid.renderpath)
4428 case RENDERPATH_GL20:
4429 case RENDERPATH_GLES2:
4432 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4433 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4434 R_Mesh_TexCoordPointer(0, 4, GL_FLOAT , sizeof(*vertex), vertex->texcoord4f , vertexbuffer, (int)((unsigned char *)vertex->texcoord4f - (unsigned char *)vertex));
4435 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4436 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4437 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4438 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4442 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4443 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4444 R_Mesh_TexCoordPointer(0, 4, GL_FLOAT , sizeof(*vertex), vertex->texcoord4f , NULL, 0);
4445 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4446 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4447 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4448 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4451 case RENDERPATH_GL13:
4454 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4455 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4456 R_Mesh_TexCoordPointer(0, 4, GL_FLOAT , sizeof(*vertex), vertex->texcoord4f , vertexbuffer, (int)((unsigned char *)vertex->texcoord4f - (unsigned char *)vertex));
4457 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4461 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4462 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4463 R_Mesh_TexCoordPointer(0, 4, GL_FLOAT , sizeof(*vertex), vertex->texcoord4f , NULL, 0);
4464 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4467 case RENDERPATH_GL11:
4470 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4471 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4472 R_Mesh_TexCoordPointer(0, 4, GL_FLOAT , sizeof(*vertex), vertex->texcoord4f , vertexbuffer, (int)((unsigned char *)vertex->texcoord4f - (unsigned char *)vertex));
4476 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4477 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4478 R_Mesh_TexCoordPointer(0, 4, GL_FLOAT , sizeof(*vertex), vertex->texcoord4f , NULL, 0);
4481 case RENDERPATH_D3D9:
4483 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexbouncelight_d3d9decl);
4485 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4487 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4488 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4489 gl_state.d3dvertexdata = (void *)vertex;
4490 gl_state.d3dvertexsize = sizeof(*vertex);
4493 case RENDERPATH_D3D10:
4494 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4496 case RENDERPATH_D3D11:
4497 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4499 case RENDERPATH_SOFT:
4500 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4501 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4502 DPSOFTRAST_SetTexCoordPointer(0, 4, sizeof(*vertex), vertex->texcoord4f);
4503 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4504 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4505 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4506 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);