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 qboolean pointer_color_enabled;
152 int pointer_vertex_components;
153 int pointer_vertex_gltype;
154 size_t pointer_vertex_stride;
155 const void *pointer_vertex_pointer;
156 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
157 size_t pointer_vertex_offset;
159 int pointer_color_components;
160 int pointer_color_gltype;
161 size_t pointer_color_stride;
162 const void *pointer_color_pointer;
163 const r_meshbuffer_t *pointer_color_vertexbuffer;
164 size_t pointer_color_offset;
166 void *preparevertices_tempdata;
167 size_t preparevertices_tempdatamaxsize;
168 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
169 r_vertexgeneric_t *preparevertices_vertexgeneric;
170 r_vertexmesh_t *preparevertices_vertexmesh;
171 int preparevertices_numvertices;
173 r_meshbuffer_t *draw_dynamicindexbuffer;
175 qboolean usevbo_staticvertex;
176 qboolean usevbo_staticindex;
177 qboolean usevbo_dynamicvertex;
178 qboolean usevbo_dynamicindex;
180 memexpandablearray_t meshbufferarray;
185 // rtexture_t *d3drt_depthtexture;
186 // rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
187 IDirect3DSurface9 *d3drt_depthsurface;
188 IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
189 IDirect3DSurface9 *d3drt_backbufferdepthsurface;
190 IDirect3DSurface9 *d3drt_backbuffercolorsurface;
191 void *d3dvertexbuffer;
193 size_t d3dvertexsize;
198 static gl_state_t gl_state;
202 note: here's strip order for a terrain row:
209 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
211 *elements++ = i + row;
213 *elements++ = i + row + 1;
216 *elements++ = i + row + 1;
219 for (y = 0;y < rows - 1;y++)
221 for (x = 0;x < columns - 1;x++)
224 *elements++ = i + columns;
226 *elements++ = i + columns + 1;
229 *elements++ = i + columns + 1;
240 for (y = 0;y < rows - 1;y++)
242 for (x = 0;x < columns - 1;x++)
246 *elements++ = i + columns;
247 *elements++ = i + columns + 1;
248 *elements++ = i + columns;
249 *elements++ = i + columns + 1;
255 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
256 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
257 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
258 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
260 void GL_VBOStats_f(void)
262 GL_Mesh_ListVBOs(true);
265 static void GL_Backend_ResetState(void);
267 static void R_Mesh_InitVertexDeclarations(void);
268 static void R_Mesh_DestroyVertexDeclarations(void);
270 static void R_Mesh_SetUseVBO(void)
272 switch(vid.renderpath)
274 case RENDERPATH_GL11:
275 case RENDERPATH_GL13:
276 case RENDERPATH_GL20:
277 case RENDERPATH_CGGL:
278 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
279 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
280 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
281 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
283 case RENDERPATH_D3D9:
284 gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
285 gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo;
287 case RENDERPATH_D3D10:
288 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
290 case RENDERPATH_D3D11:
291 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
293 case RENDERPATH_SOFT:
294 gl_state.usevbo_staticvertex = false;
295 gl_state.usevbo_staticindex = false;
296 gl_state.usevbo_dynamicvertex = false;
297 gl_state.usevbo_dynamicindex = false;
302 static void gl_backend_start(void)
304 memset(&gl_state, 0, sizeof(gl_state));
306 R_Mesh_InitVertexDeclarations();
309 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
311 Con_DPrintf("OpenGL backend started.\n");
315 GL_Backend_ResetState();
317 switch(vid.renderpath)
319 case RENDERPATH_GL11:
320 case RENDERPATH_GL13:
321 case RENDERPATH_GL20:
322 case RENDERPATH_CGGL:
324 case RENDERPATH_D3D9:
326 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
327 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
330 case RENDERPATH_D3D10:
331 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
333 case RENDERPATH_D3D11:
334 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
336 case RENDERPATH_SOFT:
341 static void gl_backend_shutdown(void)
343 Con_DPrint("OpenGL Backend shutting down\n");
345 switch(vid.renderpath)
347 case RENDERPATH_GL11:
348 case RENDERPATH_GL13:
349 case RENDERPATH_GL20:
350 case RENDERPATH_CGGL:
352 case RENDERPATH_D3D9:
354 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
355 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
358 case RENDERPATH_D3D10:
359 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
361 case RENDERPATH_D3D11:
362 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
364 case RENDERPATH_SOFT:
368 if (gl_state.preparevertices_tempdata)
369 Mem_Free(gl_state.preparevertices_tempdata);
370 if (gl_state.preparevertices_dynamicvertexbuffer)
371 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
373 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
375 R_Mesh_DestroyVertexDeclarations();
377 memset(&gl_state, 0, sizeof(gl_state));
380 static void gl_backend_newmap(void)
384 static void gl_backend_devicelost(void)
387 r_meshbuffer_t *buffer;
389 gl_state.d3dvertexbuffer = NULL;
391 switch(vid.renderpath)
393 case RENDERPATH_GL11:
394 case RENDERPATH_GL13:
395 case RENDERPATH_GL20:
396 case RENDERPATH_CGGL:
398 case RENDERPATH_D3D9:
400 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
401 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
404 case RENDERPATH_D3D10:
405 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
407 case RENDERPATH_D3D11:
408 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
410 case RENDERPATH_SOFT:
413 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
414 for (i = 0;i < endindex;i++)
416 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
417 if (!buffer || !buffer->isdynamic)
419 switch(vid.renderpath)
421 case RENDERPATH_GL11:
422 case RENDERPATH_GL13:
423 case RENDERPATH_GL20:
424 case RENDERPATH_CGGL:
426 case RENDERPATH_D3D9:
428 if (buffer->devicebuffer)
430 if (buffer->isindexbuffer)
431 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
433 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
434 buffer->devicebuffer = NULL;
438 case RENDERPATH_D3D10:
439 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
441 case RENDERPATH_D3D11:
442 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
444 case RENDERPATH_SOFT:
450 static void gl_backend_devicerestored(void)
452 switch(vid.renderpath)
454 case RENDERPATH_GL11:
455 case RENDERPATH_GL13:
456 case RENDERPATH_GL20:
457 case RENDERPATH_CGGL:
459 case RENDERPATH_D3D9:
461 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
462 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
465 case RENDERPATH_D3D10:
466 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
468 case RENDERPATH_D3D11:
469 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
471 case RENDERPATH_SOFT:
476 void gl_backend_init(void)
480 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
482 polygonelement3s[i * 3 + 0] = 0;
483 polygonelement3s[i * 3 + 1] = i + 1;
484 polygonelement3s[i * 3 + 2] = i + 2;
486 // elements for rendering a series of quads as triangles
487 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
489 quadelement3s[i * 6 + 0] = i * 4;
490 quadelement3s[i * 6 + 1] = i * 4 + 1;
491 quadelement3s[i * 6 + 2] = i * 4 + 2;
492 quadelement3s[i * 6 + 3] = i * 4;
493 quadelement3s[i * 6 + 4] = i * 4 + 2;
494 quadelement3s[i * 6 + 5] = i * 4 + 3;
497 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
498 polygonelement3i[i] = polygonelement3s[i];
499 for (i = 0;i < QUADELEMENTS_MAXQUADS*3;i++)
500 quadelement3i[i] = quadelement3s[i];
502 Cvar_RegisterVariable(&r_render);
503 Cvar_RegisterVariable(&r_renderview);
504 Cvar_RegisterVariable(&r_waterwarp);
505 Cvar_RegisterVariable(&gl_polyblend);
506 Cvar_RegisterVariable(&v_flipped);
507 Cvar_RegisterVariable(&gl_dither);
508 Cvar_RegisterVariable(&gl_vbo);
509 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
510 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
511 Cvar_RegisterVariable(&gl_paranoid);
512 Cvar_RegisterVariable(&gl_printcheckerror);
514 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
515 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
516 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
518 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");
520 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
523 void GL_SetMirrorState(qboolean state);
525 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
529 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
530 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
532 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
534 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
535 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
536 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
538 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
541 static int bboxedges[12][2] =
560 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
562 int i, ix1, iy1, ix2, iy2;
563 float x1, y1, x2, y2;
574 scissor[0] = r_refdef.view.viewport.x;
575 scissor[1] = r_refdef.view.viewport.y;
576 scissor[2] = r_refdef.view.viewport.width;
577 scissor[3] = r_refdef.view.viewport.height;
579 // if view is inside the box, just say yes it's visible
580 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
583 x1 = y1 = x2 = y2 = 0;
585 // transform all corners that are infront of the nearclip plane
586 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
587 plane4f[3] = r_refdef.view.frustum[4].dist;
589 for (i = 0;i < 8;i++)
591 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
592 dist[i] = DotProduct4(corner[i], plane4f);
593 sign[i] = dist[i] > 0;
596 VectorCopy(corner[i], vertex[numvertices]);
600 // if some points are behind the nearclip, add clipped edge points to make
601 // sure that the scissor boundary is complete
602 if (numvertices > 0 && numvertices < 8)
604 // add clipped edge points
605 for (i = 0;i < 12;i++)
609 if (sign[j] != sign[k])
611 f = dist[j] / (dist[j] - dist[k]);
612 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
618 // if we have no points to check, it is behind the view plane
622 // if we have some points to transform, check what screen area is covered
623 x1 = y1 = x2 = y2 = 0;
625 //Con_Printf("%i vertices to transform...\n", numvertices);
626 for (i = 0;i < numvertices;i++)
628 VectorCopy(vertex[i], v);
629 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
630 //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]);
633 if (x1 > v2[0]) x1 = v2[0];
634 if (x2 < v2[0]) x2 = v2[0];
635 if (y1 > v2[1]) y1 = v2[1];
636 if (y2 < v2[1]) y2 = v2[1];
645 // now convert the scissor rectangle to integer screen coordinates
646 ix1 = (int)(x1 - 1.0f);
647 //iy1 = vid.height - (int)(y2 - 1.0f);
648 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
649 iy1 = (int)(y1 - 1.0f);
650 ix2 = (int)(x2 + 1.0f);
651 //iy2 = vid.height - (int)(y1 + 1.0f);
652 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
653 iy2 = (int)(y2 + 1.0f);
654 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
656 // clamp it to the screen
657 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
658 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
659 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
660 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
662 // if it is inside out, it's not visible
663 if (ix2 <= ix1 || iy2 <= iy1)
666 // the light area is visible, set up the scissor rectangle
669 scissor[2] = ix2 - ix1;
670 scissor[3] = iy2 - iy1;
672 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
673 switch(vid.renderpath)
675 case RENDERPATH_D3D9:
676 case RENDERPATH_D3D10:
677 case RENDERPATH_D3D11:
678 scissor[1] = vid.height - scissor[1] - scissor[3];
680 case RENDERPATH_GL11:
681 case RENDERPATH_GL13:
682 case RENDERPATH_GL20:
683 case RENDERPATH_CGGL:
684 case RENDERPATH_SOFT:
692 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
696 float clipPlane[4], v3[3], v4[3];
699 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
701 VectorSet(normal, normalx, normaly, normalz);
702 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
703 VectorScale(normal, dist, v3);
704 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
705 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
706 clipPlane[3] = -DotProduct(v4, clipPlane);
710 // testing code for comparing results
712 VectorCopy4(clipPlane, clipPlane2);
713 R_EntityMatrix(&identitymatrix);
714 VectorSet(q, normal[0], normal[1], normal[2], -dist);
715 qglClipPlane(GL_CLIP_PLANE0, q);
716 qglGetClipPlane(GL_CLIP_PLANE0, q);
717 VectorCopy4(q, clipPlane);
721 // Calculate the clip-space corner point opposite the clipping plane
722 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
723 // transform it into camera space by multiplying it
724 // by the inverse of the projection matrix
725 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
726 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
728 q[3] = (1.0f + m[10]) / m[14];
730 // Calculate the scaled plane vector
731 d = 2.0f / DotProduct4(clipPlane, q);
733 // Replace the third row of the projection matrix
734 m[2] = clipPlane[0] * d;
735 m[6] = clipPlane[1] * d;
736 m[10] = clipPlane[2] * d + 1.0f;
737 m[14] = clipPlane[3] * d;
740 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)
742 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
744 memset(v, 0, sizeof(*v));
745 v->type = R_VIEWPORTTYPE_ORTHO;
746 v->cameramatrix = *cameramatrix;
753 memset(m, 0, sizeof(m));
754 m[0] = 2/(right - left);
755 m[5] = 2/(top - bottom);
756 m[10] = -2/(zFar - zNear);
757 m[12] = - (right + left)/(right - left);
758 m[13] = - (top + bottom)/(top - bottom);
759 m[14] = - (zFar + zNear)/(zFar - zNear);
761 switch(vid.renderpath)
763 case RENDERPATH_GL11:
764 case RENDERPATH_GL13:
765 case RENDERPATH_GL20:
766 case RENDERPATH_CGGL:
767 case RENDERPATH_SOFT:
769 case RENDERPATH_D3D9:
770 case RENDERPATH_D3D10:
771 case RENDERPATH_D3D11:
772 m[10] = -1/(zFar - zNear);
773 m[14] = -zNear/(zFar-zNear);
776 v->screentodepth[0] = -farclip / (farclip - nearclip);
777 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
779 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
782 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
784 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
790 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
791 R_Viewport_TransformToScreen(v, test1, test2);
792 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
797 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)
799 matrix4x4_t tempmatrix, basematrix;
801 memset(v, 0, sizeof(*v));
803 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
804 v->cameramatrix = *cameramatrix;
811 memset(m, 0, sizeof(m));
812 m[0] = 1.0 / frustumx;
813 m[5] = 1.0 / frustumy;
814 m[10] = -(farclip + nearclip) / (farclip - nearclip);
816 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
817 v->screentodepth[0] = -farclip / (farclip - nearclip);
818 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
820 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
821 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
822 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
823 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
826 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
828 if(v_flipped.integer)
836 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
839 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)
841 matrix4x4_t tempmatrix, basematrix;
842 const float nudge = 1.0 - 1.0 / (1<<23);
844 memset(v, 0, sizeof(*v));
846 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
847 v->cameramatrix = *cameramatrix;
854 memset(m, 0, sizeof(m));
855 m[ 0] = 1.0 / frustumx;
856 m[ 5] = 1.0 / frustumy;
859 m[14] = -2 * nearclip * nudge;
860 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
861 v->screentodepth[1] = m[14] * -0.5;
863 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
864 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
865 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
866 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
869 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
871 if(v_flipped.integer)
879 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
882 float cubeviewmatrix[6][16] =
884 // standard cubemap projections
922 float rectviewmatrix[6][16] =
924 // sign-preserving cubemap projections
963 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
965 matrix4x4_t tempmatrix, basematrix;
967 memset(v, 0, sizeof(*v));
968 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
969 v->cameramatrix = *cameramatrix;
973 memset(m, 0, sizeof(m));
975 m[10] = -(farclip + nearclip) / (farclip - nearclip);
977 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
979 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
980 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
981 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
984 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
986 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
989 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)
991 matrix4x4_t tempmatrix, basematrix;
993 memset(v, 0, sizeof(*v));
994 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
995 v->cameramatrix = *cameramatrix;
996 v->x = (side & 1) * size;
997 v->y = (side >> 1) * size;
1001 memset(m, 0, sizeof(m));
1002 m[0] = m[5] = 1.0f * ((float)size - border) / size;
1003 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1005 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1007 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1008 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1009 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1011 switch(vid.renderpath)
1013 case RENDERPATH_GL20:
1014 case RENDERPATH_CGGL:
1015 case RENDERPATH_GL13:
1016 case RENDERPATH_GL11:
1017 case RENDERPATH_SOFT:
1019 case RENDERPATH_D3D9:
1022 case RENDERPATH_D3D10:
1023 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1025 case RENDERPATH_D3D11:
1026 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1031 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1033 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1036 void R_SetViewport(const r_viewport_t *v)
1041 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1042 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1044 // copy over the matrices to our state
1045 gl_viewmatrix = v->viewmatrix;
1046 gl_projectionmatrix = v->projectmatrix;
1048 switch(vid.renderpath)
1050 case RENDERPATH_GL20:
1051 case RENDERPATH_CGGL:
1053 // qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1055 case RENDERPATH_GL13:
1056 case RENDERPATH_GL11:
1058 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1059 // Load the projection matrix into OpenGL
1060 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1061 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1062 qglLoadMatrixf(m);CHECKGLERROR
1063 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1065 case RENDERPATH_D3D9:
1068 D3DVIEWPORT9 d3dviewport;
1069 d3dviewport.X = gl_viewport.x;
1070 d3dviewport.Y = gl_viewport.y;
1071 d3dviewport.Width = gl_viewport.width;
1072 d3dviewport.Height = gl_viewport.height;
1073 d3dviewport.MinZ = gl_state.depthrange[0];
1074 d3dviewport.MaxZ = gl_state.depthrange[1];
1075 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1079 case RENDERPATH_D3D10:
1080 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1082 case RENDERPATH_D3D11:
1083 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1085 case RENDERPATH_SOFT:
1086 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1090 // force an update of the derived matrices
1091 gl_modelmatrixchanged = true;
1092 R_EntityMatrix(&gl_modelmatrix);
1095 void R_GetViewport(r_viewport_t *v)
1100 static void GL_BindVBO(int bufferobject)
1102 if (gl_state.vertexbufferobject != bufferobject)
1104 gl_state.vertexbufferobject = bufferobject;
1106 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1110 static void GL_BindEBO(int bufferobject)
1112 if (gl_state.elementbufferobject != bufferobject)
1114 gl_state.elementbufferobject = bufferobject;
1116 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1120 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1123 switch(vid.renderpath)
1125 case RENDERPATH_GL11:
1126 case RENDERPATH_GL13:
1127 case RENDERPATH_GL20:
1128 case RENDERPATH_CGGL:
1129 if (!vid.support.ext_framebuffer_object)
1131 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1132 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1133 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1134 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1135 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1136 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1137 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1139 case RENDERPATH_D3D9:
1140 case RENDERPATH_D3D10:
1141 case RENDERPATH_D3D11:
1143 case RENDERPATH_SOFT:
1149 void R_Mesh_DestroyFramebufferObject(int fbo)
1151 switch(vid.renderpath)
1153 case RENDERPATH_GL11:
1154 case RENDERPATH_GL13:
1155 case RENDERPATH_GL20:
1156 case RENDERPATH_CGGL:
1158 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1160 case RENDERPATH_D3D9:
1161 case RENDERPATH_D3D10:
1162 case RENDERPATH_D3D11:
1164 case RENDERPATH_SOFT:
1170 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1172 // 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)
1173 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)
1176 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1177 if (gl_state.d3drt_depthsurface != depthsurface)
1179 gl_state.d3drt_depthsurface = depthsurface;
1180 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1182 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1184 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1185 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1187 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1189 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1190 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1192 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1194 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1195 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1197 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1199 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1200 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1205 void R_Mesh_ResetRenderTargets(void)
1207 switch(vid.renderpath)
1209 case RENDERPATH_GL11:
1210 case RENDERPATH_GL13:
1211 case RENDERPATH_GL20:
1212 case RENDERPATH_CGGL:
1213 if (gl_state.framebufferobject)
1215 gl_state.framebufferobject = 0;
1216 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1219 case RENDERPATH_D3D9:
1221 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1224 case RENDERPATH_D3D10:
1225 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1227 case RENDERPATH_D3D11:
1228 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1230 case RENDERPATH_SOFT:
1231 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1236 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1240 rtexture_t *textures[5];
1241 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1242 textures[4] = depthtexture;
1243 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1244 for (j = 0;j < 5;j++)
1246 for (i = 0;i < vid.teximageunits;i++)
1247 if (gl_state.units[i].texture == textures[j])
1248 R_Mesh_TexBind(i, NULL);
1249 // set up framebuffer object or render targets for the active rendering API
1250 switch(vid.renderpath)
1252 case RENDERPATH_GL11:
1253 case RENDERPATH_GL13:
1254 case RENDERPATH_GL20:
1255 case RENDERPATH_CGGL:
1256 if (gl_state.framebufferobject != fbo)
1258 gl_state.framebufferobject = fbo;
1259 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1262 case RENDERPATH_D3D9:
1264 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1265 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1268 IDirect3DSurface9 *colorsurfaces[4];
1269 for (i = 0;i < 4;i++)
1271 colorsurfaces[i] = NULL;
1273 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1275 // set the render targets for real
1276 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1277 // release the texture surface levels (they won't be lost while bound...)
1278 for (i = 0;i < 4;i++)
1280 IDirect3DSurface9_Release(colorsurfaces[i]);
1283 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1286 case RENDERPATH_D3D10:
1287 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1289 case RENDERPATH_D3D11:
1290 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1292 case RENDERPATH_SOFT:
1296 unsigned int *pointers[5];
1297 memset(pointers, 0, sizeof(pointers));
1298 for (i = 0;i < 5;i++)
1299 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1300 width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1301 height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1302 DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1305 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1311 static int d3dcmpforglfunc(int f)
1315 case GL_NEVER: return D3DCMP_NEVER;
1316 case GL_LESS: return D3DCMP_LESS;
1317 case GL_EQUAL: return D3DCMP_EQUAL;
1318 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1319 case GL_GREATER: return D3DCMP_GREATER;
1320 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1321 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1322 case GL_ALWAYS: return D3DCMP_ALWAYS;
1323 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1327 static int d3dstencilopforglfunc(int f)
1331 case GL_KEEP: return D3DSTENCILOP_KEEP;
1332 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1333 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1334 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1340 static void GL_Backend_ResetState(void)
1343 gl_state.active = true;
1344 gl_state.depthtest = true;
1345 gl_state.alphatest = false;
1346 gl_state.alphafunc = GL_GEQUAL;
1347 gl_state.alphafuncvalue = 0.5f;
1348 gl_state.blendfunc1 = GL_ONE;
1349 gl_state.blendfunc2 = GL_ZERO;
1350 gl_state.blend = false;
1351 gl_state.depthmask = GL_TRUE;
1352 gl_state.colormask = 15;
1353 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1354 gl_state.lockrange_first = 0;
1355 gl_state.lockrange_count = 0;
1356 gl_state.cullface = GL_NONE;
1357 gl_state.cullfaceenable = false;
1358 gl_state.polygonoffset[0] = 0;
1359 gl_state.polygonoffset[1] = 0;
1360 gl_state.framebufferobject = 0;
1361 gl_state.depthfunc = GL_LEQUAL;
1363 switch(vid.renderpath)
1365 case RENDERPATH_D3D9:
1368 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1369 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1370 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1371 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1372 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1373 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1374 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1375 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1376 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1377 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1381 case RENDERPATH_D3D10:
1382 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1384 case RENDERPATH_D3D11:
1385 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1387 case RENDERPATH_GL20:
1388 case RENDERPATH_CGGL:
1391 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1392 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1393 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1394 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1395 qglDisable(GL_BLEND);CHECKGLERROR
1396 qglCullFace(gl_state.cullface);CHECKGLERROR
1397 qglDisable(GL_CULL_FACE);CHECKGLERROR
1398 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1399 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1400 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1401 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1403 if (vid.support.arb_vertex_buffer_object)
1405 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1406 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1409 if (vid.support.ext_framebuffer_object)
1411 qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1412 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1415 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1416 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1418 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1419 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1420 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1422 if (vid.support.ext_framebuffer_object)
1423 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1425 gl_state.unit = MAX_TEXTUREUNITS;
1426 gl_state.clientunit = MAX_TEXTUREUNITS;
1427 for (i = 0;i < vid.teximageunits;i++)
1429 GL_ActiveTexture(i);
1430 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1431 if (vid.support.ext_texture_3d)
1433 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1435 if (vid.support.arb_texture_cube_map)
1437 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1441 for (i = 0;i < vid.texarrayunits;i++)
1443 GL_ClientActiveTexture(i);
1445 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1446 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1450 case RENDERPATH_GL13:
1451 case RENDERPATH_GL11:
1454 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1455 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1456 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1457 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1458 qglDisable(GL_BLEND);CHECKGLERROR
1459 qglCullFace(gl_state.cullface);CHECKGLERROR
1460 qglDisable(GL_CULL_FACE);CHECKGLERROR
1461 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1462 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1463 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1464 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1466 if (vid.support.arb_vertex_buffer_object)
1468 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1469 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1472 if (vid.support.ext_framebuffer_object)
1474 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1475 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1478 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1479 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1481 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1482 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1483 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1485 if (vid.support.ext_framebuffer_object)
1486 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1488 gl_state.unit = MAX_TEXTUREUNITS;
1489 gl_state.clientunit = MAX_TEXTUREUNITS;
1490 for (i = 0;i < vid.texunits;i++)
1492 GL_ActiveTexture(i);
1493 GL_ClientActiveTexture(i);
1494 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1495 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1496 if (vid.support.ext_texture_3d)
1498 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1499 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1501 if (vid.support.arb_texture_cube_map)
1503 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1504 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1507 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1508 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1509 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1510 qglLoadIdentity();CHECKGLERROR
1511 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1512 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1516 case RENDERPATH_SOFT:
1517 DPSOFTRAST_ColorMask(1,1,1,1);
1518 DPSOFTRAST_AlphaTest(gl_state.alphatest);
1519 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1520 DPSOFTRAST_CullFace(gl_state.cullface);
1521 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1522 DPSOFTRAST_DepthMask(gl_state.depthmask);
1523 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1524 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1525 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1530 void GL_ActiveTexture(unsigned int num)
1532 if (gl_state.unit != num)
1534 gl_state.unit = num;
1535 switch(vid.renderpath)
1537 case RENDERPATH_GL11:
1538 case RENDERPATH_GL13:
1539 case RENDERPATH_GL20:
1540 case RENDERPATH_CGGL:
1541 if (qglActiveTexture)
1544 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1548 case RENDERPATH_D3D9:
1549 case RENDERPATH_D3D10:
1550 case RENDERPATH_D3D11:
1552 case RENDERPATH_SOFT:
1558 void GL_ClientActiveTexture(unsigned int num)
1560 if (gl_state.clientunit != num)
1562 gl_state.clientunit = num;
1563 switch(vid.renderpath)
1565 case RENDERPATH_GL11:
1566 case RENDERPATH_GL13:
1567 case RENDERPATH_GL20:
1568 case RENDERPATH_CGGL:
1569 if (qglActiveTexture)
1572 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1576 case RENDERPATH_D3D9:
1577 case RENDERPATH_D3D10:
1578 case RENDERPATH_D3D11:
1580 case RENDERPATH_SOFT:
1586 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1588 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1590 qboolean blendenable;
1591 gl_state.blendfunc1 = blendfunc1;
1592 gl_state.blendfunc2 = blendfunc2;
1593 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1594 switch(vid.renderpath)
1596 case RENDERPATH_GL11:
1597 case RENDERPATH_GL13:
1598 case RENDERPATH_GL20:
1599 case RENDERPATH_CGGL:
1601 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1602 if (gl_state.blend != blendenable)
1604 gl_state.blend = blendenable;
1605 if (!gl_state.blend)
1607 qglDisable(GL_BLEND);CHECKGLERROR
1611 qglEnable(GL_BLEND);CHECKGLERROR
1615 case RENDERPATH_D3D9:
1620 D3DBLEND d3dblendfunc[2];
1621 glblendfunc[0] = gl_state.blendfunc1;
1622 glblendfunc[1] = gl_state.blendfunc2;
1623 for (i = 0;i < 2;i++)
1625 switch(glblendfunc[i])
1627 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1628 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1629 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1630 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1631 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1632 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1633 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1634 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1635 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1636 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1639 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1640 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1641 if (gl_state.blend != blendenable)
1643 gl_state.blend = blendenable;
1644 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1649 case RENDERPATH_D3D10:
1650 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1652 case RENDERPATH_D3D11:
1653 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1655 case RENDERPATH_SOFT:
1656 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1662 void GL_DepthMask(int state)
1664 if (gl_state.depthmask != state)
1666 gl_state.depthmask = state;
1667 switch(vid.renderpath)
1669 case RENDERPATH_GL11:
1670 case RENDERPATH_GL13:
1671 case RENDERPATH_GL20:
1672 case RENDERPATH_CGGL:
1674 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1676 case RENDERPATH_D3D9:
1678 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1681 case RENDERPATH_D3D10:
1682 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1684 case RENDERPATH_D3D11:
1685 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1687 case RENDERPATH_SOFT:
1688 DPSOFTRAST_DepthMask(gl_state.depthmask);
1694 void GL_DepthTest(int state)
1696 if (gl_state.depthtest != state)
1698 gl_state.depthtest = state;
1699 switch(vid.renderpath)
1701 case RENDERPATH_GL11:
1702 case RENDERPATH_GL13:
1703 case RENDERPATH_GL20:
1704 case RENDERPATH_CGGL:
1706 if (gl_state.depthtest)
1708 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1712 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1715 case RENDERPATH_D3D9:
1717 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1720 case RENDERPATH_D3D10:
1721 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1723 case RENDERPATH_D3D11:
1724 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1726 case RENDERPATH_SOFT:
1727 DPSOFTRAST_DepthTest(gl_state.depthtest);
1733 void GL_DepthFunc(int state)
1735 if (gl_state.depthfunc != state)
1737 gl_state.depthfunc = state;
1738 switch(vid.renderpath)
1740 case RENDERPATH_GL11:
1741 case RENDERPATH_GL13:
1742 case RENDERPATH_GL20:
1743 case RENDERPATH_CGGL:
1745 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1747 case RENDERPATH_D3D9:
1749 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1752 case RENDERPATH_D3D10:
1753 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1755 case RENDERPATH_D3D11:
1756 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1758 case RENDERPATH_SOFT:
1759 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1765 void GL_DepthRange(float nearfrac, float farfrac)
1767 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1769 gl_state.depthrange[0] = nearfrac;
1770 gl_state.depthrange[1] = farfrac;
1771 switch(vid.renderpath)
1773 case RENDERPATH_GL11:
1774 case RENDERPATH_GL13:
1775 case RENDERPATH_GL20:
1776 case RENDERPATH_CGGL:
1777 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1779 case RENDERPATH_D3D9:
1782 D3DVIEWPORT9 d3dviewport;
1783 d3dviewport.X = gl_viewport.x;
1784 d3dviewport.Y = gl_viewport.y;
1785 d3dviewport.Width = gl_viewport.width;
1786 d3dviewport.Height = gl_viewport.height;
1787 d3dviewport.MinZ = gl_state.depthrange[0];
1788 d3dviewport.MaxZ = gl_state.depthrange[1];
1789 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1793 case RENDERPATH_D3D10:
1794 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1796 case RENDERPATH_D3D11:
1797 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1799 case RENDERPATH_SOFT:
1800 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1806 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)
1808 switch (vid.renderpath)
1810 case RENDERPATH_GL11:
1811 case RENDERPATH_GL13:
1812 case RENDERPATH_GL20:
1813 case RENDERPATH_CGGL:
1817 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1821 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1823 if (vid.support.ati_separate_stencil)
1825 qglStencilMask(writemask);CHECKGLERROR
1826 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1827 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1828 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1830 else if (vid.support.ext_stencil_two_side)
1832 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1833 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1834 qglStencilMask(writemask);CHECKGLERROR
1835 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1836 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1837 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1838 qglStencilMask(writemask);CHECKGLERROR
1839 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1840 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1843 case RENDERPATH_D3D9:
1845 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1846 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1847 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1848 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1849 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1850 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1851 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1852 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1853 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1854 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1855 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1856 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1857 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1860 case RENDERPATH_D3D10:
1861 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1863 case RENDERPATH_D3D11:
1864 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1866 case RENDERPATH_SOFT:
1867 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1872 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1874 switch (vid.renderpath)
1876 case RENDERPATH_GL11:
1877 case RENDERPATH_GL13:
1878 case RENDERPATH_GL20:
1879 case RENDERPATH_CGGL:
1883 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1887 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1889 if (vid.support.ext_stencil_two_side)
1891 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1893 qglStencilMask(writemask);CHECKGLERROR
1894 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1895 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1898 case RENDERPATH_D3D9:
1900 if (vid.support.ati_separate_stencil)
1901 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1902 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1903 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1904 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1905 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1906 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1907 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1908 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1909 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1912 case RENDERPATH_D3D10:
1913 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1915 case RENDERPATH_D3D11:
1916 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_SOFT:
1919 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1924 void GL_PolygonOffset(float planeoffset, float depthoffset)
1926 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1928 gl_state.polygonoffset[0] = planeoffset;
1929 gl_state.polygonoffset[1] = depthoffset;
1930 switch(vid.renderpath)
1932 case RENDERPATH_GL11:
1933 case RENDERPATH_GL13:
1934 case RENDERPATH_GL20:
1935 case RENDERPATH_CGGL:
1936 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1938 case RENDERPATH_D3D9:
1940 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1941 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1944 case RENDERPATH_D3D10:
1945 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1947 case RENDERPATH_D3D11:
1948 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1950 case RENDERPATH_SOFT:
1951 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1957 void GL_SetMirrorState(qboolean state)
1959 if (v_flipped_state != state)
1961 v_flipped_state = state;
1962 if (gl_state.cullface == GL_BACK)
1963 gl_state.cullface = GL_FRONT;
1964 else if (gl_state.cullface == GL_FRONT)
1965 gl_state.cullface = GL_BACK;
1968 switch(vid.renderpath)
1970 case RENDERPATH_GL11:
1971 case RENDERPATH_GL13:
1972 case RENDERPATH_GL20:
1973 case RENDERPATH_CGGL:
1974 qglCullFace(gl_state.cullface);
1976 case RENDERPATH_D3D9:
1978 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
1981 case RENDERPATH_D3D10:
1982 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1984 case RENDERPATH_D3D11:
1985 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1987 case RENDERPATH_SOFT:
1988 DPSOFTRAST_CullFace(gl_state.cullface);
1994 void GL_CullFace(int state)
1998 if(state == GL_FRONT)
2000 else if(state == GL_BACK)
2004 switch(vid.renderpath)
2006 case RENDERPATH_GL11:
2007 case RENDERPATH_GL13:
2008 case RENDERPATH_GL20:
2009 case RENDERPATH_CGGL:
2012 if (state != GL_NONE)
2014 if (!gl_state.cullfaceenable)
2016 gl_state.cullfaceenable = true;
2017 qglEnable(GL_CULL_FACE);CHECKGLERROR
2019 if (gl_state.cullface != state)
2021 gl_state.cullface = state;
2022 qglCullFace(gl_state.cullface);CHECKGLERROR
2027 if (gl_state.cullfaceenable)
2029 gl_state.cullfaceenable = false;
2030 qglDisable(GL_CULL_FACE);CHECKGLERROR
2034 case RENDERPATH_D3D9:
2036 if (gl_state.cullface != state)
2038 gl_state.cullface = state;
2039 switch(gl_state.cullface)
2042 gl_state.cullfaceenable = false;
2043 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2046 gl_state.cullfaceenable = true;
2047 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2050 gl_state.cullfaceenable = true;
2051 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2057 case RENDERPATH_D3D10:
2058 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2060 case RENDERPATH_D3D11:
2061 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2063 case RENDERPATH_SOFT:
2064 if (gl_state.cullface != state)
2066 gl_state.cullface = state;
2067 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2068 DPSOFTRAST_CullFace(gl_state.cullface);
2074 void GL_AlphaTest(int state)
2076 if (gl_state.alphatest != state)
2078 gl_state.alphatest = state;
2079 switch(vid.renderpath)
2081 case RENDERPATH_GL11:
2082 case RENDERPATH_GL13:
2083 case RENDERPATH_GL20:
2084 case RENDERPATH_CGGL:
2086 if (gl_state.alphatest)
2088 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2092 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2095 case RENDERPATH_D3D9:
2097 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2100 case RENDERPATH_D3D10:
2101 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2103 case RENDERPATH_D3D11:
2104 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2106 case RENDERPATH_SOFT:
2107 DPSOFTRAST_AlphaTest(gl_state.alphatest);
2113 void GL_AlphaFunc(int state, float value)
2115 if (gl_state.alphafunc != state || gl_state.alphafuncvalue != value)
2117 gl_state.alphafunc = state;
2118 gl_state.alphafuncvalue = value;
2119 switch(vid.renderpath)
2121 case RENDERPATH_GL11:
2122 case RENDERPATH_GL13:
2123 case RENDERPATH_GL20:
2124 case RENDERPATH_CGGL:
2126 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
2128 case RENDERPATH_D3D9:
2130 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
2131 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, value * 256.0f, 255));
2134 case RENDERPATH_D3D10:
2135 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2137 case RENDERPATH_D3D11:
2138 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2140 case RENDERPATH_SOFT:
2141 DPSOFTRAST_AlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);
2147 void GL_ColorMask(int r, int g, int b, int a)
2149 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2150 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2151 if (gl_state.colormask != state)
2153 gl_state.colormask = state;
2154 switch(vid.renderpath)
2156 case RENDERPATH_GL11:
2157 case RENDERPATH_GL13:
2158 case RENDERPATH_GL20:
2159 case RENDERPATH_CGGL:
2161 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2163 case RENDERPATH_D3D9:
2165 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2168 case RENDERPATH_D3D10:
2169 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2171 case RENDERPATH_D3D11:
2172 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2174 case RENDERPATH_SOFT:
2175 DPSOFTRAST_ColorMask(r, g, b, a);
2181 void GL_Color(float cr, float cg, float cb, float ca)
2183 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)
2185 gl_state.color4f[0] = cr;
2186 gl_state.color4f[1] = cg;
2187 gl_state.color4f[2] = cb;
2188 gl_state.color4f[3] = ca;
2189 switch(vid.renderpath)
2191 case RENDERPATH_GL11:
2192 case RENDERPATH_GL13:
2193 case RENDERPATH_GL20:
2194 case RENDERPATH_CGGL:
2196 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2199 case RENDERPATH_D3D9:
2200 case RENDERPATH_D3D10:
2201 case RENDERPATH_D3D11:
2202 // no equivalent in D3D
2204 case RENDERPATH_SOFT:
2205 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2211 void GL_Scissor (int x, int y, int width, int height)
2213 switch(vid.renderpath)
2215 case RENDERPATH_GL11:
2216 case RENDERPATH_GL13:
2217 case RENDERPATH_GL20:
2218 case RENDERPATH_CGGL:
2220 qglScissor(x, y,width,height);
2223 case RENDERPATH_D3D9:
2229 d3drect.right = x + width;
2230 d3drect.bottom = y + height;
2231 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2235 case RENDERPATH_D3D10:
2236 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2238 case RENDERPATH_D3D11:
2239 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2241 case RENDERPATH_SOFT:
2242 DPSOFTRAST_Scissor(x, y, width, height);
2247 void GL_ScissorTest(int state)
2249 if (gl_state.scissortest != state)
2251 gl_state.scissortest = state;
2252 switch(vid.renderpath)
2254 case RENDERPATH_GL11:
2255 case RENDERPATH_GL13:
2256 case RENDERPATH_GL20:
2257 case RENDERPATH_CGGL:
2259 if(gl_state.scissortest)
2260 qglEnable(GL_SCISSOR_TEST);
2262 qglDisable(GL_SCISSOR_TEST);
2265 case RENDERPATH_D3D9:
2267 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2270 case RENDERPATH_D3D10:
2271 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2273 case RENDERPATH_D3D11:
2274 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2276 case RENDERPATH_SOFT:
2277 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2283 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2285 static const float blackcolor[4] = {0, 0, 0, 0};
2286 // prevent warnings when trying to clear a buffer that does not exist
2288 colorvalue = blackcolor;
2291 mask &= ~GL_STENCIL_BUFFER_BIT;
2294 switch(vid.renderpath)
2296 case RENDERPATH_GL11:
2297 case RENDERPATH_GL13:
2298 case RENDERPATH_GL20:
2299 case RENDERPATH_CGGL:
2301 if (mask & GL_COLOR_BUFFER_BIT)
2303 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2305 if (mask & GL_DEPTH_BUFFER_BIT)
2307 qglClearDepth(depthvalue);CHECKGLERROR
2309 if (mask & GL_STENCIL_BUFFER_BIT)
2311 qglClearStencil(stencilvalue);CHECKGLERROR
2313 qglClear(mask);CHECKGLERROR
2315 case RENDERPATH_D3D9:
2317 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);
2320 case RENDERPATH_D3D10:
2321 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2323 case RENDERPATH_D3D11:
2324 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2326 case RENDERPATH_SOFT:
2327 if (mask & GL_COLOR_BUFFER_BIT)
2328 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2329 if (mask & GL_DEPTH_BUFFER_BIT)
2330 DPSOFTRAST_ClearDepth(depthvalue);
2335 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2337 switch(vid.renderpath)
2339 case RENDERPATH_GL11:
2340 case RENDERPATH_GL13:
2341 case RENDERPATH_GL20:
2342 case RENDERPATH_CGGL:
2344 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2346 case RENDERPATH_D3D9:
2349 // LordHavoc: we can't directly download the backbuffer because it may be
2350 // multisampled, and it may not be lockable, so we blit it to a lockable
2351 // surface of the same dimensions (but without multisample) to resolve the
2352 // multisample buffer to a normal image, and then lock that...
2353 IDirect3DSurface9 *stretchsurface = NULL;
2354 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2356 D3DLOCKED_RECT lockedrect;
2357 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2359 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2362 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2363 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2364 memcpy(outpixels + line * width * 4, row, width * 4);
2365 IDirect3DSurface9_UnlockRect(stretchsurface);
2368 IDirect3DSurface9_Release(stretchsurface);
2371 //IDirect3DSurface9 *syssurface = NULL;
2372 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2373 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2374 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2375 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2376 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2377 //IDirect3DSurface9_UnlockRect(syssurface);
2378 //IDirect3DSurface9_Release(syssurface);
2382 case RENDERPATH_D3D10:
2383 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2385 case RENDERPATH_D3D11:
2386 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2388 case RENDERPATH_SOFT:
2389 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2394 // called at beginning of frame
2395 void R_Mesh_Start(void)
2398 R_Mesh_ResetRenderTargets();
2400 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2402 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2403 Cvar_SetValueQuick(&gl_paranoid, 1);
2407 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2411 char compilelog[MAX_INPUTLINE];
2412 shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
2415 qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2416 qglCompileShaderARB(shaderobject);CHECKGLERROR
2417 qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
2418 qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2419 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2421 int i, j, pretextlines = 0;
2422 for (i = 0;i < numstrings - 1;i++)
2423 for (j = 0;strings[i][j];j++)
2424 if (strings[i][j] == '\n')
2426 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2428 if (!shadercompiled)
2430 qglDeleteObjectARB(shaderobject);CHECKGLERROR
2433 qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
2434 qglDeleteObjectARB(shaderobject);CHECKGLERROR
2438 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)
2440 GLint programlinked;
2441 GLuint programobject = 0;
2442 char linklog[MAX_INPUTLINE];
2445 programobject = qglCreateProgramObjectARB();CHECKGLERROR
2449 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
2452 #ifdef GL_GEOMETRY_SHADER_ARB
2453 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
2457 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
2460 qglLinkProgramARB(programobject);CHECKGLERROR
2461 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
2462 qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2465 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2466 Con_DPrintf("program link log:\n%s\n", linklog);
2467 // software vertex shader is ok but software fragment shader is WAY
2468 // too slow, fail program if so.
2469 // NOTE: this string might be ATI specific, but that's ok because the
2470 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2471 // software fragment shader due to low instruction and dependent
2473 if (strstr(linklog, "fragment shader will run in software"))
2474 programlinked = false;
2478 return programobject;
2480 qglDeleteObjectARB(programobject);CHECKGLERROR
2484 void GL_Backend_FreeProgram(unsigned int prog)
2487 qglDeleteObjectARB(prog);
2491 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2496 for (i = 0;i < count;i++)
2497 *out++ = *in++ + offset;
2500 memcpy(out, in, sizeof(*out) * count);
2503 // renders triangles using vertices from the active arrays
2504 int paranoidblah = 0;
2505 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)
2507 unsigned int numelements = numtriangles * 3;
2509 size_t bufferoffset3i;
2511 size_t bufferoffset3s;
2512 if (numvertices < 3 || numtriangles < 1)
2514 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2515 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);
2518 if (!gl_mesh_prefer_short_elements.integer)
2522 if (element3i_indexbuffer)
2523 element3i_indexbuffer = NULL;
2525 // adjust the pointers for firsttriangle
2527 element3i += firsttriangle * 3;
2528 if (element3i_indexbuffer)
2529 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2531 element3s += firsttriangle * 3;
2532 if (element3s_indexbuffer)
2533 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2534 switch(vid.renderpath)
2536 case RENDERPATH_GL11:
2537 case RENDERPATH_GL13:
2538 case RENDERPATH_GL20:
2539 case RENDERPATH_CGGL:
2540 // check if the user specified to ignore static index buffers
2541 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2543 element3i_indexbuffer = NULL;
2544 element3s_indexbuffer = NULL;
2547 case RENDERPATH_D3D9:
2548 case RENDERPATH_D3D10:
2549 case RENDERPATH_D3D11:
2551 case RENDERPATH_SOFT:
2554 // upload a dynamic index buffer if needed
2557 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2559 if (gl_state.draw_dynamicindexbuffer)
2560 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2562 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2563 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2564 element3s_bufferoffset = 0;
2569 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2571 if (gl_state.draw_dynamicindexbuffer)
2572 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2574 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2575 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2576 element3i_bufferoffset = 0;
2579 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2580 bufferoffset3i = element3i_bufferoffset;
2581 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2582 bufferoffset3s = element3s_bufferoffset;
2583 r_refdef.stats.draws++;
2584 r_refdef.stats.draws_vertices += numvertices;
2585 r_refdef.stats.draws_elements += numelements;
2586 if (gl_paranoid.integer)
2589 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2591 unsigned int j, size;
2593 // note: there's no validation done here on buffer objects because it
2594 // is somewhat difficult to get at the data, and gl_paranoid can be
2595 // used without buffer objects if the need arises
2596 // (the data could be gotten using glMapBuffer but it would be very
2597 // slow due to uncachable video memory reads)
2598 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2599 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2601 if (gl_state.pointer_vertex_pointer)
2602 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2604 if (gl_state.pointer_color_enabled)
2606 if (!qglIsEnabled(GL_COLOR_ARRAY))
2607 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2609 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2610 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2613 for (i = 0;i < vid.texarrayunits;i++)
2615 if (gl_state.units[i].arrayenabled)
2617 GL_ClientActiveTexture(i);
2618 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2619 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2621 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2622 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++)
2629 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2631 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2633 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2640 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2642 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2644 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2650 if (r_render.integer || r_refdef.draw2dstage)
2652 switch(vid.renderpath)
2654 case RENDERPATH_GL11:
2655 case RENDERPATH_GL13:
2656 case RENDERPATH_GL20:
2657 case RENDERPATH_CGGL:
2659 if (gl_mesh_testmanualfeeding.integer)
2661 unsigned int i, j, element;
2663 qglBegin(GL_TRIANGLES);
2664 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2667 element = element3i[i];
2669 element = element3s[i];
2671 element = firstvertex + i;
2672 for (j = 0;j < vid.texarrayunits;j++)
2674 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2676 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2678 p = (const GLfloat *)((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, p[0], p[1], p[2], p[3]);
2683 else if (gl_state.units[j].pointer_texcoord_components == 3)
2684 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2685 else if (gl_state.units[j].pointer_texcoord_components == 2)
2686 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2688 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2692 if (gl_state.units[j].pointer_texcoord_components == 4)
2693 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2694 else if (gl_state.units[j].pointer_texcoord_components == 3)
2695 qglTexCoord3f(p[0], p[1], p[2]);
2696 else if (gl_state.units[j].pointer_texcoord_components == 2)
2697 qglTexCoord2f(p[0], p[1]);
2699 qglTexCoord1f(p[0]);
2702 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2704 const GLshort *s = (const GLshort *)((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, s[0], s[1], s[2], s[3]);
2709 else if (gl_state.units[j].pointer_texcoord_components == 3)
2710 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2711 else if (gl_state.units[j].pointer_texcoord_components == 2)
2712 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2713 else if (gl_state.units[j].pointer_texcoord_components == 1)
2714 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2718 if (gl_state.units[j].pointer_texcoord_components == 4)
2719 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2720 else if (gl_state.units[j].pointer_texcoord_components == 3)
2721 qglTexCoord3f(s[0], s[1], s[2]);
2722 else if (gl_state.units[j].pointer_texcoord_components == 2)
2723 qglTexCoord2f(s[0], s[1]);
2724 else if (gl_state.units[j].pointer_texcoord_components == 1)
2725 qglTexCoord1f(s[0]);
2728 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2730 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2731 if (vid.texarrayunits > 1)
2733 if (gl_state.units[j].pointer_texcoord_components == 4)
2734 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2735 else if (gl_state.units[j].pointer_texcoord_components == 3)
2736 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2737 else if (gl_state.units[j].pointer_texcoord_components == 2)
2738 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2739 else if (gl_state.units[j].pointer_texcoord_components == 1)
2740 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2744 if (gl_state.units[j].pointer_texcoord_components == 4)
2745 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2746 else if (gl_state.units[j].pointer_texcoord_components == 3)
2747 qglTexCoord3f(sb[0], sb[1], sb[2]);
2748 else if (gl_state.units[j].pointer_texcoord_components == 2)
2749 qglTexCoord2f(sb[0], sb[1]);
2750 else if (gl_state.units[j].pointer_texcoord_components == 1)
2751 qglTexCoord1f(sb[0]);
2756 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2758 if (gl_state.pointer_color_gltype == GL_FLOAT)
2760 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2761 qglColor4f(p[0], p[1], p[2], p[3]);
2763 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2765 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2766 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2769 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2771 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2772 if (gl_state.pointer_vertex_components == 4)
2773 qglVertex4f(p[0], p[1], p[2], p[3]);
2774 else if (gl_state.pointer_vertex_components == 3)
2775 qglVertex3f(p[0], p[1], p[2]);
2777 qglVertex2f(p[0], p[1]);
2783 else if (bufferobject3s)
2785 GL_BindEBO(bufferobject3s);
2786 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2788 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2793 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2797 else if (bufferobject3i)
2799 GL_BindEBO(bufferobject3i);
2800 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2802 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2807 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2814 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2816 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2821 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2828 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2830 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2835 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2841 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2845 case RENDERPATH_D3D9:
2847 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2849 if (element3s_indexbuffer)
2851 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2852 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2854 else if (element3i_indexbuffer)
2856 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2857 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2860 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2865 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2867 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2869 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2873 case RENDERPATH_D3D10:
2874 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2876 case RENDERPATH_D3D11:
2877 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2879 case RENDERPATH_SOFT:
2880 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2886 // restores backend state, used when done with 3D rendering
2887 void R_Mesh_Finish(void)
2889 R_Mesh_ResetRenderTargets();
2892 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2894 r_meshbuffer_t *buffer;
2895 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2897 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2898 memset(buffer, 0, sizeof(*buffer));
2899 buffer->bufferobject = 0;
2900 buffer->devicebuffer = NULL;
2902 buffer->isindexbuffer = isindexbuffer;
2903 buffer->isdynamic = isdynamic;
2904 buffer->isindex16 = isindex16;
2905 strlcpy(buffer->name, name, sizeof(buffer->name));
2906 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2910 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
2914 if (buffer->isindexbuffer)
2916 r_refdef.stats.indexbufferuploadcount++;
2917 r_refdef.stats.indexbufferuploadsize += size;
2921 r_refdef.stats.vertexbufferuploadcount++;
2922 r_refdef.stats.vertexbufferuploadsize += size;
2924 switch(vid.renderpath)
2926 case RENDERPATH_GL11:
2927 case RENDERPATH_GL13:
2928 case RENDERPATH_GL20:
2929 case RENDERPATH_CGGL:
2930 if (!buffer->bufferobject)
2931 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
2932 if (buffer->isindexbuffer)
2933 GL_BindEBO(buffer->bufferobject);
2935 GL_BindVBO(buffer->bufferobject);
2936 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
2938 case RENDERPATH_D3D9:
2942 void *datapointer = NULL;
2943 if (buffer->isindexbuffer)
2945 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
2946 if (size > buffer->size || !buffer->devicebuffer)
2948 if (buffer->devicebuffer)
2949 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
2950 buffer->devicebuffer = NULL;
2951 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)))
2952 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);
2953 buffer->devicebuffer = (void *)d3d9indexbuffer;
2954 buffer->size = size;
2956 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2959 memcpy(datapointer, data, size);
2961 memset(datapointer, 0, size);
2962 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
2967 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
2968 if (size > buffer->size || !buffer->devicebuffer)
2970 if (buffer->devicebuffer)
2971 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
2972 buffer->devicebuffer = NULL;
2973 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
2974 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);
2975 buffer->devicebuffer = (void *)d3d9vertexbuffer;
2976 buffer->size = size;
2978 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2981 memcpy(datapointer, data, size);
2983 memset(datapointer, 0, size);
2984 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
2990 case RENDERPATH_D3D10:
2991 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2993 case RENDERPATH_D3D11:
2994 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2996 case RENDERPATH_SOFT:
3001 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3005 switch(vid.renderpath)
3007 case RENDERPATH_GL11:
3008 case RENDERPATH_GL13:
3009 case RENDERPATH_GL20:
3010 case RENDERPATH_CGGL:
3011 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3013 case RENDERPATH_D3D9:
3015 if (gl_state.d3dvertexbuffer == (void *)buffer)
3016 gl_state.d3dvertexbuffer = NULL;
3017 if (buffer->devicebuffer)
3019 if (buffer->isindexbuffer)
3020 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3022 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3023 buffer->devicebuffer = NULL;
3027 case RENDERPATH_D3D10:
3028 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3030 case RENDERPATH_D3D11:
3031 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3033 case RENDERPATH_SOFT:
3036 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3039 void GL_Mesh_ListVBOs(qboolean printeach)
3042 size_t ebocount = 0, ebomemory = 0;
3043 size_t vbocount = 0, vbomemory = 0;
3044 r_meshbuffer_t *buffer;
3045 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3046 for (i = 0;i < endindex;i++)
3048 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3051 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)");}
3052 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)");}
3054 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);
3059 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3061 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3062 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)
3064 gl_state.pointer_vertex_components = components;
3065 gl_state.pointer_vertex_gltype = gltype;
3066 gl_state.pointer_vertex_stride = stride;
3067 gl_state.pointer_vertex_pointer = pointer;
3068 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3069 gl_state.pointer_vertex_offset = bufferoffset;
3071 GL_BindVBO(bufferobject);
3072 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3076 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3078 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3079 // the pointer only.
3082 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3083 // caller wants color array enabled
3084 if (!gl_state.pointer_color_enabled)
3086 gl_state.pointer_color_enabled = true;
3088 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3090 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)
3092 gl_state.pointer_color_components = components;
3093 gl_state.pointer_color_gltype = gltype;
3094 gl_state.pointer_color_stride = stride;
3095 gl_state.pointer_color_pointer = pointer;
3096 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3097 gl_state.pointer_color_offset = bufferoffset;
3099 GL_BindVBO(bufferobject);
3100 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3105 // caller wants color array disabled
3106 if (gl_state.pointer_color_enabled)
3108 gl_state.pointer_color_enabled = false;
3110 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3111 // when color array is on the glColor gets trashed, set it again
3112 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3117 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)
3119 gltextureunit_t *unit = gl_state.units + unitnum;
3120 // update array settings
3122 // note: there is no need to check bufferobject here because all cases
3123 // that involve a valid bufferobject also supply a texcoord array
3126 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3127 // texture array unit is enabled, enable the array
3128 if (!unit->arrayenabled)
3130 unit->arrayenabled = true;
3131 GL_ClientActiveTexture(unitnum);
3132 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3135 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)
3137 unit->pointer_texcoord_components = components;
3138 unit->pointer_texcoord_gltype = gltype;
3139 unit->pointer_texcoord_stride = stride;
3140 unit->pointer_texcoord_pointer = pointer;
3141 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3142 unit->pointer_texcoord_offset = bufferoffset;
3143 GL_ClientActiveTexture(unitnum);
3144 GL_BindVBO(bufferobject);
3145 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3150 // texture array unit is disabled, disable the array
3151 if (unit->arrayenabled)
3153 unit->arrayenabled = false;
3154 GL_ClientActiveTexture(unitnum);
3155 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3160 int R_Mesh_TexBound(unsigned int unitnum, int id)
3162 gltextureunit_t *unit = gl_state.units + unitnum;
3163 if (unitnum >= vid.teximageunits)
3165 if (id == GL_TEXTURE_2D)
3167 if (id == GL_TEXTURE_3D)
3169 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3170 return unit->tcubemap;
3174 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3176 switch(vid.renderpath)
3178 case RENDERPATH_GL11:
3179 case RENDERPATH_GL13:
3180 case RENDERPATH_GL20:
3181 case RENDERPATH_CGGL:
3182 R_Mesh_TexBind(0, tex);
3183 GL_ActiveTexture(0);CHECKGLERROR
3184 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3186 case RENDERPATH_D3D9:
3189 IDirect3DSurface9 *currentsurface = NULL;
3190 IDirect3DSurface9 *texturesurface = NULL;
3193 sourcerect.left = sx;
3194 sourcerect.top = sy;
3195 sourcerect.right = sx + width;
3196 sourcerect.bottom = sy + height;
3199 destrect.right = tx + width;
3200 destrect.bottom = ty + height;
3201 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3203 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3205 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3206 IDirect3DSurface9_Release(currentsurface);
3208 IDirect3DSurface9_Release(texturesurface);
3213 case RENDERPATH_D3D10:
3214 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3216 case RENDERPATH_D3D11:
3217 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3219 case RENDERPATH_SOFT:
3220 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3226 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};
3229 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3231 gltextureunit_t *unit = gl_state.units + unitnum;
3232 int tex2d, tex3d, texcubemap, texnum;
3233 if (unitnum >= vid.teximageunits)
3235 // if (unit->texture == tex)
3237 switch(vid.renderpath)
3239 case RENDERPATH_GL20:
3240 case RENDERPATH_CGGL:
3243 tex = r_texture_white;
3244 // not initialized enough yet...
3248 unit->texture = tex;
3249 texnum = R_GetTexture(tex);
3250 switch(tex->gltexturetypeenum)
3252 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3253 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3254 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;
3257 case RENDERPATH_GL13:
3258 case RENDERPATH_GL11:
3259 unit->texture = tex;
3265 texnum = R_GetTexture(tex);
3266 switch(tex->gltexturetypeenum)
3274 case GL_TEXTURE_CUBE_MAP_ARB:
3275 texcubemap = texnum;
3279 // update 2d texture binding
3280 if (unit->t2d != tex2d)
3282 GL_ActiveTexture(unitnum);
3287 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3294 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3298 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3300 // update 3d texture binding
3301 if (unit->t3d != tex3d)
3303 GL_ActiveTexture(unitnum);
3308 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3315 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3319 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3321 // update cubemap texture binding
3322 if (unit->tcubemap != texcubemap)
3324 GL_ActiveTexture(unitnum);
3327 if (unit->tcubemap == 0)
3329 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3336 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3339 unit->tcubemap = texcubemap;
3340 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3343 case RENDERPATH_D3D9:
3346 extern cvar_t gl_texture_anisotropy;
3349 tex = r_texture_white;
3350 // not initialized enough yet...
3354 if (unit->texture == tex)
3356 unit->texture = tex;
3357 // upload texture if needed
3359 R_RealGetTexture(tex);
3360 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3361 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3362 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3363 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3364 if (tex->d3daddressw)
3365 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3366 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3367 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3368 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3369 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3370 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3371 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3375 case RENDERPATH_D3D10:
3376 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3378 case RENDERPATH_D3D11:
3379 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3381 case RENDERPATH_SOFT:
3384 tex = r_texture_white;
3385 // not initialized enough yet...
3389 if (unit->texture == tex)
3391 unit->texture = tex;
3392 DPSOFTRAST_SetTexture(unitnum, R_GetTexture(tex));
3397 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3399 gltextureunit_t *unit = gl_state.units + unitnum;
3400 switch(vid.renderpath)
3402 case RENDERPATH_GL11:
3403 case RENDERPATH_GL13:
3404 case RENDERPATH_GL20:
3405 case RENDERPATH_CGGL:
3406 if (matrix && matrix->m[3][3])
3408 // texmatrix specified, check if it is different
3409 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3412 unit->texmatrixenabled = true;
3413 unit->matrix = *matrix;
3415 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3416 GL_ActiveTexture(unitnum);
3417 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3418 qglLoadMatrixf(glmatrix);CHECKGLERROR
3419 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3424 // no texmatrix specified, revert to identity
3425 if (unit->texmatrixenabled)
3427 unit->texmatrixenabled = false;
3428 unit->matrix = identitymatrix;
3430 GL_ActiveTexture(unitnum);
3431 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3432 qglLoadIdentity();CHECKGLERROR
3433 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3437 case RENDERPATH_D3D9:
3438 case RENDERPATH_D3D10:
3439 case RENDERPATH_D3D11:
3441 case RENDERPATH_SOFT:
3446 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3448 gltextureunit_t *unit = gl_state.units + unitnum;
3450 switch(vid.renderpath)
3452 case RENDERPATH_GL20:
3453 case RENDERPATH_CGGL:
3456 case RENDERPATH_GL13:
3457 // GL_ARB_texture_env_combine
3459 combinergb = GL_MODULATE;
3461 combinealpha = GL_MODULATE;
3466 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3468 if (combinergb == GL_DECAL)
3469 combinergb = GL_INTERPOLATE_ARB;
3470 if (unit->combine != GL_COMBINE_ARB)
3472 unit->combine = GL_COMBINE_ARB;
3473 GL_ActiveTexture(unitnum);
3474 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3475 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3477 if (unit->combinergb != combinergb)
3479 unit->combinergb = combinergb;
3480 GL_ActiveTexture(unitnum);
3481 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3483 if (unit->combinealpha != combinealpha)
3485 unit->combinealpha = combinealpha;
3486 GL_ActiveTexture(unitnum);
3487 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3489 if (unit->rgbscale != rgbscale)
3491 unit->rgbscale = rgbscale;
3492 GL_ActiveTexture(unitnum);
3493 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3495 if (unit->alphascale != alphascale)
3497 unit->alphascale = alphascale;
3498 GL_ActiveTexture(unitnum);
3499 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3504 if (unit->combine != combinergb)
3506 unit->combine = combinergb;
3507 GL_ActiveTexture(unitnum);
3508 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3512 case RENDERPATH_GL11:
3515 combinergb = GL_MODULATE;
3516 if (unit->combine != combinergb)
3518 unit->combine = combinergb;
3519 GL_ActiveTexture(unitnum);
3520 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3523 case RENDERPATH_D3D9:
3524 case RENDERPATH_D3D10:
3525 case RENDERPATH_D3D11:
3527 case RENDERPATH_SOFT:
3532 void R_Mesh_ResetTextureState(void)
3534 unsigned int unitnum;
3539 switch(vid.renderpath)
3541 case RENDERPATH_GL20:
3542 case RENDERPATH_CGGL:
3543 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3545 gltextureunit_t *unit = gl_state.units + unitnum;
3549 GL_ActiveTexture(unitnum);
3550 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3555 GL_ActiveTexture(unitnum);
3556 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3561 GL_ActiveTexture(unitnum);
3562 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3565 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3567 gltextureunit_t *unit = gl_state.units + unitnum;
3568 if (unit->arrayenabled)
3570 unit->arrayenabled = false;
3571 GL_ClientActiveTexture(unitnum);
3572 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3575 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3577 gltextureunit_t *unit = gl_state.units + unitnum;
3578 if (unit->texmatrixenabled)
3580 unit->texmatrixenabled = false;
3581 unit->matrix = identitymatrix;
3583 GL_ActiveTexture(unitnum);
3584 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3585 qglLoadIdentity();CHECKGLERROR
3586 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3590 case RENDERPATH_GL13:
3591 case RENDERPATH_GL11:
3592 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3594 gltextureunit_t *unit = gl_state.units + unitnum;
3598 GL_ActiveTexture(unitnum);
3599 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3600 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3605 GL_ActiveTexture(unitnum);
3606 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3607 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3612 GL_ActiveTexture(unitnum);
3613 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3614 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3616 if (unit->arrayenabled)
3618 unit->arrayenabled = false;
3619 GL_ClientActiveTexture(unitnum);
3620 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3622 if (unit->texmatrixenabled)
3624 unit->texmatrixenabled = false;
3625 unit->matrix = identitymatrix;
3627 GL_ActiveTexture(unitnum);
3628 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3629 qglLoadIdentity();CHECKGLERROR
3630 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3632 if (unit->combine != GL_MODULATE)
3634 unit->combine = GL_MODULATE;
3635 GL_ActiveTexture(unitnum);
3636 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3640 case RENDERPATH_D3D9:
3641 case RENDERPATH_D3D10:
3642 case RENDERPATH_D3D11:
3644 case RENDERPATH_SOFT:
3652 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3653 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3654 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3656 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3658 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3662 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3664 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3665 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3666 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3670 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3672 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3673 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3674 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3675 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3676 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3677 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3678 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3682 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3683 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3684 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3687 static void R_Mesh_InitVertexDeclarations(void)
3690 r_vertex3f_d3d9decl = NULL;
3691 r_vertexgeneric_d3d9decl = NULL;
3692 r_vertexmesh_d3d9decl = NULL;
3693 switch(vid.renderpath)
3695 case RENDERPATH_GL20:
3696 case RENDERPATH_CGGL:
3697 case RENDERPATH_GL13:
3698 case RENDERPATH_GL11:
3700 case RENDERPATH_D3D9:
3701 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3702 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3703 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3705 case RENDERPATH_D3D10:
3706 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3708 case RENDERPATH_D3D11:
3709 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3711 case RENDERPATH_SOFT:
3717 static void R_Mesh_DestroyVertexDeclarations(void)
3720 if (r_vertex3f_d3d9decl)
3721 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3722 r_vertex3f_d3d9decl = NULL;
3723 if (r_vertexgeneric_d3d9decl)
3724 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3725 r_vertexgeneric_d3d9decl = NULL;
3726 if (r_vertexmesh_d3d9decl)
3727 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3728 r_vertexmesh_d3d9decl = NULL;
3732 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3734 // upload temporary vertexbuffer for this rendering
3735 if (!gl_state.usevbo_staticvertex)
3736 vertexbuffer = NULL;
3737 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3739 if (gl_state.preparevertices_dynamicvertexbuffer)
3740 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3742 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3743 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3745 switch(vid.renderpath)
3747 case RENDERPATH_GL20:
3748 case RENDERPATH_CGGL:
3751 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3752 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3753 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3754 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3755 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3756 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3757 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3761 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3762 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3763 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3764 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3765 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3766 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3767 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3770 case RENDERPATH_GL13:
3773 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3774 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3775 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3776 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3780 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3781 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3782 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3783 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3786 case RENDERPATH_GL11:
3789 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3790 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3791 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3795 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3796 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3797 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3800 case RENDERPATH_D3D9:
3802 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3804 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3806 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3807 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3808 gl_state.d3dvertexdata = (void *)vertex3f;
3809 gl_state.d3dvertexsize = sizeof(float[3]);
3812 case RENDERPATH_D3D10:
3813 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3815 case RENDERPATH_D3D11:
3816 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3818 case RENDERPATH_SOFT:
3819 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3820 DPSOFTRAST_SetColorPointer(NULL, 0);
3821 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3822 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3823 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3824 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3825 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3832 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3835 size = sizeof(r_vertexgeneric_t) * numvertices;
3836 if (gl_state.preparevertices_tempdatamaxsize < size)
3838 gl_state.preparevertices_tempdatamaxsize = size;
3839 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3841 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3842 gl_state.preparevertices_numvertices = numvertices;
3843 return gl_state.preparevertices_vertexgeneric;
3846 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
3848 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
3849 gl_state.preparevertices_vertexgeneric = NULL;
3850 gl_state.preparevertices_numvertices = 0;
3854 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
3857 r_vertexgeneric_t *vertex;
3858 switch(vid.renderpath)
3860 case RENDERPATH_GL20:
3861 case RENDERPATH_CGGL:
3862 if (!vid.useinterleavedarrays)
3864 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3865 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3866 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3867 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3868 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3869 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3870 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3874 case RENDERPATH_GL13:
3875 case RENDERPATH_GL11:
3876 if (!vid.useinterleavedarrays)
3878 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3879 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3880 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3881 if (vid.texunits >= 2)
3882 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3883 if (vid.texunits >= 3)
3884 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3888 case RENDERPATH_D3D9:
3889 case RENDERPATH_D3D10:
3890 case RENDERPATH_D3D11:
3892 case RENDERPATH_SOFT:
3893 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3894 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
3895 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
3896 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3897 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3898 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3899 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3903 // no quick path for this case, convert to vertex structs
3904 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
3905 for (i = 0;i < numvertices;i++)
3906 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3909 for (i = 0;i < numvertices;i++)
3910 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
3914 float tempcolor4f[4];
3915 unsigned char tempcolor4ub[4];
3916 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
3917 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
3918 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
3919 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
3920 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
3921 for (i = 0;i < numvertices;i++)
3922 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
3925 for (i = 0;i < numvertices;i++)
3926 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
3927 R_Mesh_PrepareVertices_Generic_Unlock();
3928 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
3931 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
3933 // upload temporary vertexbuffer for this rendering
3934 if (!gl_state.usevbo_staticvertex)
3935 vertexbuffer = NULL;
3936 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3938 if (gl_state.preparevertices_dynamicvertexbuffer)
3939 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
3941 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
3942 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3944 switch(vid.renderpath)
3946 case RENDERPATH_GL20:
3947 case RENDERPATH_CGGL:
3950 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3951 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3952 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3953 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3954 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3955 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3956 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3960 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3961 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3962 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3963 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3964 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3965 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3966 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3969 case RENDERPATH_GL13:
3972 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3973 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3974 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3975 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3979 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3980 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3981 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3982 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3985 case RENDERPATH_GL11:
3988 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3989 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3990 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3994 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3995 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3996 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3999 case RENDERPATH_D3D9:
4001 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4003 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4005 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4006 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4007 gl_state.d3dvertexdata = (void *)vertex;
4008 gl_state.d3dvertexsize = sizeof(*vertex);
4011 case RENDERPATH_D3D10:
4012 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4014 case RENDERPATH_D3D11:
4015 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4017 case RENDERPATH_SOFT:
4018 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4019 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4020 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4021 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4022 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4023 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4024 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4031 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4034 size = sizeof(r_vertexmesh_t) * numvertices;
4035 if (gl_state.preparevertices_tempdatamaxsize < size)
4037 gl_state.preparevertices_tempdatamaxsize = size;
4038 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4040 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4041 gl_state.preparevertices_numvertices = numvertices;
4042 return gl_state.preparevertices_vertexmesh;
4045 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4047 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4048 gl_state.preparevertices_vertexmesh = NULL;
4049 gl_state.preparevertices_numvertices = 0;
4053 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)
4056 r_vertexmesh_t *vertex;
4057 switch(vid.renderpath)
4059 case RENDERPATH_GL20:
4060 case RENDERPATH_CGGL:
4061 if (!vid.useinterleavedarrays)
4063 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4064 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4065 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4066 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4067 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4068 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4069 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4073 case RENDERPATH_GL13:
4074 case RENDERPATH_GL11:
4075 if (!vid.useinterleavedarrays)
4077 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4078 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4079 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4080 if (vid.texunits >= 2)
4081 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4082 if (vid.texunits >= 3)
4083 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4087 case RENDERPATH_D3D9:
4088 case RENDERPATH_D3D10:
4089 case RENDERPATH_D3D11:
4091 case RENDERPATH_SOFT:
4092 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4093 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4094 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4095 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4096 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4097 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4098 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4102 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4103 for (i = 0;i < numvertices;i++)
4104 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4106 for (i = 0;i < numvertices;i++)
4107 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4109 for (i = 0;i < numvertices;i++)
4110 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4112 for (i = 0;i < numvertices;i++)
4113 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4116 for (i = 0;i < numvertices;i++)
4117 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
4121 float tempcolor4f[4];
4122 unsigned char tempcolor4ub[4];
4123 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
4124 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
4125 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
4126 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
4127 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
4128 for (i = 0;i < numvertices;i++)
4129 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
4131 if (texcoordtexture2f)
4132 for (i = 0;i < numvertices;i++)
4133 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4134 if (texcoordlightmap2f)
4135 for (i = 0;i < numvertices;i++)
4136 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4137 R_Mesh_PrepareVertices_Mesh_Unlock();
4138 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4141 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4143 // upload temporary vertexbuffer for this rendering
4144 if (!gl_state.usevbo_staticvertex)
4145 vertexbuffer = NULL;
4146 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4148 if (gl_state.preparevertices_dynamicvertexbuffer)
4149 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4151 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4152 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4154 switch(vid.renderpath)
4156 case RENDERPATH_GL20:
4157 case RENDERPATH_CGGL:
4160 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4161 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4162 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4163 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4164 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4165 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4166 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4170 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4171 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4172 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4173 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4174 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4175 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4176 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4179 case RENDERPATH_GL13:
4182 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4183 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4184 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4185 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4189 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4190 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4191 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4192 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4195 case RENDERPATH_GL11:
4198 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4199 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4200 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4204 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4205 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4206 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4209 case RENDERPATH_D3D9:
4211 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4213 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4215 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4216 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4217 gl_state.d3dvertexdata = (void *)vertex;
4218 gl_state.d3dvertexsize = sizeof(*vertex);
4221 case RENDERPATH_D3D10:
4222 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4224 case RENDERPATH_D3D11:
4225 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4227 case RENDERPATH_SOFT:
4228 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4229 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4230 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4231 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4232 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4233 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4234 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);