3 #include "cl_collision.h"
4 #include "dpsoftrast.h"
7 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
8 extern D3DCAPS9 vid_d3d9caps;
11 #define MAX_RENDERTARGETS 4
13 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
14 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
15 cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
16 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
17 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
19 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
20 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
21 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
22 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
23 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
24 cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
25 cvar_t gl_vbo_dynamicvertex = {CVAR_SAVE, "gl_vbo_dynamicvertex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
26 cvar_t gl_vbo_dynamicindex = {CVAR_SAVE, "gl_vbo_dynamicindex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
27 cvar_t gl_fbo = {CVAR_SAVE, "gl_fbo", "1", "make use of GL_ARB_framebuffer_object extension to enable shadowmaps and other features using pixel formats different from the framebuffer"};
29 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
30 qboolean v_flipped_state = false;
32 r_viewport_t gl_viewport;
33 matrix4x4_t gl_modelmatrix;
34 matrix4x4_t gl_viewmatrix;
35 matrix4x4_t gl_modelviewmatrix;
36 matrix4x4_t gl_projectionmatrix;
37 matrix4x4_t gl_modelviewprojectionmatrix;
38 float gl_modelview16f[16];
39 float gl_modelviewprojection16f[16];
40 qboolean gl_modelmatrixchanged;
42 int gl_maxdrawrangeelementsvertices;
43 int gl_maxdrawrangeelementsindices;
48 void GL_PrintError(int errornumber, const char *filename, int linenumber)
52 #ifdef GL_INVALID_ENUM
54 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
57 #ifdef GL_INVALID_VALUE
58 case GL_INVALID_VALUE:
59 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
62 #ifdef GL_INVALID_OPERATION
63 case GL_INVALID_OPERATION:
64 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
67 #ifdef GL_STACK_OVERFLOW
68 case GL_STACK_OVERFLOW:
69 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
72 #ifdef GL_STACK_UNDERFLOW
73 case GL_STACK_UNDERFLOW:
74 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
77 #ifdef GL_OUT_OF_MEMORY
78 case GL_OUT_OF_MEMORY:
79 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
82 #ifdef GL_TABLE_TOO_LARGE
83 case GL_TABLE_TOO_LARGE:
84 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
87 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
88 case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
89 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
93 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
99 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
101 void SCR_ScreenShot_f (void);
103 typedef struct gltextureunit_s
105 int pointer_texcoord_components;
106 int pointer_texcoord_gltype;
107 size_t pointer_texcoord_stride;
108 const void *pointer_texcoord_pointer;
109 const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
110 size_t pointer_texcoord_offset;
113 int t2d, t3d, tcubemap;
115 int rgbscale, alphascale;
117 int combinergb, combinealpha;
118 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
119 int texmatrixenabled;
124 typedef struct gl_state_s
132 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
136 float polygonoffset[2];
139 float alphafuncvalue;
142 unsigned int clientunit;
143 gltextureunit_t units[MAX_TEXTUREUNITS];
147 int vertexbufferobject;
148 int elementbufferobject;
149 int framebufferobject;
150 int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
151 qboolean pointer_color_enabled;
153 int pointer_vertex_components;
154 int pointer_vertex_gltype;
155 size_t pointer_vertex_stride;
156 const void *pointer_vertex_pointer;
157 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
158 size_t pointer_vertex_offset;
160 int pointer_color_components;
161 int pointer_color_gltype;
162 size_t pointer_color_stride;
163 const void *pointer_color_pointer;
164 const r_meshbuffer_t *pointer_color_vertexbuffer;
165 size_t pointer_color_offset;
167 void *preparevertices_tempdata;
168 size_t preparevertices_tempdatamaxsize;
169 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
170 r_vertexgeneric_t *preparevertices_vertexgeneric;
171 r_vertexmesh_t *preparevertices_vertexmesh;
172 int preparevertices_numvertices;
174 r_meshbuffer_t *draw_dynamicindexbuffer;
176 qboolean usevbo_staticvertex;
177 qboolean usevbo_staticindex;
178 qboolean usevbo_dynamicvertex;
179 qboolean usevbo_dynamicindex;
181 memexpandablearray_t meshbufferarray;
186 // rtexture_t *d3drt_depthtexture;
187 // rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
188 IDirect3DSurface9 *d3drt_depthsurface;
189 IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
190 IDirect3DSurface9 *d3drt_backbufferdepthsurface;
191 IDirect3DSurface9 *d3drt_backbuffercolorsurface;
192 void *d3dvertexbuffer;
194 size_t d3dvertexsize;
199 static gl_state_t gl_state;
203 note: here's strip order for a terrain row:
210 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
212 *elements++ = i + row;
214 *elements++ = i + row + 1;
217 *elements++ = i + row + 1;
220 for (y = 0;y < rows - 1;y++)
222 for (x = 0;x < columns - 1;x++)
225 *elements++ = i + columns;
227 *elements++ = i + columns + 1;
230 *elements++ = i + columns + 1;
241 for (y = 0;y < rows - 1;y++)
243 for (x = 0;x < columns - 1;x++)
247 *elements++ = i + columns;
248 *elements++ = i + columns + 1;
249 *elements++ = i + columns;
250 *elements++ = i + columns + 1;
256 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
257 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
258 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
259 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
261 void GL_VBOStats_f(void)
263 GL_Mesh_ListVBOs(true);
266 static void GL_Backend_ResetState(void);
268 static void R_Mesh_InitVertexDeclarations(void);
269 static void R_Mesh_DestroyVertexDeclarations(void);
271 static void R_Mesh_SetUseVBO(void)
273 switch(vid.renderpath)
275 case RENDERPATH_GL11:
276 case RENDERPATH_GL13:
277 case RENDERPATH_GL20:
278 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;
299 case RENDERPATH_GLES2:
300 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
301 gl_state.usevbo_staticindex = false;
302 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
303 gl_state.usevbo_dynamicindex = false;
308 static void gl_backend_start(void)
310 memset(&gl_state, 0, sizeof(gl_state));
312 R_Mesh_InitVertexDeclarations();
315 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
317 Con_DPrintf("OpenGL backend started.\n");
321 GL_Backend_ResetState();
323 switch(vid.renderpath)
325 case RENDERPATH_GL11:
326 case RENDERPATH_GL13:
327 case RENDERPATH_GL20:
328 case RENDERPATH_GLES2:
329 // fetch current fbo here (default fbo is not 0 on some GLES devices)
330 if (vid.support.ext_framebuffer_object)
331 qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
333 case RENDERPATH_D3D9:
335 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
336 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
339 case RENDERPATH_D3D10:
340 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
342 case RENDERPATH_D3D11:
343 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
345 case RENDERPATH_SOFT:
350 static void gl_backend_shutdown(void)
352 Con_DPrint("OpenGL Backend shutting down\n");
354 switch(vid.renderpath)
356 case RENDERPATH_GL11:
357 case RENDERPATH_GL13:
358 case RENDERPATH_GL20:
359 case RENDERPATH_SOFT:
360 case RENDERPATH_GLES2:
362 case RENDERPATH_D3D9:
364 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
365 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
368 case RENDERPATH_D3D10:
369 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
371 case RENDERPATH_D3D11:
372 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
376 if (gl_state.preparevertices_tempdata)
377 Mem_Free(gl_state.preparevertices_tempdata);
378 if (gl_state.preparevertices_dynamicvertexbuffer)
379 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
381 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
383 R_Mesh_DestroyVertexDeclarations();
385 memset(&gl_state, 0, sizeof(gl_state));
388 static void gl_backend_newmap(void)
392 static void gl_backend_devicelost(void)
395 r_meshbuffer_t *buffer;
397 gl_state.d3dvertexbuffer = NULL;
399 switch(vid.renderpath)
401 case RENDERPATH_GL11:
402 case RENDERPATH_GL13:
403 case RENDERPATH_GL20:
404 case RENDERPATH_SOFT:
405 case RENDERPATH_GLES2:
407 case RENDERPATH_D3D9:
409 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
410 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
413 case RENDERPATH_D3D10:
414 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
416 case RENDERPATH_D3D11:
417 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
420 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
421 for (i = 0;i < endindex;i++)
423 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
424 if (!buffer || !buffer->isdynamic)
426 switch(vid.renderpath)
428 case RENDERPATH_GL11:
429 case RENDERPATH_GL13:
430 case RENDERPATH_GL20:
431 case RENDERPATH_SOFT:
432 case RENDERPATH_GLES2:
434 case RENDERPATH_D3D9:
436 if (buffer->devicebuffer)
438 if (buffer->isindexbuffer)
439 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
441 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
442 buffer->devicebuffer = NULL;
446 case RENDERPATH_D3D10:
447 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
449 case RENDERPATH_D3D11:
450 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
456 static void gl_backend_devicerestored(void)
458 switch(vid.renderpath)
460 case RENDERPATH_GL11:
461 case RENDERPATH_GL13:
462 case RENDERPATH_GL20:
463 case RENDERPATH_SOFT:
464 case RENDERPATH_GLES2:
466 case RENDERPATH_D3D9:
468 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
469 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
472 case RENDERPATH_D3D10:
473 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
475 case RENDERPATH_D3D11:
476 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
481 void gl_backend_init(void)
485 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
487 polygonelement3s[i * 3 + 0] = 0;
488 polygonelement3s[i * 3 + 1] = i + 1;
489 polygonelement3s[i * 3 + 2] = i + 2;
491 // elements for rendering a series of quads as triangles
492 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
494 quadelement3s[i * 6 + 0] = i * 4;
495 quadelement3s[i * 6 + 1] = i * 4 + 1;
496 quadelement3s[i * 6 + 2] = i * 4 + 2;
497 quadelement3s[i * 6 + 3] = i * 4;
498 quadelement3s[i * 6 + 4] = i * 4 + 2;
499 quadelement3s[i * 6 + 5] = i * 4 + 3;
502 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
503 polygonelement3i[i] = polygonelement3s[i];
504 for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
505 quadelement3i[i] = quadelement3s[i];
507 Cvar_RegisterVariable(&r_render);
508 Cvar_RegisterVariable(&r_renderview);
509 Cvar_RegisterVariable(&r_waterwarp);
510 Cvar_RegisterVariable(&gl_polyblend);
511 Cvar_RegisterVariable(&v_flipped);
512 Cvar_RegisterVariable(&gl_dither);
513 Cvar_RegisterVariable(&gl_vbo);
514 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
515 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
516 Cvar_RegisterVariable(&gl_paranoid);
517 Cvar_RegisterVariable(&gl_printcheckerror);
519 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
520 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
521 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
523 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");
525 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
528 void GL_SetMirrorState(qboolean state);
530 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
534 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
535 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
537 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
539 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
540 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
541 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
543 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
546 static int bboxedges[12][2] =
565 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
567 int i, ix1, iy1, ix2, iy2;
568 float x1, y1, x2, y2;
579 scissor[0] = r_refdef.view.viewport.x;
580 scissor[1] = r_refdef.view.viewport.y;
581 scissor[2] = r_refdef.view.viewport.width;
582 scissor[3] = r_refdef.view.viewport.height;
584 // if view is inside the box, just say yes it's visible
585 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
588 x1 = y1 = x2 = y2 = 0;
590 // transform all corners that are infront of the nearclip plane
591 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
592 plane4f[3] = r_refdef.view.frustum[4].dist;
594 for (i = 0;i < 8;i++)
596 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
597 dist[i] = DotProduct4(corner[i], plane4f);
598 sign[i] = dist[i] > 0;
601 VectorCopy(corner[i], vertex[numvertices]);
605 // if some points are behind the nearclip, add clipped edge points to make
606 // sure that the scissor boundary is complete
607 if (numvertices > 0 && numvertices < 8)
609 // add clipped edge points
610 for (i = 0;i < 12;i++)
614 if (sign[j] != sign[k])
616 f = dist[j] / (dist[j] - dist[k]);
617 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
623 // if we have no points to check, it is behind the view plane
627 // if we have some points to transform, check what screen area is covered
628 x1 = y1 = x2 = y2 = 0;
630 //Con_Printf("%i vertices to transform...\n", numvertices);
631 for (i = 0;i < numvertices;i++)
633 VectorCopy(vertex[i], v);
634 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
635 //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]);
638 if (x1 > v2[0]) x1 = v2[0];
639 if (x2 < v2[0]) x2 = v2[0];
640 if (y1 > v2[1]) y1 = v2[1];
641 if (y2 < v2[1]) y2 = v2[1];
650 // now convert the scissor rectangle to integer screen coordinates
651 ix1 = (int)(x1 - 1.0f);
652 //iy1 = vid.height - (int)(y2 - 1.0f);
653 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
654 iy1 = (int)(y1 - 1.0f);
655 ix2 = (int)(x2 + 1.0f);
656 //iy2 = vid.height - (int)(y1 + 1.0f);
657 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
658 iy2 = (int)(y2 + 1.0f);
659 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
661 // clamp it to the screen
662 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
663 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
664 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
665 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
667 // if it is inside out, it's not visible
668 if (ix2 <= ix1 || iy2 <= iy1)
671 // the light area is visible, set up the scissor rectangle
674 scissor[2] = ix2 - ix1;
675 scissor[3] = iy2 - iy1;
677 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
678 switch(vid.renderpath)
680 case RENDERPATH_D3D9:
681 case RENDERPATH_D3D10:
682 case RENDERPATH_D3D11:
683 scissor[1] = vid.height - scissor[1] - scissor[3];
685 case RENDERPATH_GL11:
686 case RENDERPATH_GL13:
687 case RENDERPATH_GL20:
688 case RENDERPATH_SOFT:
689 case RENDERPATH_GLES2:
697 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
701 float clipPlane[4], v3[3], v4[3];
704 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
706 VectorSet(normal, normalx, normaly, normalz);
707 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
708 VectorScale(normal, dist, v3);
709 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
710 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
711 clipPlane[3] = -DotProduct(v4, clipPlane);
715 // testing code for comparing results
717 VectorCopy4(clipPlane, clipPlane2);
718 R_EntityMatrix(&identitymatrix);
719 VectorSet(q, normal[0], normal[1], normal[2], -dist);
720 qglClipPlane(GL_CLIP_PLANE0, q);
721 qglGetClipPlane(GL_CLIP_PLANE0, q);
722 VectorCopy4(q, clipPlane);
726 // Calculate the clip-space corner point opposite the clipping plane
727 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
728 // transform it into camera space by multiplying it
729 // by the inverse of the projection matrix
730 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
731 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
733 q[3] = (1.0f + m[10]) / m[14];
735 // Calculate the scaled plane vector
736 d = 2.0f / DotProduct4(clipPlane, q);
738 // Replace the third row of the projection matrix
739 m[2] = clipPlane[0] * d;
740 m[6] = clipPlane[1] * d;
741 m[10] = clipPlane[2] * d + 1.0f;
742 m[14] = clipPlane[3] * d;
745 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)
747 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
749 memset(v, 0, sizeof(*v));
750 v->type = R_VIEWPORTTYPE_ORTHO;
751 v->cameramatrix = *cameramatrix;
758 memset(m, 0, sizeof(m));
759 m[0] = 2/(right - left);
760 m[5] = 2/(top - bottom);
761 m[10] = -2/(zFar - zNear);
762 m[12] = - (right + left)/(right - left);
763 m[13] = - (top + bottom)/(top - bottom);
764 m[14] = - (zFar + zNear)/(zFar - zNear);
766 switch(vid.renderpath)
768 case RENDERPATH_GL11:
769 case RENDERPATH_GL13:
770 case RENDERPATH_GL20:
771 case RENDERPATH_SOFT:
772 case RENDERPATH_GLES2:
774 case RENDERPATH_D3D9:
775 case RENDERPATH_D3D10:
776 case RENDERPATH_D3D11:
777 m[10] = -1/(zFar - zNear);
778 m[14] = -zNear/(zFar-zNear);
781 v->screentodepth[0] = -farclip / (farclip - nearclip);
782 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
784 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
787 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
789 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
795 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
796 R_Viewport_TransformToScreen(v, test1, test2);
797 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
802 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)
804 matrix4x4_t tempmatrix, basematrix;
806 memset(v, 0, sizeof(*v));
808 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
809 v->cameramatrix = *cameramatrix;
816 memset(m, 0, sizeof(m));
817 m[0] = 1.0 / frustumx;
818 m[5] = 1.0 / frustumy;
819 m[10] = -(farclip + nearclip) / (farclip - nearclip);
821 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
822 v->screentodepth[0] = -farclip / (farclip - nearclip);
823 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
825 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
826 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
827 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
828 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
831 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
833 if(v_flipped.integer)
841 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
844 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)
846 matrix4x4_t tempmatrix, basematrix;
847 const float nudge = 1.0 - 1.0 / (1<<23);
849 memset(v, 0, sizeof(*v));
851 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
852 v->cameramatrix = *cameramatrix;
859 memset(m, 0, sizeof(m));
860 m[ 0] = 1.0 / frustumx;
861 m[ 5] = 1.0 / frustumy;
864 m[14] = -2 * nearclip * nudge;
865 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
866 v->screentodepth[1] = m[14] * -0.5;
868 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
869 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
870 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
871 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
874 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
876 if(v_flipped.integer)
884 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
887 float cubeviewmatrix[6][16] =
889 // standard cubemap projections
927 float rectviewmatrix[6][16] =
929 // sign-preserving cubemap projections
968 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
970 matrix4x4_t tempmatrix, basematrix;
972 memset(v, 0, sizeof(*v));
973 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
974 v->cameramatrix = *cameramatrix;
978 memset(m, 0, sizeof(m));
980 m[10] = -(farclip + nearclip) / (farclip - nearclip);
982 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
984 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
985 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
986 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
989 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
991 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
994 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)
996 matrix4x4_t tempmatrix, basematrix;
998 memset(v, 0, sizeof(*v));
999 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1000 v->cameramatrix = *cameramatrix;
1001 v->x = (side & 1) * size;
1002 v->y = (side >> 1) * size;
1006 memset(m, 0, sizeof(m));
1007 m[0] = m[5] = 1.0f * ((float)size - border) / size;
1008 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1010 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1012 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1013 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1014 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1016 switch(vid.renderpath)
1018 case RENDERPATH_GL20:
1019 case RENDERPATH_GL13:
1020 case RENDERPATH_GL11:
1021 case RENDERPATH_SOFT:
1022 case RENDERPATH_GLES2:
1024 case RENDERPATH_D3D9:
1027 case RENDERPATH_D3D10:
1028 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1030 case RENDERPATH_D3D11:
1031 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1036 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1038 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1041 void R_SetViewport(const r_viewport_t *v)
1046 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1047 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1049 // copy over the matrices to our state
1050 gl_viewmatrix = v->viewmatrix;
1051 gl_projectionmatrix = v->projectmatrix;
1053 switch(vid.renderpath)
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);
1088 case RENDERPATH_GL20:
1089 case RENDERPATH_GLES2:
1091 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1095 // force an update of the derived matrices
1096 gl_modelmatrixchanged = true;
1097 R_EntityMatrix(&gl_modelmatrix);
1100 void R_GetViewport(r_viewport_t *v)
1105 static void GL_BindVBO(int bufferobject)
1107 if (gl_state.vertexbufferobject != bufferobject)
1109 gl_state.vertexbufferobject = bufferobject;
1111 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1115 static void GL_BindEBO(int bufferobject)
1117 if (gl_state.elementbufferobject != bufferobject)
1119 gl_state.elementbufferobject = bufferobject;
1121 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1125 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1128 switch(vid.renderpath)
1130 case RENDERPATH_GL11:
1131 case RENDERPATH_GL13:
1132 case RENDERPATH_GL20:
1133 case RENDERPATH_GLES2:
1134 if (!vid.support.ext_framebuffer_object)
1136 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1137 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1138 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1139 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1140 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1141 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1142 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1144 case RENDERPATH_D3D9:
1145 case RENDERPATH_D3D10:
1146 case RENDERPATH_D3D11:
1148 case RENDERPATH_SOFT:
1154 void R_Mesh_DestroyFramebufferObject(int fbo)
1156 switch(vid.renderpath)
1158 case RENDERPATH_GL11:
1159 case RENDERPATH_GL13:
1160 case RENDERPATH_GL20:
1161 case RENDERPATH_GLES2:
1163 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1165 case RENDERPATH_D3D9:
1166 case RENDERPATH_D3D10:
1167 case RENDERPATH_D3D11:
1169 case RENDERPATH_SOFT:
1175 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1177 // 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)
1178 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)
1181 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1182 if (gl_state.d3drt_depthsurface != depthsurface)
1184 gl_state.d3drt_depthsurface = depthsurface;
1185 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1187 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1189 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1190 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1192 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1194 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1195 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1197 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1199 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1200 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1202 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1204 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1205 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1210 void R_Mesh_ResetRenderTargets(void)
1212 switch(vid.renderpath)
1214 case RENDERPATH_GL11:
1215 case RENDERPATH_GL13:
1216 case RENDERPATH_GL20:
1217 case RENDERPATH_GLES2:
1218 if (gl_state.framebufferobject)
1220 gl_state.framebufferobject = 0;
1221 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1224 case RENDERPATH_D3D9:
1226 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1229 case RENDERPATH_D3D10:
1230 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1232 case RENDERPATH_D3D11:
1233 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1235 case RENDERPATH_SOFT:
1236 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1241 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1245 rtexture_t *textures[5];
1246 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1247 textures[4] = depthtexture;
1248 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1249 for (j = 0;j < 5;j++)
1251 for (i = 0;i < vid.teximageunits;i++)
1252 if (gl_state.units[i].texture == textures[j])
1253 R_Mesh_TexBind(i, NULL);
1254 // set up framebuffer object or render targets for the active rendering API
1255 switch(vid.renderpath)
1257 case RENDERPATH_GL11:
1258 case RENDERPATH_GL13:
1259 case RENDERPATH_GL20:
1260 case RENDERPATH_GLES2:
1261 if (gl_state.framebufferobject != fbo)
1263 gl_state.framebufferobject = fbo;
1264 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1267 case RENDERPATH_D3D9:
1269 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1270 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1273 IDirect3DSurface9 *colorsurfaces[4];
1274 for (i = 0;i < 4;i++)
1276 colorsurfaces[i] = NULL;
1278 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1280 // set the render targets for real
1281 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1282 // release the texture surface levels (they won't be lost while bound...)
1283 for (i = 0;i < 4;i++)
1285 IDirect3DSurface9_Release(colorsurfaces[i]);
1288 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1291 case RENDERPATH_D3D10:
1292 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1294 case RENDERPATH_D3D11:
1295 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1297 case RENDERPATH_SOFT:
1301 unsigned int *pointers[5];
1302 memset(pointers, 0, sizeof(pointers));
1303 for (i = 0;i < 5;i++)
1304 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1305 width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1306 height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1307 DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1310 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1316 static int d3dcmpforglfunc(int f)
1320 case GL_NEVER: return D3DCMP_NEVER;
1321 case GL_LESS: return D3DCMP_LESS;
1322 case GL_EQUAL: return D3DCMP_EQUAL;
1323 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1324 case GL_GREATER: return D3DCMP_GREATER;
1325 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1326 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1327 case GL_ALWAYS: return D3DCMP_ALWAYS;
1328 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1332 static int d3dstencilopforglfunc(int f)
1336 case GL_KEEP: return D3DSTENCILOP_KEEP;
1337 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1338 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1339 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1345 static void GL_Backend_ResetState(void)
1348 gl_state.active = true;
1349 gl_state.depthtest = true;
1350 gl_state.alphatest = false;
1351 gl_state.alphafunc = GL_GEQUAL;
1352 gl_state.alphafuncvalue = 0.5f;
1353 gl_state.blendfunc1 = GL_ONE;
1354 gl_state.blendfunc2 = GL_ZERO;
1355 gl_state.blend = false;
1356 gl_state.depthmask = GL_TRUE;
1357 gl_state.colormask = 15;
1358 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1359 gl_state.lockrange_first = 0;
1360 gl_state.lockrange_count = 0;
1361 gl_state.cullface = GL_FRONT;
1362 gl_state.cullfaceenable = false;
1363 gl_state.polygonoffset[0] = 0;
1364 gl_state.polygonoffset[1] = 0;
1365 gl_state.framebufferobject = 0;
1366 gl_state.depthfunc = GL_LEQUAL;
1368 switch(vid.renderpath)
1370 case RENDERPATH_D3D9:
1373 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1374 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1375 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1376 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1377 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1378 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1379 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1380 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1381 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1382 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1386 case RENDERPATH_D3D10:
1387 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1389 case RENDERPATH_D3D11:
1390 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1392 case RENDERPATH_GL13:
1393 case RENDERPATH_GL11:
1396 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1397 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1398 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1399 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1400 qglDisable(GL_BLEND);CHECKGLERROR
1401 qglCullFace(gl_state.cullface);CHECKGLERROR
1402 qglDisable(GL_CULL_FACE);CHECKGLERROR
1403 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1404 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1405 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1406 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1408 if (vid.support.arb_vertex_buffer_object)
1410 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1411 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1414 if (vid.support.ext_framebuffer_object)
1416 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1417 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1420 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1421 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1423 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1424 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1425 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1427 if (vid.support.ext_framebuffer_object)
1428 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1430 gl_state.unit = MAX_TEXTUREUNITS;
1431 gl_state.clientunit = MAX_TEXTUREUNITS;
1432 for (i = 0;i < vid.texunits;i++)
1434 GL_ActiveTexture(i);
1435 GL_ClientActiveTexture(i);
1436 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1437 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1438 if (vid.support.ext_texture_3d)
1440 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1441 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1443 if (vid.support.arb_texture_cube_map)
1445 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1446 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1449 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1450 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1451 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1452 qglLoadIdentity();CHECKGLERROR
1453 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1454 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1458 case RENDERPATH_SOFT:
1459 DPSOFTRAST_ColorMask(1,1,1,1);
1460 DPSOFTRAST_AlphaTest(gl_state.alphatest);
1461 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1462 DPSOFTRAST_CullFace(gl_state.cullface);
1463 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1464 DPSOFTRAST_DepthMask(gl_state.depthmask);
1465 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1466 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1467 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1469 case RENDERPATH_GL20:
1470 case RENDERPATH_GLES2:
1472 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1473 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1474 qglDisable(GL_BLEND);CHECKGLERROR
1475 qglCullFace(gl_state.cullface);CHECKGLERROR
1476 qglDisable(GL_CULL_FACE);CHECKGLERROR
1477 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1478 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1479 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1480 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1481 // if (vid.renderpath == RENDERPATH_GL20)
1483 // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1484 // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1486 if (vid.support.arb_vertex_buffer_object)
1488 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1489 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1491 if (vid.support.ext_framebuffer_object)
1492 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1493 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1494 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1495 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1496 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1497 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1498 gl_state.unit = MAX_TEXTUREUNITS;
1499 gl_state.clientunit = MAX_TEXTUREUNITS;
1500 for (i = 0;i < vid.teximageunits;i++)
1502 GL_ActiveTexture(i);
1503 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1504 if (vid.support.ext_texture_3d)
1506 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1508 if (vid.support.arb_texture_cube_map)
1510 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1513 for (i = 0;i < vid.texarrayunits;i++)
1516 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1517 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1524 void GL_ActiveTexture(unsigned int num)
1526 if (gl_state.unit != num)
1528 gl_state.unit = num;
1529 switch(vid.renderpath)
1531 case RENDERPATH_GL11:
1532 case RENDERPATH_GL13:
1533 case RENDERPATH_GL20:
1534 case RENDERPATH_GLES2:
1535 if (qglActiveTexture)
1538 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1542 case RENDERPATH_D3D9:
1543 case RENDERPATH_D3D10:
1544 case RENDERPATH_D3D11:
1546 case RENDERPATH_SOFT:
1552 void GL_ClientActiveTexture(unsigned int num)
1554 if (gl_state.clientunit != num)
1556 gl_state.clientunit = num;
1557 switch(vid.renderpath)
1559 case RENDERPATH_GL11:
1560 case RENDERPATH_GL13:
1561 if (qglActiveTexture)
1564 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1568 case RENDERPATH_D3D9:
1569 case RENDERPATH_D3D10:
1570 case RENDERPATH_D3D11:
1572 case RENDERPATH_SOFT:
1574 case RENDERPATH_GL20:
1575 case RENDERPATH_GLES2:
1581 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1583 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1585 qboolean blendenable;
1586 gl_state.blendfunc1 = blendfunc1;
1587 gl_state.blendfunc2 = blendfunc2;
1588 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1589 switch(vid.renderpath)
1591 case RENDERPATH_GL11:
1592 case RENDERPATH_GL13:
1593 case RENDERPATH_GL20:
1594 case RENDERPATH_GLES2:
1596 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1597 if (gl_state.blend != blendenable)
1599 gl_state.blend = blendenable;
1600 if (!gl_state.blend)
1602 qglDisable(GL_BLEND);CHECKGLERROR
1606 qglEnable(GL_BLEND);CHECKGLERROR
1610 case RENDERPATH_D3D9:
1615 D3DBLEND d3dblendfunc[2];
1616 glblendfunc[0] = gl_state.blendfunc1;
1617 glblendfunc[1] = gl_state.blendfunc2;
1618 for (i = 0;i < 2;i++)
1620 switch(glblendfunc[i])
1622 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1623 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1624 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1625 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1626 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1627 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1628 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1629 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1630 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1631 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1634 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1635 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1636 if (gl_state.blend != blendenable)
1638 gl_state.blend = blendenable;
1639 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1644 case RENDERPATH_D3D10:
1645 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1647 case RENDERPATH_D3D11:
1648 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1650 case RENDERPATH_SOFT:
1651 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1657 void GL_DepthMask(int state)
1659 if (gl_state.depthmask != state)
1661 gl_state.depthmask = state;
1662 switch(vid.renderpath)
1664 case RENDERPATH_GL11:
1665 case RENDERPATH_GL13:
1666 case RENDERPATH_GL20:
1667 case RENDERPATH_GLES2:
1669 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1671 case RENDERPATH_D3D9:
1673 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1676 case RENDERPATH_D3D10:
1677 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1679 case RENDERPATH_D3D11:
1680 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1682 case RENDERPATH_SOFT:
1683 DPSOFTRAST_DepthMask(gl_state.depthmask);
1689 void GL_DepthTest(int state)
1691 if (gl_state.depthtest != state)
1693 gl_state.depthtest = state;
1694 switch(vid.renderpath)
1696 case RENDERPATH_GL11:
1697 case RENDERPATH_GL13:
1698 case RENDERPATH_GL20:
1699 case RENDERPATH_GLES2:
1701 if (gl_state.depthtest)
1703 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1707 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1710 case RENDERPATH_D3D9:
1712 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1715 case RENDERPATH_D3D10:
1716 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1718 case RENDERPATH_D3D11:
1719 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1721 case RENDERPATH_SOFT:
1722 DPSOFTRAST_DepthTest(gl_state.depthtest);
1728 void GL_DepthFunc(int state)
1730 if (gl_state.depthfunc != state)
1732 gl_state.depthfunc = state;
1733 switch(vid.renderpath)
1735 case RENDERPATH_GL11:
1736 case RENDERPATH_GL13:
1737 case RENDERPATH_GL20:
1738 case RENDERPATH_GLES2:
1740 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1742 case RENDERPATH_D3D9:
1744 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1747 case RENDERPATH_D3D10:
1748 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1750 case RENDERPATH_D3D11:
1751 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1753 case RENDERPATH_SOFT:
1754 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1760 void GL_DepthRange(float nearfrac, float farfrac)
1762 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1764 gl_state.depthrange[0] = nearfrac;
1765 gl_state.depthrange[1] = farfrac;
1766 switch(vid.renderpath)
1768 case RENDERPATH_GL11:
1769 case RENDERPATH_GL13:
1770 case RENDERPATH_GL20:
1771 case RENDERPATH_GLES2:
1772 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1774 case RENDERPATH_D3D9:
1777 D3DVIEWPORT9 d3dviewport;
1778 d3dviewport.X = gl_viewport.x;
1779 d3dviewport.Y = gl_viewport.y;
1780 d3dviewport.Width = gl_viewport.width;
1781 d3dviewport.Height = gl_viewport.height;
1782 d3dviewport.MinZ = gl_state.depthrange[0];
1783 d3dviewport.MaxZ = gl_state.depthrange[1];
1784 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1788 case RENDERPATH_D3D10:
1789 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1791 case RENDERPATH_D3D11:
1792 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1794 case RENDERPATH_SOFT:
1795 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1801 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)
1803 switch (vid.renderpath)
1805 case RENDERPATH_GL11:
1806 case RENDERPATH_GL13:
1807 case RENDERPATH_GL20:
1808 case RENDERPATH_GLES2:
1812 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1816 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1818 if (vid.support.ati_separate_stencil)
1820 qglStencilMask(writemask);CHECKGLERROR
1821 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1822 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1823 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1825 else if (vid.support.ext_stencil_two_side)
1827 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1828 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1829 qglStencilMask(writemask);CHECKGLERROR
1830 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1831 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1832 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1833 qglStencilMask(writemask);CHECKGLERROR
1834 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1835 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1838 case RENDERPATH_D3D9:
1840 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1841 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1842 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1843 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1844 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1845 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1846 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1847 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1848 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1849 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1850 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1851 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1852 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1855 case RENDERPATH_D3D10:
1856 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1858 case RENDERPATH_D3D11:
1859 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1861 case RENDERPATH_SOFT:
1862 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1867 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1869 switch (vid.renderpath)
1871 case RENDERPATH_GL11:
1872 case RENDERPATH_GL13:
1873 case RENDERPATH_GL20:
1874 case RENDERPATH_GLES2:
1878 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1882 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1884 if (vid.support.ext_stencil_two_side)
1886 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1888 qglStencilMask(writemask);CHECKGLERROR
1889 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1890 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1893 case RENDERPATH_D3D9:
1895 if (vid.support.ati_separate_stencil)
1896 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1897 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1898 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1899 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1900 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1901 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1902 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1903 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1904 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1907 case RENDERPATH_D3D10:
1908 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1910 case RENDERPATH_D3D11:
1911 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1913 case RENDERPATH_SOFT:
1914 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919 void GL_PolygonOffset(float planeoffset, float depthoffset)
1921 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1923 gl_state.polygonoffset[0] = planeoffset;
1924 gl_state.polygonoffset[1] = depthoffset;
1925 switch(vid.renderpath)
1927 case RENDERPATH_GL11:
1928 case RENDERPATH_GL13:
1929 case RENDERPATH_GL20:
1930 case RENDERPATH_GLES2:
1931 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1933 case RENDERPATH_D3D9:
1935 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1936 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1939 case RENDERPATH_D3D10:
1940 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1942 case RENDERPATH_D3D11:
1943 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945 case RENDERPATH_SOFT:
1946 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1952 void GL_SetMirrorState(qboolean state)
1954 if (v_flipped_state != state)
1956 v_flipped_state = state;
1957 if (gl_state.cullface == GL_BACK)
1958 gl_state.cullface = GL_FRONT;
1959 else if (gl_state.cullface == GL_FRONT)
1960 gl_state.cullface = GL_BACK;
1963 switch(vid.renderpath)
1965 case RENDERPATH_GL11:
1966 case RENDERPATH_GL13:
1967 case RENDERPATH_GL20:
1968 case RENDERPATH_GLES2:
1969 qglCullFace(gl_state.cullface);CHECKGLERROR
1971 case RENDERPATH_D3D9:
1973 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
1976 case RENDERPATH_D3D10:
1977 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1979 case RENDERPATH_D3D11:
1980 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1982 case RENDERPATH_SOFT:
1983 DPSOFTRAST_CullFace(gl_state.cullface);
1989 void GL_CullFace(int state)
1993 if(state == GL_FRONT)
1995 else if(state == GL_BACK)
1999 switch(vid.renderpath)
2001 case RENDERPATH_GL11:
2002 case RENDERPATH_GL13:
2003 case RENDERPATH_GL20:
2004 case RENDERPATH_GLES2:
2007 if (state != GL_NONE)
2009 if (!gl_state.cullfaceenable)
2011 gl_state.cullfaceenable = true;
2012 qglEnable(GL_CULL_FACE);CHECKGLERROR
2014 if (gl_state.cullface != state)
2016 gl_state.cullface = state;
2017 qglCullFace(gl_state.cullface);CHECKGLERROR
2022 if (gl_state.cullfaceenable)
2024 gl_state.cullfaceenable = false;
2025 qglDisable(GL_CULL_FACE);CHECKGLERROR
2029 case RENDERPATH_D3D9:
2031 if (gl_state.cullface != state)
2033 gl_state.cullface = state;
2034 switch(gl_state.cullface)
2037 gl_state.cullfaceenable = false;
2038 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2041 gl_state.cullfaceenable = true;
2042 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2045 gl_state.cullfaceenable = true;
2046 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2052 case RENDERPATH_D3D10:
2053 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2055 case RENDERPATH_D3D11:
2056 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2058 case RENDERPATH_SOFT:
2059 if (gl_state.cullface != state)
2061 gl_state.cullface = state;
2062 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2063 DPSOFTRAST_CullFace(gl_state.cullface);
2069 void GL_AlphaTest(int state)
2071 if (gl_state.alphatest != state)
2073 gl_state.alphatest = state;
2074 switch(vid.renderpath)
2076 case RENDERPATH_GL11:
2077 case RENDERPATH_GL13:
2078 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2080 if (gl_state.alphatest)
2082 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2086 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2089 case RENDERPATH_D3D9:
2091 // IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2094 case RENDERPATH_D3D10:
2096 case RENDERPATH_D3D11:
2098 case RENDERPATH_SOFT:
2099 // DPSOFTRAST_AlphaTest(gl_state.alphatest);
2101 case RENDERPATH_GL20:
2102 case RENDERPATH_GLES2:
2108 void GL_ColorMask(int r, int g, int b, int a)
2110 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2111 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2112 if (gl_state.colormask != state)
2114 gl_state.colormask = state;
2115 switch(vid.renderpath)
2117 case RENDERPATH_GL11:
2118 case RENDERPATH_GL13:
2119 case RENDERPATH_GL20:
2120 case RENDERPATH_GLES2:
2122 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2124 case RENDERPATH_D3D9:
2126 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2129 case RENDERPATH_D3D10:
2130 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2132 case RENDERPATH_D3D11:
2133 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2135 case RENDERPATH_SOFT:
2136 DPSOFTRAST_ColorMask(r, g, b, a);
2142 void GL_Color(float cr, float cg, float cb, float ca)
2144 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)
2146 gl_state.color4f[0] = cr;
2147 gl_state.color4f[1] = cg;
2148 gl_state.color4f[2] = cb;
2149 gl_state.color4f[3] = ca;
2150 switch(vid.renderpath)
2152 case RENDERPATH_GL11:
2153 case RENDERPATH_GL13:
2155 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2158 case RENDERPATH_D3D9:
2159 case RENDERPATH_D3D10:
2160 case RENDERPATH_D3D11:
2161 // no equivalent in D3D
2163 case RENDERPATH_SOFT:
2164 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2166 case RENDERPATH_GL20:
2167 case RENDERPATH_GLES2:
2168 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2174 void GL_Scissor (int x, int y, int width, int height)
2176 switch(vid.renderpath)
2178 case RENDERPATH_GL11:
2179 case RENDERPATH_GL13:
2180 case RENDERPATH_GL20:
2181 case RENDERPATH_GLES2:
2183 qglScissor(x, y,width,height);
2186 case RENDERPATH_D3D9:
2192 d3drect.right = x + width;
2193 d3drect.bottom = y + height;
2194 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2198 case RENDERPATH_D3D10:
2199 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2201 case RENDERPATH_D3D11:
2202 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2204 case RENDERPATH_SOFT:
2205 DPSOFTRAST_Scissor(x, y, width, height);
2210 void GL_ScissorTest(int state)
2212 if (gl_state.scissortest != state)
2214 gl_state.scissortest = state;
2215 switch(vid.renderpath)
2217 case RENDERPATH_GL11:
2218 case RENDERPATH_GL13:
2219 case RENDERPATH_GL20:
2220 case RENDERPATH_GLES2:
2222 if(gl_state.scissortest)
2223 qglEnable(GL_SCISSOR_TEST);
2225 qglDisable(GL_SCISSOR_TEST);
2228 case RENDERPATH_D3D9:
2230 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2233 case RENDERPATH_D3D10:
2234 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2236 case RENDERPATH_D3D11:
2237 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2239 case RENDERPATH_SOFT:
2240 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2246 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2248 static const float blackcolor[4] = {0, 0, 0, 0};
2249 // prevent warnings when trying to clear a buffer that does not exist
2251 colorvalue = blackcolor;
2254 mask &= ~GL_STENCIL_BUFFER_BIT;
2257 switch(vid.renderpath)
2259 case RENDERPATH_GL11:
2260 case RENDERPATH_GL13:
2261 case RENDERPATH_GL20:
2262 case RENDERPATH_GLES2:
2264 if (mask & GL_COLOR_BUFFER_BIT)
2266 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2268 if (mask & GL_DEPTH_BUFFER_BIT)
2270 qglClearDepth(depthvalue);CHECKGLERROR
2272 if (mask & GL_STENCIL_BUFFER_BIT)
2274 qglClearStencil(stencilvalue);CHECKGLERROR
2276 qglClear(mask);CHECKGLERROR
2278 case RENDERPATH_D3D9:
2280 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);
2283 case RENDERPATH_D3D10:
2284 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2286 case RENDERPATH_D3D11:
2287 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2289 case RENDERPATH_SOFT:
2290 if (mask & GL_COLOR_BUFFER_BIT)
2291 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2292 if (mask & GL_DEPTH_BUFFER_BIT)
2293 DPSOFTRAST_ClearDepth(depthvalue);
2298 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2300 switch(vid.renderpath)
2302 case RENDERPATH_GL11:
2303 case RENDERPATH_GL13:
2304 case RENDERPATH_GL20:
2305 case RENDERPATH_GLES2:
2307 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2309 case RENDERPATH_D3D9:
2312 // LordHavoc: we can't directly download the backbuffer because it may be
2313 // multisampled, and it may not be lockable, so we blit it to a lockable
2314 // surface of the same dimensions (but without multisample) to resolve the
2315 // multisample buffer to a normal image, and then lock that...
2316 IDirect3DSurface9 *stretchsurface = NULL;
2317 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2319 D3DLOCKED_RECT lockedrect;
2320 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2322 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2325 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2326 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2327 memcpy(outpixels + line * width * 4, row, width * 4);
2328 IDirect3DSurface9_UnlockRect(stretchsurface);
2331 IDirect3DSurface9_Release(stretchsurface);
2334 //IDirect3DSurface9 *syssurface = NULL;
2335 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2336 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2337 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2338 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2339 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2340 //IDirect3DSurface9_UnlockRect(syssurface);
2341 //IDirect3DSurface9_Release(syssurface);
2345 case RENDERPATH_D3D10:
2346 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2348 case RENDERPATH_D3D11:
2349 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2351 case RENDERPATH_SOFT:
2352 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2357 // called at beginning of frame
2358 void R_Mesh_Start(void)
2361 R_Mesh_ResetRenderTargets();
2363 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2365 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2366 Cvar_SetValueQuick(&gl_paranoid, 1);
2370 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2374 char compilelog[MAX_INPUTLINE];
2375 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2378 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2379 qglCompileShader(shaderobject);CHECKGLERROR
2380 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2381 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2382 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2384 int i, j, pretextlines = 0;
2385 for (i = 0;i < numstrings - 1;i++)
2386 for (j = 0;strings[i][j];j++)
2387 if (strings[i][j] == '\n')
2389 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2391 if (!shadercompiled)
2393 qglDeleteShader(shaderobject);CHECKGLERROR
2396 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2397 qglDeleteShader(shaderobject);CHECKGLERROR
2401 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)
2403 GLint programlinked;
2404 GLuint programobject = 0;
2405 char linklog[MAX_INPUTLINE];
2408 programobject = qglCreateProgram();CHECKGLERROR
2412 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2413 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2414 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2415 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2416 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2417 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2418 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2419 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2420 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2421 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2423 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2426 #ifdef GL_GEOMETRY_SHADER
2427 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2431 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2434 qglLinkProgram(programobject);CHECKGLERROR
2435 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2436 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2439 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2440 Con_DPrintf("program link log:\n%s\n", linklog);
2441 // software vertex shader is ok but software fragment shader is WAY
2442 // too slow, fail program if so.
2443 // NOTE: this string might be ATI specific, but that's ok because the
2444 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2445 // software fragment shader due to low instruction and dependent
2447 if (strstr(linklog, "fragment shader will run in software"))
2448 programlinked = false;
2452 return programobject;
2454 qglDeleteProgram(programobject);CHECKGLERROR
2458 void GL_Backend_FreeProgram(unsigned int prog)
2461 qglDeleteProgram(prog);
2465 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2470 for (i = 0;i < count;i++)
2471 *out++ = *in++ + offset;
2474 memcpy(out, in, sizeof(*out) * count);
2477 // renders triangles using vertices from the active arrays
2478 int paranoidblah = 0;
2479 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)
2481 unsigned int numelements = numtriangles * 3;
2483 size_t bufferoffset3i;
2485 size_t bufferoffset3s;
2486 if (numvertices < 3 || numtriangles < 1)
2488 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2489 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);
2492 if (!gl_mesh_prefer_short_elements.integer)
2496 if (element3i_indexbuffer)
2497 element3i_indexbuffer = NULL;
2499 // adjust the pointers for firsttriangle
2501 element3i += firsttriangle * 3;
2502 if (element3i_indexbuffer)
2503 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2505 element3s += firsttriangle * 3;
2506 if (element3s_indexbuffer)
2507 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2508 switch(vid.renderpath)
2510 case RENDERPATH_GL11:
2511 case RENDERPATH_GL13:
2512 case RENDERPATH_GL20:
2513 case RENDERPATH_GLES2:
2514 // check if the user specified to ignore static index buffers
2515 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2517 element3i_indexbuffer = NULL;
2518 element3s_indexbuffer = NULL;
2521 case RENDERPATH_D3D9:
2522 case RENDERPATH_D3D10:
2523 case RENDERPATH_D3D11:
2525 case RENDERPATH_SOFT:
2528 // upload a dynamic index buffer if needed
2531 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2533 if (gl_state.draw_dynamicindexbuffer)
2534 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2536 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2537 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2538 element3s_bufferoffset = 0;
2543 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2545 if (gl_state.draw_dynamicindexbuffer)
2546 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2548 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2549 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2550 element3i_bufferoffset = 0;
2553 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2554 bufferoffset3i = element3i_bufferoffset;
2555 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2556 bufferoffset3s = element3s_bufferoffset;
2557 r_refdef.stats.draws++;
2558 r_refdef.stats.draws_vertices += numvertices;
2559 r_refdef.stats.draws_elements += numelements;
2560 if (gl_paranoid.integer)
2563 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2565 unsigned int j, size;
2567 // note: there's no validation done here on buffer objects because it
2568 // is somewhat difficult to get at the data, and gl_paranoid can be
2569 // used without buffer objects if the need arises
2570 // (the data could be gotten using glMapBuffer but it would be very
2571 // slow due to uncachable video memory reads)
2572 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2573 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2575 if (gl_state.pointer_vertex_pointer)
2576 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2578 if (gl_state.pointer_color_enabled)
2580 if (!qglIsEnabled(GL_COLOR_ARRAY))
2581 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2583 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2584 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2587 for (i = 0;i < vid.texarrayunits;i++)
2589 if (gl_state.units[i].arrayenabled)
2591 GL_ClientActiveTexture(i);
2592 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2593 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2595 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2596 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++)
2603 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2605 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2607 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2614 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2616 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2618 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2624 if (r_render.integer || r_refdef.draw2dstage)
2626 switch(vid.renderpath)
2628 case RENDERPATH_GL11:
2629 case RENDERPATH_GL13:
2630 case RENDERPATH_GL20:
2632 if (gl_mesh_testmanualfeeding.integer)
2634 unsigned int i, j, element;
2636 qglBegin(GL_TRIANGLES);
2637 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2640 element = element3i[i];
2642 element = element3s[i];
2644 element = firstvertex + i;
2645 for (j = 0;j < vid.texarrayunits;j++)
2647 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2649 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2651 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2652 if (vid.texarrayunits > 1)
2654 if (gl_state.units[j].pointer_texcoord_components == 4)
2655 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2656 else if (gl_state.units[j].pointer_texcoord_components == 3)
2657 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2658 else if (gl_state.units[j].pointer_texcoord_components == 2)
2659 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2661 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2665 if (gl_state.units[j].pointer_texcoord_components == 4)
2666 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2667 else if (gl_state.units[j].pointer_texcoord_components == 3)
2668 qglTexCoord3f(p[0], p[1], p[2]);
2669 else if (gl_state.units[j].pointer_texcoord_components == 2)
2670 qglTexCoord2f(p[0], p[1]);
2672 qglTexCoord1f(p[0]);
2675 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2677 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2678 if (vid.texarrayunits > 1)
2680 if (gl_state.units[j].pointer_texcoord_components == 4)
2681 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2682 else if (gl_state.units[j].pointer_texcoord_components == 3)
2683 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2684 else if (gl_state.units[j].pointer_texcoord_components == 2)
2685 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2686 else if (gl_state.units[j].pointer_texcoord_components == 1)
2687 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2691 if (gl_state.units[j].pointer_texcoord_components == 4)
2692 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2693 else if (gl_state.units[j].pointer_texcoord_components == 3)
2694 qglTexCoord3f(s[0], s[1], s[2]);
2695 else if (gl_state.units[j].pointer_texcoord_components == 2)
2696 qglTexCoord2f(s[0], s[1]);
2697 else if (gl_state.units[j].pointer_texcoord_components == 1)
2698 qglTexCoord1f(s[0]);
2701 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2703 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2704 if (vid.texarrayunits > 1)
2706 if (gl_state.units[j].pointer_texcoord_components == 4)
2707 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2708 else if (gl_state.units[j].pointer_texcoord_components == 3)
2709 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2710 else if (gl_state.units[j].pointer_texcoord_components == 2)
2711 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2712 else if (gl_state.units[j].pointer_texcoord_components == 1)
2713 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2717 if (gl_state.units[j].pointer_texcoord_components == 4)
2718 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2719 else if (gl_state.units[j].pointer_texcoord_components == 3)
2720 qglTexCoord3f(sb[0], sb[1], sb[2]);
2721 else if (gl_state.units[j].pointer_texcoord_components == 2)
2722 qglTexCoord2f(sb[0], sb[1]);
2723 else if (gl_state.units[j].pointer_texcoord_components == 1)
2724 qglTexCoord1f(sb[0]);
2729 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2731 if (gl_state.pointer_color_gltype == GL_FLOAT)
2733 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2734 qglColor4f(p[0], p[1], p[2], p[3]);
2736 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2738 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2739 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2742 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2744 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2745 if (gl_state.pointer_vertex_components == 4)
2746 qglVertex4f(p[0], p[1], p[2], p[3]);
2747 else if (gl_state.pointer_vertex_components == 3)
2748 qglVertex3f(p[0], p[1], p[2]);
2750 qglVertex2f(p[0], p[1]);
2756 else if (bufferobject3s)
2758 GL_BindEBO(bufferobject3s);
2759 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2761 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2766 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2770 else if (bufferobject3i)
2772 GL_BindEBO(bufferobject3i);
2773 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2775 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2780 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2787 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2789 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2794 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2801 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2803 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2808 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2814 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2818 case RENDERPATH_D3D9:
2820 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2822 if (element3s_indexbuffer)
2824 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2825 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2827 else if (element3i_indexbuffer)
2829 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2830 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2833 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2838 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2840 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2842 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2846 case RENDERPATH_D3D10:
2847 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2849 case RENDERPATH_D3D11:
2850 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2852 case RENDERPATH_SOFT:
2853 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2855 case RENDERPATH_GLES2:
2856 // GLES does not have glDrawRangeElements, and generally
2857 // underperforms with index buffers, so this code path is
2858 // relatively straightforward...
2860 if (gl_paranoid.integer)
2862 int r, prog, enabled, i;
2863 GLsizei attriblength;
2866 GLchar attribname[1024];
2867 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2868 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2869 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2870 #ifndef GL_CURRENT_PROGRAM
2871 #define GL_CURRENT_PROGRAM 0x8B8D
2873 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2874 if (r < 0 || r > 10000)
2875 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2877 for (i = 0;i < 8;i++)
2879 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2882 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2883 Con_DPrintf("prog %i position %i length %i size %04X type %i name \"%s\"\n", prog, i, (int)attriblength, (int)attribsize, (int)attribtype, (char *)attribname);
2889 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2894 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2899 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2907 // restores backend state, used when done with 3D rendering
2908 void R_Mesh_Finish(void)
2910 R_Mesh_ResetRenderTargets();
2913 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2915 r_meshbuffer_t *buffer;
2916 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2918 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2919 memset(buffer, 0, sizeof(*buffer));
2920 buffer->bufferobject = 0;
2921 buffer->devicebuffer = NULL;
2923 buffer->isindexbuffer = isindexbuffer;
2924 buffer->isdynamic = isdynamic;
2925 buffer->isindex16 = isindex16;
2926 strlcpy(buffer->name, name, sizeof(buffer->name));
2927 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2931 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
2935 if (buffer->isindexbuffer)
2937 r_refdef.stats.indexbufferuploadcount++;
2938 r_refdef.stats.indexbufferuploadsize += size;
2942 r_refdef.stats.vertexbufferuploadcount++;
2943 r_refdef.stats.vertexbufferuploadsize += size;
2945 switch(vid.renderpath)
2947 case RENDERPATH_GL11:
2948 case RENDERPATH_GL13:
2949 case RENDERPATH_GL20:
2950 case RENDERPATH_GLES2:
2951 if (!buffer->bufferobject)
2952 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
2953 if (buffer->isindexbuffer)
2954 GL_BindEBO(buffer->bufferobject);
2956 GL_BindVBO(buffer->bufferobject);
2957 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
2959 case RENDERPATH_D3D9:
2963 void *datapointer = NULL;
2964 if (buffer->isindexbuffer)
2966 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
2967 if (size > buffer->size || !buffer->devicebuffer)
2969 if (buffer->devicebuffer)
2970 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
2971 buffer->devicebuffer = NULL;
2972 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)))
2973 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);
2974 buffer->devicebuffer = (void *)d3d9indexbuffer;
2975 buffer->size = size;
2977 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2980 memcpy(datapointer, data, size);
2982 memset(datapointer, 0, size);
2983 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
2988 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
2989 if (size > buffer->size || !buffer->devicebuffer)
2991 if (buffer->devicebuffer)
2992 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
2993 buffer->devicebuffer = NULL;
2994 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
2995 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);
2996 buffer->devicebuffer = (void *)d3d9vertexbuffer;
2997 buffer->size = size;
2999 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3002 memcpy(datapointer, data, size);
3004 memset(datapointer, 0, size);
3005 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3011 case RENDERPATH_D3D10:
3012 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3014 case RENDERPATH_D3D11:
3015 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3017 case RENDERPATH_SOFT:
3022 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3026 switch(vid.renderpath)
3028 case RENDERPATH_GL11:
3029 case RENDERPATH_GL13:
3030 case RENDERPATH_GL20:
3031 case RENDERPATH_GLES2:
3032 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3034 case RENDERPATH_D3D9:
3036 if (gl_state.d3dvertexbuffer == (void *)buffer)
3037 gl_state.d3dvertexbuffer = NULL;
3038 if (buffer->devicebuffer)
3040 if (buffer->isindexbuffer)
3041 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3043 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3044 buffer->devicebuffer = NULL;
3048 case RENDERPATH_D3D10:
3049 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3051 case RENDERPATH_D3D11:
3052 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3054 case RENDERPATH_SOFT:
3057 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3060 void GL_Mesh_ListVBOs(qboolean printeach)
3063 size_t ebocount = 0, ebomemory = 0;
3064 size_t vbocount = 0, vbomemory = 0;
3065 r_meshbuffer_t *buffer;
3066 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3067 for (i = 0;i < endindex;i++)
3069 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3072 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)");}
3073 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)");}
3075 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);
3080 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3082 switch(vid.renderpath)
3084 case RENDERPATH_GL11:
3085 case RENDERPATH_GL13:
3086 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)
3088 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3089 gl_state.pointer_vertex_components = components;
3090 gl_state.pointer_vertex_gltype = gltype;
3091 gl_state.pointer_vertex_stride = stride;
3092 gl_state.pointer_vertex_pointer = pointer;
3093 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3094 gl_state.pointer_vertex_offset = bufferoffset;
3096 GL_BindVBO(bufferobject);
3097 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3100 case RENDERPATH_GL20:
3101 case RENDERPATH_GLES2:
3102 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)
3104 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3105 gl_state.pointer_vertex_components = components;
3106 gl_state.pointer_vertex_gltype = gltype;
3107 gl_state.pointer_vertex_stride = stride;
3108 gl_state.pointer_vertex_pointer = pointer;
3109 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3110 gl_state.pointer_vertex_offset = bufferoffset;
3112 GL_BindVBO(bufferobject);
3113 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3116 case RENDERPATH_D3D9:
3117 case RENDERPATH_D3D10:
3118 case RENDERPATH_D3D11:
3119 case RENDERPATH_SOFT:
3124 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3126 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3127 // the pointer only.
3128 switch(vid.renderpath)
3130 case RENDERPATH_GL11:
3131 case RENDERPATH_GL13:
3135 // caller wants color array enabled
3136 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3137 if (!gl_state.pointer_color_enabled)
3139 gl_state.pointer_color_enabled = true;
3141 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3143 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)
3145 gl_state.pointer_color_components = components;
3146 gl_state.pointer_color_gltype = gltype;
3147 gl_state.pointer_color_stride = stride;
3148 gl_state.pointer_color_pointer = pointer;
3149 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3150 gl_state.pointer_color_offset = bufferoffset;
3152 GL_BindVBO(bufferobject);
3153 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3158 // caller wants color array disabled
3159 if (gl_state.pointer_color_enabled)
3161 gl_state.pointer_color_enabled = false;
3163 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3164 // when color array is on the glColor gets trashed, set it again
3165 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3169 case RENDERPATH_GL20:
3170 case RENDERPATH_GLES2:
3174 // caller wants color array enabled
3175 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3176 if (!gl_state.pointer_color_enabled)
3178 gl_state.pointer_color_enabled = true;
3180 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3182 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)
3184 gl_state.pointer_color_components = components;
3185 gl_state.pointer_color_gltype = gltype;
3186 gl_state.pointer_color_stride = stride;
3187 gl_state.pointer_color_pointer = pointer;
3188 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3189 gl_state.pointer_color_offset = bufferoffset;
3191 GL_BindVBO(bufferobject);
3192 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3197 // caller wants color array disabled
3198 if (gl_state.pointer_color_enabled)
3200 gl_state.pointer_color_enabled = false;
3202 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3203 // when color array is on the glColor gets trashed, set it again
3204 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3208 case RENDERPATH_D3D9:
3209 case RENDERPATH_D3D10:
3210 case RENDERPATH_D3D11:
3211 case RENDERPATH_SOFT:
3216 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)
3218 gltextureunit_t *unit = gl_state.units + unitnum;
3219 // update array settings
3220 // note: there is no need to check bufferobject here because all cases
3221 // that involve a valid bufferobject also supply a texcoord array
3222 switch(vid.renderpath)
3224 case RENDERPATH_GL11:
3225 case RENDERPATH_GL13:
3229 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3230 // texture array unit is enabled, enable the array
3231 if (!unit->arrayenabled)
3233 unit->arrayenabled = true;
3234 GL_ClientActiveTexture(unitnum);
3235 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3238 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)
3240 unit->pointer_texcoord_components = components;
3241 unit->pointer_texcoord_gltype = gltype;
3242 unit->pointer_texcoord_stride = stride;
3243 unit->pointer_texcoord_pointer = pointer;
3244 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3245 unit->pointer_texcoord_offset = bufferoffset;
3246 GL_ClientActiveTexture(unitnum);
3247 GL_BindVBO(bufferobject);
3248 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3253 // texture array unit is disabled, disable the array
3254 if (unit->arrayenabled)
3256 unit->arrayenabled = false;
3257 GL_ClientActiveTexture(unitnum);
3258 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3262 case RENDERPATH_GL20:
3263 case RENDERPATH_GLES2:
3267 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3268 // texture array unit is enabled, enable the array
3269 if (!unit->arrayenabled)
3271 unit->arrayenabled = true;
3272 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3275 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)
3277 unit->pointer_texcoord_components = components;
3278 unit->pointer_texcoord_gltype = gltype;
3279 unit->pointer_texcoord_stride = stride;
3280 unit->pointer_texcoord_pointer = pointer;
3281 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3282 unit->pointer_texcoord_offset = bufferoffset;
3283 GL_BindVBO(bufferobject);
3284 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3289 // texture array unit is disabled, disable the array
3290 if (unit->arrayenabled)
3292 unit->arrayenabled = false;
3293 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3297 case RENDERPATH_D3D9:
3298 case RENDERPATH_D3D10:
3299 case RENDERPATH_D3D11:
3300 case RENDERPATH_SOFT:
3305 int R_Mesh_TexBound(unsigned int unitnum, int id)
3307 gltextureunit_t *unit = gl_state.units + unitnum;
3308 if (unitnum >= vid.teximageunits)
3310 if (id == GL_TEXTURE_2D)
3312 if (id == GL_TEXTURE_3D)
3314 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3315 return unit->tcubemap;
3319 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3321 switch(vid.renderpath)
3323 case RENDERPATH_GL11:
3324 case RENDERPATH_GL13:
3325 case RENDERPATH_GL20:
3326 case RENDERPATH_GLES2:
3327 R_Mesh_TexBind(0, tex);
3328 GL_ActiveTexture(0);CHECKGLERROR
3329 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3331 case RENDERPATH_D3D9:
3334 IDirect3DSurface9 *currentsurface = NULL;
3335 IDirect3DSurface9 *texturesurface = NULL;
3338 sourcerect.left = sx;
3339 sourcerect.top = sy;
3340 sourcerect.right = sx + width;
3341 sourcerect.bottom = sy + height;
3344 destrect.right = tx + width;
3345 destrect.bottom = ty + height;
3346 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3348 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3350 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3351 IDirect3DSurface9_Release(currentsurface);
3353 IDirect3DSurface9_Release(texturesurface);
3358 case RENDERPATH_D3D10:
3359 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3361 case RENDERPATH_D3D11:
3362 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3364 case RENDERPATH_SOFT:
3365 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3371 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};
3374 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3376 gltextureunit_t *unit = gl_state.units + unitnum;
3377 int tex2d, tex3d, texcubemap, texnum;
3378 if (unitnum >= vid.teximageunits)
3380 // if (unit->texture == tex)
3382 switch(vid.renderpath)
3384 case RENDERPATH_GL20:
3385 case RENDERPATH_GLES2:
3388 tex = r_texture_white;
3389 // not initialized enough yet...
3393 unit->texture = tex;
3394 texnum = R_GetTexture(tex);
3395 switch(tex->gltexturetypeenum)
3397 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3398 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3399 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;
3402 case RENDERPATH_GL13:
3403 case RENDERPATH_GL11:
3404 unit->texture = tex;
3410 texnum = R_GetTexture(tex);
3411 switch(tex->gltexturetypeenum)
3419 case GL_TEXTURE_CUBE_MAP_ARB:
3420 texcubemap = texnum;
3424 // update 2d texture binding
3425 if (unit->t2d != tex2d)
3427 GL_ActiveTexture(unitnum);
3432 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3439 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3443 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3445 // update 3d texture binding
3446 if (unit->t3d != tex3d)
3448 GL_ActiveTexture(unitnum);
3453 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3460 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3464 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3466 // update cubemap texture binding
3467 if (unit->tcubemap != texcubemap)
3469 GL_ActiveTexture(unitnum);
3472 if (unit->tcubemap == 0)
3474 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3481 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3484 unit->tcubemap = texcubemap;
3485 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3488 case RENDERPATH_D3D9:
3491 extern cvar_t gl_texture_anisotropy;
3494 tex = r_texture_white;
3495 // not initialized enough yet...
3499 // upload texture if needed
3501 if (unit->texture == tex)
3503 unit->texture = tex;
3504 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3505 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3506 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3507 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3508 if (tex->d3daddressw)
3509 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3510 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3511 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3512 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3513 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3514 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3515 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3519 case RENDERPATH_D3D10:
3520 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3522 case RENDERPATH_D3D11:
3523 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3525 case RENDERPATH_SOFT:
3528 tex = r_texture_white;
3529 // not initialized enough yet...
3533 texnum = R_GetTexture(tex);
3534 if (unit->texture == tex)
3536 unit->texture = tex;
3537 DPSOFTRAST_SetTexture(unitnum, texnum);
3542 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3544 gltextureunit_t *unit = gl_state.units + unitnum;
3545 switch(vid.renderpath)
3547 case RENDERPATH_GL11:
3548 case RENDERPATH_GL13:
3549 case RENDERPATH_GL20:
3550 case RENDERPATH_GLES2:
3551 if (matrix && matrix->m[3][3])
3553 // texmatrix specified, check if it is different
3554 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3557 unit->texmatrixenabled = true;
3558 unit->matrix = *matrix;
3560 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3561 GL_ActiveTexture(unitnum);
3562 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3563 qglLoadMatrixf(glmatrix);CHECKGLERROR
3564 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3569 // no texmatrix specified, revert to identity
3570 if (unit->texmatrixenabled)
3572 unit->texmatrixenabled = false;
3573 unit->matrix = identitymatrix;
3575 GL_ActiveTexture(unitnum);
3576 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3577 qglLoadIdentity();CHECKGLERROR
3578 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3582 case RENDERPATH_D3D9:
3583 case RENDERPATH_D3D10:
3584 case RENDERPATH_D3D11:
3586 case RENDERPATH_SOFT:
3591 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3593 gltextureunit_t *unit = gl_state.units + unitnum;
3595 switch(vid.renderpath)
3597 case RENDERPATH_GL20:
3598 case RENDERPATH_GLES2:
3601 case RENDERPATH_GL13:
3602 // GL_ARB_texture_env_combine
3604 combinergb = GL_MODULATE;
3606 combinealpha = GL_MODULATE;
3611 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3613 if (combinergb == GL_DECAL)
3614 combinergb = GL_INTERPOLATE_ARB;
3615 if (unit->combine != GL_COMBINE_ARB)
3617 unit->combine = GL_COMBINE_ARB;
3618 GL_ActiveTexture(unitnum);
3619 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3620 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3622 if (unit->combinergb != combinergb)
3624 unit->combinergb = combinergb;
3625 GL_ActiveTexture(unitnum);
3626 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3628 if (unit->combinealpha != combinealpha)
3630 unit->combinealpha = combinealpha;
3631 GL_ActiveTexture(unitnum);
3632 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3634 if (unit->rgbscale != rgbscale)
3636 unit->rgbscale = rgbscale;
3637 GL_ActiveTexture(unitnum);
3638 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3640 if (unit->alphascale != alphascale)
3642 unit->alphascale = alphascale;
3643 GL_ActiveTexture(unitnum);
3644 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3649 if (unit->combine != combinergb)
3651 unit->combine = combinergb;
3652 GL_ActiveTexture(unitnum);
3653 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3657 case RENDERPATH_GL11:
3660 combinergb = GL_MODULATE;
3661 if (unit->combine != combinergb)
3663 unit->combine = combinergb;
3664 GL_ActiveTexture(unitnum);
3665 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3668 case RENDERPATH_D3D9:
3669 case RENDERPATH_D3D10:
3670 case RENDERPATH_D3D11:
3672 case RENDERPATH_SOFT:
3677 void R_Mesh_ResetTextureState(void)
3679 unsigned int unitnum;
3683 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3684 R_Mesh_TexBind(unitnum, NULL);
3685 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3686 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3687 switch(vid.renderpath)
3689 case RENDERPATH_GL20:
3690 case RENDERPATH_GLES2:
3691 case RENDERPATH_D3D9:
3692 case RENDERPATH_D3D10:
3693 case RENDERPATH_D3D11:
3694 case RENDERPATH_SOFT:
3696 case RENDERPATH_GL13:
3697 case RENDERPATH_GL11:
3698 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3700 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3701 R_Mesh_TexMatrix(unitnum, NULL);
3710 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3711 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3712 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3714 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3716 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3720 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3722 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3723 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3724 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3728 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3730 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3731 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3732 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3733 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3734 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3735 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3736 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3740 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3741 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3742 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3745 static void R_Mesh_InitVertexDeclarations(void)
3748 r_vertex3f_d3d9decl = NULL;
3749 r_vertexgeneric_d3d9decl = NULL;
3750 r_vertexmesh_d3d9decl = NULL;
3751 switch(vid.renderpath)
3753 case RENDERPATH_GL20:
3754 case RENDERPATH_GL13:
3755 case RENDERPATH_GL11:
3756 case RENDERPATH_GLES2:
3758 case RENDERPATH_D3D9:
3759 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3760 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3761 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3763 case RENDERPATH_D3D10:
3764 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3766 case RENDERPATH_D3D11:
3767 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3769 case RENDERPATH_SOFT:
3775 static void R_Mesh_DestroyVertexDeclarations(void)
3778 if (r_vertex3f_d3d9decl)
3779 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3780 r_vertex3f_d3d9decl = NULL;
3781 if (r_vertexgeneric_d3d9decl)
3782 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3783 r_vertexgeneric_d3d9decl = NULL;
3784 if (r_vertexmesh_d3d9decl)
3785 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3786 r_vertexmesh_d3d9decl = NULL;
3790 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3792 // upload temporary vertexbuffer for this rendering
3793 if (!gl_state.usevbo_staticvertex)
3794 vertexbuffer = NULL;
3795 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3797 if (gl_state.preparevertices_dynamicvertexbuffer)
3798 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3800 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3801 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3803 switch(vid.renderpath)
3805 case RENDERPATH_GL20:
3806 case RENDERPATH_GLES2:
3809 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3810 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3811 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3812 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3813 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3814 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3815 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3819 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3820 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3821 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3822 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3823 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3824 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3825 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3828 case RENDERPATH_GL13:
3831 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3832 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3833 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3834 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3838 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3839 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3840 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3841 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3844 case RENDERPATH_GL11:
3847 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3848 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3849 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3853 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3854 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3855 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3858 case RENDERPATH_D3D9:
3860 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3862 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3864 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3865 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3866 gl_state.d3dvertexdata = (void *)vertex3f;
3867 gl_state.d3dvertexsize = sizeof(float[3]);
3870 case RENDERPATH_D3D10:
3871 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3873 case RENDERPATH_D3D11:
3874 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3876 case RENDERPATH_SOFT:
3877 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3878 DPSOFTRAST_SetColorPointer(NULL, 0);
3879 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3880 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3881 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3882 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3883 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3890 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3893 size = sizeof(r_vertexgeneric_t) * numvertices;
3894 if (gl_state.preparevertices_tempdatamaxsize < size)
3896 gl_state.preparevertices_tempdatamaxsize = size;
3897 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3899 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3900 gl_state.preparevertices_numvertices = numvertices;
3901 return gl_state.preparevertices_vertexgeneric;
3904 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
3906 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
3907 gl_state.preparevertices_vertexgeneric = NULL;
3908 gl_state.preparevertices_numvertices = 0;
3912 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
3915 r_vertexgeneric_t *vertex;
3916 switch(vid.renderpath)
3918 case RENDERPATH_GL20:
3919 case RENDERPATH_GLES2:
3920 if (!vid.useinterleavedarrays)
3922 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3923 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3924 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3925 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3926 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3927 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3928 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3932 case RENDERPATH_GL13:
3933 case RENDERPATH_GL11:
3934 if (!vid.useinterleavedarrays)
3936 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3937 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3938 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3939 if (vid.texunits >= 2)
3940 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3941 if (vid.texunits >= 3)
3942 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3946 case RENDERPATH_D3D9:
3947 case RENDERPATH_D3D10:
3948 case RENDERPATH_D3D11:
3950 case RENDERPATH_SOFT:
3951 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3952 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
3953 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
3954 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3955 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3956 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3957 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3961 // no quick path for this case, convert to vertex structs
3962 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
3963 for (i = 0;i < numvertices;i++)
3964 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3967 for (i = 0;i < numvertices;i++)
3968 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
3972 float tempcolor4f[4];
3973 unsigned char tempcolor4ub[4];
3974 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
3975 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
3976 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
3977 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
3978 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
3979 for (i = 0;i < numvertices;i++)
3980 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
3983 for (i = 0;i < numvertices;i++)
3984 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
3985 R_Mesh_PrepareVertices_Generic_Unlock();
3986 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
3989 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
3991 // upload temporary vertexbuffer for this rendering
3992 if (!gl_state.usevbo_staticvertex)
3993 vertexbuffer = NULL;
3994 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3996 if (gl_state.preparevertices_dynamicvertexbuffer)
3997 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
3999 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4000 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4002 switch(vid.renderpath)
4004 case RENDERPATH_GL20:
4005 case RENDERPATH_GLES2:
4008 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4009 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4010 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4011 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4012 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4013 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4014 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4018 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4019 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4020 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4021 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4022 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4023 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4024 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4027 case RENDERPATH_GL13:
4030 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4031 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4032 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4033 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4037 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4038 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4039 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4040 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4043 case RENDERPATH_GL11:
4046 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4047 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4048 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4052 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4053 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4054 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4057 case RENDERPATH_D3D9:
4059 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4061 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4063 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4064 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4065 gl_state.d3dvertexdata = (void *)vertex;
4066 gl_state.d3dvertexsize = sizeof(*vertex);
4069 case RENDERPATH_D3D10:
4070 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4072 case RENDERPATH_D3D11:
4073 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4075 case RENDERPATH_SOFT:
4076 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4077 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4078 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4079 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4080 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4081 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4082 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4089 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4092 size = sizeof(r_vertexmesh_t) * numvertices;
4093 if (gl_state.preparevertices_tempdatamaxsize < size)
4095 gl_state.preparevertices_tempdatamaxsize = size;
4096 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4098 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4099 gl_state.preparevertices_numvertices = numvertices;
4100 return gl_state.preparevertices_vertexmesh;
4103 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4105 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4106 gl_state.preparevertices_vertexmesh = NULL;
4107 gl_state.preparevertices_numvertices = 0;
4111 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)
4114 r_vertexmesh_t *vertex;
4115 switch(vid.renderpath)
4117 case RENDERPATH_GL20:
4118 case RENDERPATH_GLES2:
4119 if (!vid.useinterleavedarrays)
4121 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4122 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4123 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4124 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4125 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4126 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4127 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4131 case RENDERPATH_GL13:
4132 case RENDERPATH_GL11:
4133 if (!vid.useinterleavedarrays)
4135 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4136 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4137 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4138 if (vid.texunits >= 2)
4139 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4140 if (vid.texunits >= 3)
4141 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4145 case RENDERPATH_D3D9:
4146 case RENDERPATH_D3D10:
4147 case RENDERPATH_D3D11:
4149 case RENDERPATH_SOFT:
4150 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4151 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4152 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4153 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4154 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4155 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4156 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4160 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4161 for (i = 0;i < numvertices;i++)
4162 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4164 for (i = 0;i < numvertices;i++)
4165 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4167 for (i = 0;i < numvertices;i++)
4168 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4170 for (i = 0;i < numvertices;i++)
4171 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4174 for (i = 0;i < numvertices;i++)
4175 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
4179 float tempcolor4f[4];
4180 unsigned char tempcolor4ub[4];
4181 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
4182 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
4183 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
4184 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
4185 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
4186 for (i = 0;i < numvertices;i++)
4187 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
4189 if (texcoordtexture2f)
4190 for (i = 0;i < numvertices;i++)
4191 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4192 if (texcoordlightmap2f)
4193 for (i = 0;i < numvertices;i++)
4194 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4195 R_Mesh_PrepareVertices_Mesh_Unlock();
4196 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4199 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4201 // upload temporary vertexbuffer for this rendering
4202 if (!gl_state.usevbo_staticvertex)
4203 vertexbuffer = NULL;
4204 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4206 if (gl_state.preparevertices_dynamicvertexbuffer)
4207 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4209 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4210 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4212 switch(vid.renderpath)
4214 case RENDERPATH_GL20:
4215 case RENDERPATH_GLES2:
4218 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4219 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4220 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4221 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4222 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4223 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4224 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4228 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4229 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4230 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4231 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4232 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4233 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4234 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4237 case RENDERPATH_GL13:
4240 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4241 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4242 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4243 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4247 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4248 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4249 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4250 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4253 case RENDERPATH_GL11:
4256 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4257 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4258 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4262 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4263 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4264 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4267 case RENDERPATH_D3D9:
4269 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4271 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4273 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4274 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4275 gl_state.d3dvertexdata = (void *)vertex;
4276 gl_state.d3dvertexsize = sizeof(*vertex);
4279 case RENDERPATH_D3D10:
4280 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4282 case RENDERPATH_D3D11:
4283 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4285 case RENDERPATH_SOFT:
4286 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4287 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4288 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4289 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4290 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4291 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4292 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);