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");
2422 if(qglBindFragDataLocation)
2423 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2425 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2428 #ifdef GL_GEOMETRY_SHADER
2429 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2433 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2436 qglLinkProgram(programobject);CHECKGLERROR
2437 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2438 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2441 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2442 Con_DPrintf("program link log:\n%s\n", linklog);
2443 // software vertex shader is ok but software fragment shader is WAY
2444 // too slow, fail program if so.
2445 // NOTE: this string might be ATI specific, but that's ok because the
2446 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2447 // software fragment shader due to low instruction and dependent
2449 if (strstr(linklog, "fragment shader will run in software"))
2450 programlinked = false;
2454 return programobject;
2456 qglDeleteProgram(programobject);CHECKGLERROR
2460 void GL_Backend_FreeProgram(unsigned int prog)
2463 qglDeleteProgram(prog);
2467 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2472 for (i = 0;i < count;i++)
2473 *out++ = *in++ + offset;
2476 memcpy(out, in, sizeof(*out) * count);
2479 // renders triangles using vertices from the active arrays
2480 int paranoidblah = 0;
2481 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)
2483 unsigned int numelements = numtriangles * 3;
2485 size_t bufferoffset3i;
2487 size_t bufferoffset3s;
2488 if (numvertices < 3 || numtriangles < 1)
2490 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2491 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);
2494 if (!gl_mesh_prefer_short_elements.integer)
2498 if (element3i_indexbuffer)
2499 element3i_indexbuffer = NULL;
2501 // adjust the pointers for firsttriangle
2503 element3i += firsttriangle * 3;
2504 if (element3i_indexbuffer)
2505 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2507 element3s += firsttriangle * 3;
2508 if (element3s_indexbuffer)
2509 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2510 switch(vid.renderpath)
2512 case RENDERPATH_GL11:
2513 case RENDERPATH_GL13:
2514 case RENDERPATH_GL20:
2515 case RENDERPATH_GLES2:
2516 // check if the user specified to ignore static index buffers
2517 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2519 element3i_indexbuffer = NULL;
2520 element3s_indexbuffer = NULL;
2523 case RENDERPATH_D3D9:
2524 case RENDERPATH_D3D10:
2525 case RENDERPATH_D3D11:
2527 case RENDERPATH_SOFT:
2530 // upload a dynamic index buffer if needed
2533 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2535 if (gl_state.draw_dynamicindexbuffer)
2536 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2538 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2539 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2540 element3s_bufferoffset = 0;
2545 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2547 if (gl_state.draw_dynamicindexbuffer)
2548 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2550 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2551 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2552 element3i_bufferoffset = 0;
2555 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2556 bufferoffset3i = element3i_bufferoffset;
2557 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2558 bufferoffset3s = element3s_bufferoffset;
2559 r_refdef.stats.draws++;
2560 r_refdef.stats.draws_vertices += numvertices;
2561 r_refdef.stats.draws_elements += numelements;
2562 if (gl_paranoid.integer)
2565 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2567 unsigned int j, size;
2569 // note: there's no validation done here on buffer objects because it
2570 // is somewhat difficult to get at the data, and gl_paranoid can be
2571 // used without buffer objects if the need arises
2572 // (the data could be gotten using glMapBuffer but it would be very
2573 // slow due to uncachable video memory reads)
2574 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2575 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2577 if (gl_state.pointer_vertex_pointer)
2578 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2580 if (gl_state.pointer_color_enabled)
2582 if (!qglIsEnabled(GL_COLOR_ARRAY))
2583 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2585 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2586 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2589 for (i = 0;i < vid.texarrayunits;i++)
2591 if (gl_state.units[i].arrayenabled)
2593 GL_ClientActiveTexture(i);
2594 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2595 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2597 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2598 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++)
2605 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2607 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2609 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2616 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2618 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2620 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2626 if (r_render.integer || r_refdef.draw2dstage)
2628 switch(vid.renderpath)
2630 case RENDERPATH_GL11:
2631 case RENDERPATH_GL13:
2632 case RENDERPATH_GL20:
2634 if (gl_mesh_testmanualfeeding.integer)
2636 unsigned int i, j, element;
2638 qglBegin(GL_TRIANGLES);
2639 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2642 element = element3i[i];
2644 element = element3s[i];
2646 element = firstvertex + i;
2647 for (j = 0;j < vid.texarrayunits;j++)
2649 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2651 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2653 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2654 if (vid.texarrayunits > 1)
2656 if (gl_state.units[j].pointer_texcoord_components == 4)
2657 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2658 else if (gl_state.units[j].pointer_texcoord_components == 3)
2659 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2660 else if (gl_state.units[j].pointer_texcoord_components == 2)
2661 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2663 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2667 if (gl_state.units[j].pointer_texcoord_components == 4)
2668 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2669 else if (gl_state.units[j].pointer_texcoord_components == 3)
2670 qglTexCoord3f(p[0], p[1], p[2]);
2671 else if (gl_state.units[j].pointer_texcoord_components == 2)
2672 qglTexCoord2f(p[0], p[1]);
2674 qglTexCoord1f(p[0]);
2677 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2679 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2680 if (vid.texarrayunits > 1)
2682 if (gl_state.units[j].pointer_texcoord_components == 4)
2683 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2684 else if (gl_state.units[j].pointer_texcoord_components == 3)
2685 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2686 else if (gl_state.units[j].pointer_texcoord_components == 2)
2687 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2688 else if (gl_state.units[j].pointer_texcoord_components == 1)
2689 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2693 if (gl_state.units[j].pointer_texcoord_components == 4)
2694 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2695 else if (gl_state.units[j].pointer_texcoord_components == 3)
2696 qglTexCoord3f(s[0], s[1], s[2]);
2697 else if (gl_state.units[j].pointer_texcoord_components == 2)
2698 qglTexCoord2f(s[0], s[1]);
2699 else if (gl_state.units[j].pointer_texcoord_components == 1)
2700 qglTexCoord1f(s[0]);
2703 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2705 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2706 if (vid.texarrayunits > 1)
2708 if (gl_state.units[j].pointer_texcoord_components == 4)
2709 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2710 else if (gl_state.units[j].pointer_texcoord_components == 3)
2711 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2712 else if (gl_state.units[j].pointer_texcoord_components == 2)
2713 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2714 else if (gl_state.units[j].pointer_texcoord_components == 1)
2715 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2719 if (gl_state.units[j].pointer_texcoord_components == 4)
2720 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2721 else if (gl_state.units[j].pointer_texcoord_components == 3)
2722 qglTexCoord3f(sb[0], sb[1], sb[2]);
2723 else if (gl_state.units[j].pointer_texcoord_components == 2)
2724 qglTexCoord2f(sb[0], sb[1]);
2725 else if (gl_state.units[j].pointer_texcoord_components == 1)
2726 qglTexCoord1f(sb[0]);
2731 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2733 if (gl_state.pointer_color_gltype == GL_FLOAT)
2735 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2736 qglColor4f(p[0], p[1], p[2], p[3]);
2738 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2740 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2741 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2744 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2746 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2747 if (gl_state.pointer_vertex_components == 4)
2748 qglVertex4f(p[0], p[1], p[2], p[3]);
2749 else if (gl_state.pointer_vertex_components == 3)
2750 qglVertex3f(p[0], p[1], p[2]);
2752 qglVertex2f(p[0], p[1]);
2758 else if (bufferobject3s)
2760 GL_BindEBO(bufferobject3s);
2761 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2763 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2768 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2772 else if (bufferobject3i)
2774 GL_BindEBO(bufferobject3i);
2775 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2777 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2782 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2789 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2791 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2796 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2803 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2805 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2810 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2816 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2820 case RENDERPATH_D3D9:
2822 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2824 if (element3s_indexbuffer)
2826 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2827 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2829 else if (element3i_indexbuffer)
2831 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2832 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2835 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2840 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2842 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2844 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2848 case RENDERPATH_D3D10:
2849 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2851 case RENDERPATH_D3D11:
2852 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2854 case RENDERPATH_SOFT:
2855 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2857 case RENDERPATH_GLES2:
2858 // GLES does not have glDrawRangeElements, and generally
2859 // underperforms with index buffers, so this code path is
2860 // relatively straightforward...
2862 if (gl_paranoid.integer)
2864 int r, prog, enabled, i;
2865 GLsizei attriblength;
2868 GLchar attribname[1024];
2869 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2870 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2871 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2872 #ifndef GL_CURRENT_PROGRAM
2873 #define GL_CURRENT_PROGRAM 0x8B8D
2875 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2876 if (r < 0 || r > 10000)
2877 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2879 for (i = 0;i < 8;i++)
2881 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2884 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2885 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);
2891 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2896 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2901 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2909 // restores backend state, used when done with 3D rendering
2910 void R_Mesh_Finish(void)
2912 R_Mesh_ResetRenderTargets();
2915 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2917 r_meshbuffer_t *buffer;
2918 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2920 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2921 memset(buffer, 0, sizeof(*buffer));
2922 buffer->bufferobject = 0;
2923 buffer->devicebuffer = NULL;
2925 buffer->isindexbuffer = isindexbuffer;
2926 buffer->isdynamic = isdynamic;
2927 buffer->isindex16 = isindex16;
2928 strlcpy(buffer->name, name, sizeof(buffer->name));
2929 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2933 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
2937 if (buffer->isindexbuffer)
2939 r_refdef.stats.indexbufferuploadcount++;
2940 r_refdef.stats.indexbufferuploadsize += size;
2944 r_refdef.stats.vertexbufferuploadcount++;
2945 r_refdef.stats.vertexbufferuploadsize += size;
2947 switch(vid.renderpath)
2949 case RENDERPATH_GL11:
2950 case RENDERPATH_GL13:
2951 case RENDERPATH_GL20:
2952 case RENDERPATH_GLES2:
2953 if (!buffer->bufferobject)
2954 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
2955 if (buffer->isindexbuffer)
2956 GL_BindEBO(buffer->bufferobject);
2958 GL_BindVBO(buffer->bufferobject);
2959 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
2961 case RENDERPATH_D3D9:
2965 void *datapointer = NULL;
2966 if (buffer->isindexbuffer)
2968 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
2969 if (size > buffer->size || !buffer->devicebuffer)
2971 if (buffer->devicebuffer)
2972 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
2973 buffer->devicebuffer = NULL;
2974 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)))
2975 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);
2976 buffer->devicebuffer = (void *)d3d9indexbuffer;
2977 buffer->size = size;
2979 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2982 memcpy(datapointer, data, size);
2984 memset(datapointer, 0, size);
2985 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
2990 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
2991 if (size > buffer->size || !buffer->devicebuffer)
2993 if (buffer->devicebuffer)
2994 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
2995 buffer->devicebuffer = NULL;
2996 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
2997 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);
2998 buffer->devicebuffer = (void *)d3d9vertexbuffer;
2999 buffer->size = size;
3001 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3004 memcpy(datapointer, data, size);
3006 memset(datapointer, 0, size);
3007 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3013 case RENDERPATH_D3D10:
3014 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3016 case RENDERPATH_D3D11:
3017 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3019 case RENDERPATH_SOFT:
3024 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3028 switch(vid.renderpath)
3030 case RENDERPATH_GL11:
3031 case RENDERPATH_GL13:
3032 case RENDERPATH_GL20:
3033 case RENDERPATH_GLES2:
3034 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3036 case RENDERPATH_D3D9:
3038 if (gl_state.d3dvertexbuffer == (void *)buffer)
3039 gl_state.d3dvertexbuffer = NULL;
3040 if (buffer->devicebuffer)
3042 if (buffer->isindexbuffer)
3043 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3045 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3046 buffer->devicebuffer = NULL;
3050 case RENDERPATH_D3D10:
3051 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053 case RENDERPATH_D3D11:
3054 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056 case RENDERPATH_SOFT:
3059 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3062 void GL_Mesh_ListVBOs(qboolean printeach)
3065 size_t ebocount = 0, ebomemory = 0;
3066 size_t vbocount = 0, vbomemory = 0;
3067 r_meshbuffer_t *buffer;
3068 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3069 for (i = 0;i < endindex;i++)
3071 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3074 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)");}
3075 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)");}
3077 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);
3082 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3084 switch(vid.renderpath)
3086 case RENDERPATH_GL11:
3087 case RENDERPATH_GL13:
3088 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)
3090 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3091 gl_state.pointer_vertex_components = components;
3092 gl_state.pointer_vertex_gltype = gltype;
3093 gl_state.pointer_vertex_stride = stride;
3094 gl_state.pointer_vertex_pointer = pointer;
3095 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3096 gl_state.pointer_vertex_offset = bufferoffset;
3098 GL_BindVBO(bufferobject);
3099 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3102 case RENDERPATH_GL20:
3103 case RENDERPATH_GLES2:
3104 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)
3106 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3107 gl_state.pointer_vertex_components = components;
3108 gl_state.pointer_vertex_gltype = gltype;
3109 gl_state.pointer_vertex_stride = stride;
3110 gl_state.pointer_vertex_pointer = pointer;
3111 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3112 gl_state.pointer_vertex_offset = bufferoffset;
3114 GL_BindVBO(bufferobject);
3115 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3118 case RENDERPATH_D3D9:
3119 case RENDERPATH_D3D10:
3120 case RENDERPATH_D3D11:
3121 case RENDERPATH_SOFT:
3126 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3128 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3129 // the pointer only.
3130 switch(vid.renderpath)
3132 case RENDERPATH_GL11:
3133 case RENDERPATH_GL13:
3137 // caller wants color array enabled
3138 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3139 if (!gl_state.pointer_color_enabled)
3141 gl_state.pointer_color_enabled = true;
3143 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3145 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)
3147 gl_state.pointer_color_components = components;
3148 gl_state.pointer_color_gltype = gltype;
3149 gl_state.pointer_color_stride = stride;
3150 gl_state.pointer_color_pointer = pointer;
3151 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3152 gl_state.pointer_color_offset = bufferoffset;
3154 GL_BindVBO(bufferobject);
3155 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3160 // caller wants color array disabled
3161 if (gl_state.pointer_color_enabled)
3163 gl_state.pointer_color_enabled = false;
3165 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3166 // when color array is on the glColor gets trashed, set it again
3167 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3171 case RENDERPATH_GL20:
3172 case RENDERPATH_GLES2:
3176 // caller wants color array enabled
3177 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3178 if (!gl_state.pointer_color_enabled)
3180 gl_state.pointer_color_enabled = true;
3182 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3184 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)
3186 gl_state.pointer_color_components = components;
3187 gl_state.pointer_color_gltype = gltype;
3188 gl_state.pointer_color_stride = stride;
3189 gl_state.pointer_color_pointer = pointer;
3190 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3191 gl_state.pointer_color_offset = bufferoffset;
3193 GL_BindVBO(bufferobject);
3194 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3199 // caller wants color array disabled
3200 if (gl_state.pointer_color_enabled)
3202 gl_state.pointer_color_enabled = false;
3204 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3205 // when color array is on the glColor gets trashed, set it again
3206 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3210 case RENDERPATH_D3D9:
3211 case RENDERPATH_D3D10:
3212 case RENDERPATH_D3D11:
3213 case RENDERPATH_SOFT:
3218 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)
3220 gltextureunit_t *unit = gl_state.units + unitnum;
3221 // update array settings
3222 // note: there is no need to check bufferobject here because all cases
3223 // that involve a valid bufferobject also supply a texcoord array
3224 switch(vid.renderpath)
3226 case RENDERPATH_GL11:
3227 case RENDERPATH_GL13:
3231 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3232 // texture array unit is enabled, enable the array
3233 if (!unit->arrayenabled)
3235 unit->arrayenabled = true;
3236 GL_ClientActiveTexture(unitnum);
3237 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3240 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)
3242 unit->pointer_texcoord_components = components;
3243 unit->pointer_texcoord_gltype = gltype;
3244 unit->pointer_texcoord_stride = stride;
3245 unit->pointer_texcoord_pointer = pointer;
3246 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3247 unit->pointer_texcoord_offset = bufferoffset;
3248 GL_ClientActiveTexture(unitnum);
3249 GL_BindVBO(bufferobject);
3250 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3255 // texture array unit is disabled, disable the array
3256 if (unit->arrayenabled)
3258 unit->arrayenabled = false;
3259 GL_ClientActiveTexture(unitnum);
3260 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3264 case RENDERPATH_GL20:
3265 case RENDERPATH_GLES2:
3269 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3270 // texture array unit is enabled, enable the array
3271 if (!unit->arrayenabled)
3273 unit->arrayenabled = true;
3274 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3277 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)
3279 unit->pointer_texcoord_components = components;
3280 unit->pointer_texcoord_gltype = gltype;
3281 unit->pointer_texcoord_stride = stride;
3282 unit->pointer_texcoord_pointer = pointer;
3283 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3284 unit->pointer_texcoord_offset = bufferoffset;
3285 GL_BindVBO(bufferobject);
3286 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3291 // texture array unit is disabled, disable the array
3292 if (unit->arrayenabled)
3294 unit->arrayenabled = false;
3295 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3299 case RENDERPATH_D3D9:
3300 case RENDERPATH_D3D10:
3301 case RENDERPATH_D3D11:
3302 case RENDERPATH_SOFT:
3307 int R_Mesh_TexBound(unsigned int unitnum, int id)
3309 gltextureunit_t *unit = gl_state.units + unitnum;
3310 if (unitnum >= vid.teximageunits)
3312 if (id == GL_TEXTURE_2D)
3314 if (id == GL_TEXTURE_3D)
3316 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3317 return unit->tcubemap;
3321 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3323 switch(vid.renderpath)
3325 case RENDERPATH_GL11:
3326 case RENDERPATH_GL13:
3327 case RENDERPATH_GL20:
3328 case RENDERPATH_GLES2:
3329 R_Mesh_TexBind(0, tex);
3330 GL_ActiveTexture(0);CHECKGLERROR
3331 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3333 case RENDERPATH_D3D9:
3336 IDirect3DSurface9 *currentsurface = NULL;
3337 IDirect3DSurface9 *texturesurface = NULL;
3340 sourcerect.left = sx;
3341 sourcerect.top = sy;
3342 sourcerect.right = sx + width;
3343 sourcerect.bottom = sy + height;
3346 destrect.right = tx + width;
3347 destrect.bottom = ty + height;
3348 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3350 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3352 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3353 IDirect3DSurface9_Release(currentsurface);
3355 IDirect3DSurface9_Release(texturesurface);
3360 case RENDERPATH_D3D10:
3361 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3363 case RENDERPATH_D3D11:
3364 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3366 case RENDERPATH_SOFT:
3367 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3373 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};
3376 void R_Mesh_ClearBindingsForTexture(int texnum)
3378 gltextureunit_t *unit;
3379 unsigned int unitnum;
3380 // this doesn't really unbind the texture, but it does prevent a mistaken "do nothing" behavior on the next time this same texnum is bound on the same unit as the same type (this mainly affects r_shadow_bouncegrid because 3D textures are so rarely used)
3381 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3383 unit = gl_state.units + unitnum;
3384 if (unit->t2d == texnum)
3386 if (unit->t3d == texnum)
3388 if (unit->tcubemap == texnum)
3389 unit->tcubemap = -1;
3393 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3395 gltextureunit_t *unit = gl_state.units + unitnum;
3396 int tex2d, tex3d, texcubemap, texnum;
3397 if (unitnum >= vid.teximageunits)
3399 // if (unit->texture == tex)
3401 switch(vid.renderpath)
3403 case RENDERPATH_GL20:
3404 case RENDERPATH_GLES2:
3407 tex = r_texture_white;
3408 // not initialized enough yet...
3412 unit->texture = tex;
3413 texnum = R_GetTexture(tex);
3414 switch(tex->gltexturetypeenum)
3416 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3417 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3418 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;
3421 case RENDERPATH_GL13:
3422 case RENDERPATH_GL11:
3423 unit->texture = tex;
3429 texnum = R_GetTexture(tex);
3430 switch(tex->gltexturetypeenum)
3438 case GL_TEXTURE_CUBE_MAP_ARB:
3439 texcubemap = texnum;
3443 // update 2d texture binding
3444 if (unit->t2d != tex2d)
3446 GL_ActiveTexture(unitnum);
3451 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3458 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3462 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3464 // update 3d texture binding
3465 if (unit->t3d != tex3d)
3467 GL_ActiveTexture(unitnum);
3472 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3479 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3483 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3485 // update cubemap texture binding
3486 if (unit->tcubemap != texcubemap)
3488 GL_ActiveTexture(unitnum);
3491 if (unit->tcubemap == 0)
3493 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3500 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3503 unit->tcubemap = texcubemap;
3504 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3507 case RENDERPATH_D3D9:
3510 extern cvar_t gl_texture_anisotropy;
3513 tex = r_texture_white;
3514 // not initialized enough yet...
3518 // upload texture if needed
3520 if (unit->texture == tex)
3522 unit->texture = tex;
3523 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3524 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3525 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3526 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3527 if (tex->d3daddressw)
3528 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3529 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3530 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3531 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3532 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3533 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3534 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3538 case RENDERPATH_D3D10:
3539 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3541 case RENDERPATH_D3D11:
3542 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3544 case RENDERPATH_SOFT:
3547 tex = r_texture_white;
3548 // not initialized enough yet...
3552 texnum = R_GetTexture(tex);
3553 if (unit->texture == tex)
3555 unit->texture = tex;
3556 DPSOFTRAST_SetTexture(unitnum, texnum);
3561 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3563 gltextureunit_t *unit = gl_state.units + unitnum;
3564 switch(vid.renderpath)
3566 case RENDERPATH_GL11:
3567 case RENDERPATH_GL13:
3568 case RENDERPATH_GL20:
3569 case RENDERPATH_GLES2:
3570 if (matrix && matrix->m[3][3])
3572 // texmatrix specified, check if it is different
3573 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3576 unit->texmatrixenabled = true;
3577 unit->matrix = *matrix;
3579 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3580 GL_ActiveTexture(unitnum);
3581 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3582 qglLoadMatrixf(glmatrix);CHECKGLERROR
3583 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3588 // no texmatrix specified, revert to identity
3589 if (unit->texmatrixenabled)
3591 unit->texmatrixenabled = false;
3592 unit->matrix = identitymatrix;
3594 GL_ActiveTexture(unitnum);
3595 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3596 qglLoadIdentity();CHECKGLERROR
3597 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3601 case RENDERPATH_D3D9:
3602 case RENDERPATH_D3D10:
3603 case RENDERPATH_D3D11:
3605 case RENDERPATH_SOFT:
3610 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3612 gltextureunit_t *unit = gl_state.units + unitnum;
3614 switch(vid.renderpath)
3616 case RENDERPATH_GL20:
3617 case RENDERPATH_GLES2:
3620 case RENDERPATH_GL13:
3621 // GL_ARB_texture_env_combine
3623 combinergb = GL_MODULATE;
3625 combinealpha = GL_MODULATE;
3630 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3632 if (combinergb == GL_DECAL)
3633 combinergb = GL_INTERPOLATE_ARB;
3634 if (unit->combine != GL_COMBINE_ARB)
3636 unit->combine = GL_COMBINE_ARB;
3637 GL_ActiveTexture(unitnum);
3638 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3639 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3641 if (unit->combinergb != combinergb)
3643 unit->combinergb = combinergb;
3644 GL_ActiveTexture(unitnum);
3645 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3647 if (unit->combinealpha != combinealpha)
3649 unit->combinealpha = combinealpha;
3650 GL_ActiveTexture(unitnum);
3651 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3653 if (unit->rgbscale != rgbscale)
3655 unit->rgbscale = rgbscale;
3656 GL_ActiveTexture(unitnum);
3657 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3659 if (unit->alphascale != alphascale)
3661 unit->alphascale = alphascale;
3662 GL_ActiveTexture(unitnum);
3663 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3668 if (unit->combine != combinergb)
3670 unit->combine = combinergb;
3671 GL_ActiveTexture(unitnum);
3672 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3676 case RENDERPATH_GL11:
3679 combinergb = GL_MODULATE;
3680 if (unit->combine != combinergb)
3682 unit->combine = combinergb;
3683 GL_ActiveTexture(unitnum);
3684 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3687 case RENDERPATH_D3D9:
3688 case RENDERPATH_D3D10:
3689 case RENDERPATH_D3D11:
3691 case RENDERPATH_SOFT:
3696 void R_Mesh_ResetTextureState(void)
3698 unsigned int unitnum;
3702 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3703 R_Mesh_TexBind(unitnum, NULL);
3704 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3705 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3706 switch(vid.renderpath)
3708 case RENDERPATH_GL20:
3709 case RENDERPATH_GLES2:
3710 case RENDERPATH_D3D9:
3711 case RENDERPATH_D3D10:
3712 case RENDERPATH_D3D11:
3713 case RENDERPATH_SOFT:
3715 case RENDERPATH_GL13:
3716 case RENDERPATH_GL11:
3717 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3719 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3720 R_Mesh_TexMatrix(unitnum, NULL);
3729 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3730 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3731 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3733 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3735 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3739 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3741 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3742 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3743 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3747 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3749 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3750 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3751 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3752 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3753 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3754 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3755 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3759 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3760 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3761 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3764 static void R_Mesh_InitVertexDeclarations(void)
3767 r_vertex3f_d3d9decl = NULL;
3768 r_vertexgeneric_d3d9decl = NULL;
3769 r_vertexmesh_d3d9decl = NULL;
3770 switch(vid.renderpath)
3772 case RENDERPATH_GL20:
3773 case RENDERPATH_GL13:
3774 case RENDERPATH_GL11:
3775 case RENDERPATH_GLES2:
3777 case RENDERPATH_D3D9:
3778 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3779 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3780 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3782 case RENDERPATH_D3D10:
3783 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3785 case RENDERPATH_D3D11:
3786 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3788 case RENDERPATH_SOFT:
3794 static void R_Mesh_DestroyVertexDeclarations(void)
3797 if (r_vertex3f_d3d9decl)
3798 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3799 r_vertex3f_d3d9decl = NULL;
3800 if (r_vertexgeneric_d3d9decl)
3801 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3802 r_vertexgeneric_d3d9decl = NULL;
3803 if (r_vertexmesh_d3d9decl)
3804 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3805 r_vertexmesh_d3d9decl = NULL;
3809 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3811 // upload temporary vertexbuffer for this rendering
3812 if (!gl_state.usevbo_staticvertex)
3813 vertexbuffer = NULL;
3814 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3816 if (gl_state.preparevertices_dynamicvertexbuffer)
3817 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3819 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3820 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3822 switch(vid.renderpath)
3824 case RENDERPATH_GL20:
3825 case RENDERPATH_GLES2:
3828 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3829 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3830 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3831 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3832 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3833 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3834 R_Mesh_TexCoordPointer(4, 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);
3842 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3843 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3844 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3847 case RENDERPATH_GL13:
3850 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3851 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3852 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3853 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3857 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3858 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3859 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3860 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3863 case RENDERPATH_GL11:
3866 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3867 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3868 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3872 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3873 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3874 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3877 case RENDERPATH_D3D9:
3879 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3881 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3883 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3884 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3885 gl_state.d3dvertexdata = (void *)vertex3f;
3886 gl_state.d3dvertexsize = sizeof(float[3]);
3889 case RENDERPATH_D3D10:
3890 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3892 case RENDERPATH_D3D11:
3893 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3895 case RENDERPATH_SOFT:
3896 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3897 DPSOFTRAST_SetColorPointer(NULL, 0);
3898 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3899 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3900 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3901 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3902 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3909 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3912 size = sizeof(r_vertexgeneric_t) * numvertices;
3913 if (gl_state.preparevertices_tempdatamaxsize < size)
3915 gl_state.preparevertices_tempdatamaxsize = size;
3916 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3918 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3919 gl_state.preparevertices_numvertices = numvertices;
3920 return gl_state.preparevertices_vertexgeneric;
3923 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
3925 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
3926 gl_state.preparevertices_vertexgeneric = NULL;
3927 gl_state.preparevertices_numvertices = 0;
3931 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
3934 r_vertexgeneric_t *vertex;
3935 switch(vid.renderpath)
3937 case RENDERPATH_GL20:
3938 case RENDERPATH_GLES2:
3939 if (!vid.useinterleavedarrays)
3941 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3942 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3943 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3944 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3945 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3946 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3947 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3951 case RENDERPATH_GL13:
3952 case RENDERPATH_GL11:
3953 if (!vid.useinterleavedarrays)
3955 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3956 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3957 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3958 if (vid.texunits >= 2)
3959 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3960 if (vid.texunits >= 3)
3961 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3965 case RENDERPATH_D3D9:
3966 case RENDERPATH_D3D10:
3967 case RENDERPATH_D3D11:
3969 case RENDERPATH_SOFT:
3970 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3971 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
3972 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
3973 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3974 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3975 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3976 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3980 // no quick path for this case, convert to vertex structs
3981 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
3982 for (i = 0;i < numvertices;i++)
3983 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3986 for (i = 0;i < numvertices;i++)
3987 Vector4Copy(color4f + 4*i, vertex[i].color4f);
3991 for (i = 0;i < numvertices;i++)
3992 Vector4Copy(gl_state.color4f, vertex[i].color4f);
3995 for (i = 0;i < numvertices;i++)
3996 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
3997 R_Mesh_PrepareVertices_Generic_Unlock();
3998 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4001 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4003 // upload temporary vertexbuffer for this rendering
4004 if (!gl_state.usevbo_staticvertex)
4005 vertexbuffer = NULL;
4006 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4008 if (gl_state.preparevertices_dynamicvertexbuffer)
4009 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4011 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4012 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4014 switch(vid.renderpath)
4016 case RENDERPATH_GL20:
4017 case RENDERPATH_GLES2:
4020 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4021 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4022 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4023 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4024 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4025 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4026 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4030 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4031 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4032 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4033 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4034 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4035 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4036 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4039 case RENDERPATH_GL13:
4042 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4043 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4044 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4045 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4049 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4050 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4051 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4052 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4055 case RENDERPATH_GL11:
4058 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4059 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4060 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4064 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4065 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4066 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4069 case RENDERPATH_D3D9:
4071 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4073 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4075 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4076 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4077 gl_state.d3dvertexdata = (void *)vertex;
4078 gl_state.d3dvertexsize = sizeof(*vertex);
4081 case RENDERPATH_D3D10:
4082 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4084 case RENDERPATH_D3D11:
4085 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4087 case RENDERPATH_SOFT:
4088 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4089 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4090 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4091 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4092 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4093 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4094 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4101 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4104 size = sizeof(r_vertexmesh_t) * numvertices;
4105 if (gl_state.preparevertices_tempdatamaxsize < size)
4107 gl_state.preparevertices_tempdatamaxsize = size;
4108 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4110 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4111 gl_state.preparevertices_numvertices = numvertices;
4112 return gl_state.preparevertices_vertexmesh;
4115 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4117 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4118 gl_state.preparevertices_vertexmesh = NULL;
4119 gl_state.preparevertices_numvertices = 0;
4123 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)
4126 r_vertexmesh_t *vertex;
4127 switch(vid.renderpath)
4129 case RENDERPATH_GL20:
4130 case RENDERPATH_GLES2:
4131 if (!vid.useinterleavedarrays)
4133 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4134 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4135 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4136 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4137 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4138 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4139 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4143 case RENDERPATH_GL13:
4144 case RENDERPATH_GL11:
4145 if (!vid.useinterleavedarrays)
4147 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4148 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4149 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4150 if (vid.texunits >= 2)
4151 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4152 if (vid.texunits >= 3)
4153 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4157 case RENDERPATH_D3D9:
4158 case RENDERPATH_D3D10:
4159 case RENDERPATH_D3D11:
4161 case RENDERPATH_SOFT:
4162 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4163 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4164 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4165 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4166 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4167 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4168 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4172 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4173 for (i = 0;i < numvertices;i++)
4174 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4176 for (i = 0;i < numvertices;i++)
4177 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4179 for (i = 0;i < numvertices;i++)
4180 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4182 for (i = 0;i < numvertices;i++)
4183 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4186 for (i = 0;i < numvertices;i++)
4187 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4191 for (i = 0;i < numvertices;i++)
4192 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4194 if (texcoordtexture2f)
4195 for (i = 0;i < numvertices;i++)
4196 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4197 if (texcoordlightmap2f)
4198 for (i = 0;i < numvertices;i++)
4199 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4200 R_Mesh_PrepareVertices_Mesh_Unlock();
4201 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4204 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4206 // upload temporary vertexbuffer for this rendering
4207 if (!gl_state.usevbo_staticvertex)
4208 vertexbuffer = NULL;
4209 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4211 if (gl_state.preparevertices_dynamicvertexbuffer)
4212 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4214 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4215 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4217 switch(vid.renderpath)
4219 case RENDERPATH_GL20:
4220 case RENDERPATH_GLES2:
4223 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4224 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4225 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4226 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4227 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4228 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4229 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4233 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4234 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4235 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4236 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4237 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4238 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4239 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4242 case RENDERPATH_GL13:
4245 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4246 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4247 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4248 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4252 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4253 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4254 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4255 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4258 case RENDERPATH_GL11:
4261 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4262 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4263 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4267 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4268 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4269 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4272 case RENDERPATH_D3D9:
4274 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4276 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4278 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4279 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4280 gl_state.d3dvertexdata = (void *)vertex;
4281 gl_state.d3dvertexsize = sizeof(*vertex);
4284 case RENDERPATH_D3D10:
4285 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4287 case RENDERPATH_D3D11:
4288 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4290 case RENDERPATH_SOFT:
4291 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4292 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4293 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4294 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4295 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4296 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4297 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);