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;
548 switch(vid.renderpath)
550 case RENDERPATH_GL11:
551 case RENDERPATH_GL13:
552 case RENDERPATH_GL20:
553 case RENDERPATH_GLES2:
556 case RENDERPATH_D3D9:
557 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
559 case RENDERPATH_D3D10:
560 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
562 case RENDERPATH_D3D11:
563 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
565 case RENDERPATH_SOFT:
571 static int bboxedges[12][2] =
590 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
592 int i, ix1, iy1, ix2, iy2;
593 float x1, y1, x2, y2;
604 scissor[0] = r_refdef.view.viewport.x;
605 scissor[1] = r_refdef.view.viewport.y;
606 scissor[2] = r_refdef.view.viewport.width;
607 scissor[3] = r_refdef.view.viewport.height;
609 // if view is inside the box, just say yes it's visible
610 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
613 x1 = y1 = x2 = y2 = 0;
615 // transform all corners that are infront of the nearclip plane
616 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
617 plane4f[3] = r_refdef.view.frustum[4].dist;
619 for (i = 0;i < 8;i++)
621 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
622 dist[i] = DotProduct4(corner[i], plane4f);
623 sign[i] = dist[i] > 0;
626 VectorCopy(corner[i], vertex[numvertices]);
630 // if some points are behind the nearclip, add clipped edge points to make
631 // sure that the scissor boundary is complete
632 if (numvertices > 0 && numvertices < 8)
634 // add clipped edge points
635 for (i = 0;i < 12;i++)
639 if (sign[j] != sign[k])
641 f = dist[j] / (dist[j] - dist[k]);
642 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
648 // if we have no points to check, it is behind the view plane
652 // if we have some points to transform, check what screen area is covered
653 x1 = y1 = x2 = y2 = 0;
655 //Con_Printf("%i vertices to transform...\n", numvertices);
656 for (i = 0;i < numvertices;i++)
658 VectorCopy(vertex[i], v);
659 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
660 //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]);
663 if (x1 > v2[0]) x1 = v2[0];
664 if (x2 < v2[0]) x2 = v2[0];
665 if (y1 > v2[1]) y1 = v2[1];
666 if (y2 < v2[1]) y2 = v2[1];
675 // now convert the scissor rectangle to integer screen coordinates
676 ix1 = (int)(x1 - 1.0f);
677 //iy1 = vid.height - (int)(y2 - 1.0f);
678 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
679 iy1 = (int)(y1 - 1.0f);
680 ix2 = (int)(x2 + 1.0f);
681 //iy2 = vid.height - (int)(y1 + 1.0f);
682 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
683 iy2 = (int)(y2 + 1.0f);
684 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
686 // clamp it to the screen
687 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
688 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
689 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
690 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
692 // if it is inside out, it's not visible
693 if (ix2 <= ix1 || iy2 <= iy1)
696 // the light area is visible, set up the scissor rectangle
699 scissor[2] = ix2 - ix1;
700 scissor[3] = iy2 - iy1;
702 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
703 switch(vid.renderpath)
705 case RENDERPATH_D3D9:
706 case RENDERPATH_D3D10:
707 case RENDERPATH_D3D11:
708 scissor[1] = vid.height - scissor[1] - scissor[3];
710 case RENDERPATH_GL11:
711 case RENDERPATH_GL13:
712 case RENDERPATH_GL20:
713 case RENDERPATH_SOFT:
714 case RENDERPATH_GLES2:
722 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
726 float clipPlane[4], v3[3], v4[3];
729 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
731 VectorSet(normal, normalx, normaly, normalz);
732 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
733 VectorScale(normal, -dist, v3);
734 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
735 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
736 clipPlane[3] = -DotProduct(v4, clipPlane);
740 // testing code for comparing results
742 VectorCopy4(clipPlane, clipPlane2);
743 R_EntityMatrix(&identitymatrix);
744 VectorSet(q, normal[0], normal[1], normal[2], -dist);
745 qglClipPlane(GL_CLIP_PLANE0, q);
746 qglGetClipPlane(GL_CLIP_PLANE0, q);
747 VectorCopy4(q, clipPlane);
751 // Calculate the clip-space corner point opposite the clipping plane
752 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
753 // transform it into camera space by multiplying it
754 // by the inverse of the projection matrix
755 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
756 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
758 q[3] = (1.0f + m[10]) / m[14];
760 // Calculate the scaled plane vector
761 d = 2.0f / DotProduct4(clipPlane, q);
763 // Replace the third row of the projection matrix
764 m[2] = clipPlane[0] * d;
765 m[6] = clipPlane[1] * d;
766 m[10] = clipPlane[2] * d + 1.0f;
767 m[14] = clipPlane[3] * d;
770 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)
772 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
774 memset(v, 0, sizeof(*v));
775 v->type = R_VIEWPORTTYPE_ORTHO;
776 v->cameramatrix = *cameramatrix;
783 memset(m, 0, sizeof(m));
784 m[0] = 2/(right - left);
785 m[5] = 2/(top - bottom);
786 m[10] = -2/(zFar - zNear);
787 m[12] = - (right + left)/(right - left);
788 m[13] = - (top + bottom)/(top - bottom);
789 m[14] = - (zFar + zNear)/(zFar - zNear);
791 switch(vid.renderpath)
793 case RENDERPATH_GL11:
794 case RENDERPATH_GL13:
795 case RENDERPATH_GL20:
796 case RENDERPATH_SOFT:
797 case RENDERPATH_GLES2:
799 case RENDERPATH_D3D9:
800 case RENDERPATH_D3D10:
801 case RENDERPATH_D3D11:
802 m[10] = -1/(zFar - zNear);
803 m[14] = -zNear/(zFar-zNear);
806 v->screentodepth[0] = -farclip / (farclip - nearclip);
807 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
809 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
812 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
814 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
820 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
821 R_Viewport_TransformToScreen(v, test1, test2);
822 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
827 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)
829 matrix4x4_t tempmatrix, basematrix;
831 memset(v, 0, sizeof(*v));
833 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
834 v->cameramatrix = *cameramatrix;
841 memset(m, 0, sizeof(m));
842 m[0] = 1.0 / frustumx;
843 m[5] = 1.0 / frustumy;
844 m[10] = -(farclip + nearclip) / (farclip - nearclip);
846 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
847 v->screentodepth[0] = -farclip / (farclip - nearclip);
848 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
850 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
851 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
852 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
853 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
856 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
858 if(v_flipped.integer)
866 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
869 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)
871 matrix4x4_t tempmatrix, basematrix;
872 const float nudge = 1.0 - 1.0 / (1<<23);
874 memset(v, 0, sizeof(*v));
876 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
877 v->cameramatrix = *cameramatrix;
884 memset(m, 0, sizeof(m));
885 m[ 0] = 1.0 / frustumx;
886 m[ 5] = 1.0 / frustumy;
889 m[14] = -2 * nearclip * nudge;
890 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
891 v->screentodepth[1] = m[14] * -0.5;
893 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
894 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
895 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
896 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
899 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
901 if(v_flipped.integer)
909 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
912 float cubeviewmatrix[6][16] =
914 // standard cubemap projections
952 float rectviewmatrix[6][16] =
954 // sign-preserving cubemap projections
993 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
995 matrix4x4_t tempmatrix, basematrix;
997 memset(v, 0, sizeof(*v));
998 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
999 v->cameramatrix = *cameramatrix;
1003 memset(m, 0, sizeof(m));
1005 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1007 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1009 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
1010 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1011 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1014 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1016 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1019 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)
1021 matrix4x4_t tempmatrix, basematrix;
1023 memset(v, 0, sizeof(*v));
1024 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1025 v->cameramatrix = *cameramatrix;
1026 v->x = (side & 1) * size;
1027 v->y = (side >> 1) * size;
1031 memset(m, 0, sizeof(m));
1032 m[0] = m[5] = 1.0f * ((float)size - border) / size;
1033 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1035 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1037 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1038 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1039 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1041 switch(vid.renderpath)
1043 case RENDERPATH_GL20:
1044 case RENDERPATH_GL13:
1045 case RENDERPATH_GL11:
1046 case RENDERPATH_SOFT:
1047 case RENDERPATH_GLES2:
1049 case RENDERPATH_D3D9:
1052 case RENDERPATH_D3D10:
1053 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1055 case RENDERPATH_D3D11:
1056 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1061 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1063 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1066 void R_SetViewport(const r_viewport_t *v)
1071 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1072 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1074 // copy over the matrices to our state
1075 gl_viewmatrix = v->viewmatrix;
1076 gl_projectionmatrix = v->projectmatrix;
1078 switch(vid.renderpath)
1080 case RENDERPATH_GL13:
1081 case RENDERPATH_GL11:
1083 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1084 // Load the projection matrix into OpenGL
1085 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1086 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1087 qglLoadMatrixf(m);CHECKGLERROR
1088 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1090 case RENDERPATH_D3D9:
1093 D3DVIEWPORT9 d3dviewport;
1094 d3dviewport.X = gl_viewport.x;
1095 d3dviewport.Y = gl_viewport.y;
1096 d3dviewport.Width = gl_viewport.width;
1097 d3dviewport.Height = gl_viewport.height;
1098 d3dviewport.MinZ = gl_state.depthrange[0];
1099 d3dviewport.MaxZ = gl_state.depthrange[1];
1100 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1104 case RENDERPATH_D3D10:
1105 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1107 case RENDERPATH_D3D11:
1108 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1110 case RENDERPATH_SOFT:
1111 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1113 case RENDERPATH_GL20:
1114 case RENDERPATH_GLES2:
1116 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1120 // force an update of the derived matrices
1121 gl_modelmatrixchanged = true;
1122 R_EntityMatrix(&gl_modelmatrix);
1125 void R_GetViewport(r_viewport_t *v)
1130 static void GL_BindVBO(int bufferobject)
1132 if (gl_state.vertexbufferobject != bufferobject)
1134 gl_state.vertexbufferobject = bufferobject;
1136 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1140 static void GL_BindEBO(int bufferobject)
1142 if (gl_state.elementbufferobject != bufferobject)
1144 gl_state.elementbufferobject = bufferobject;
1146 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1150 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1153 switch(vid.renderpath)
1155 case RENDERPATH_GL11:
1156 case RENDERPATH_GL13:
1157 case RENDERPATH_GL20:
1158 case RENDERPATH_GLES2:
1159 if (!vid.support.ext_framebuffer_object)
1161 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1162 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1163 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1164 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1165 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1166 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1167 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1169 case RENDERPATH_D3D9:
1170 case RENDERPATH_D3D10:
1171 case RENDERPATH_D3D11:
1173 case RENDERPATH_SOFT:
1179 void R_Mesh_DestroyFramebufferObject(int fbo)
1181 switch(vid.renderpath)
1183 case RENDERPATH_GL11:
1184 case RENDERPATH_GL13:
1185 case RENDERPATH_GL20:
1186 case RENDERPATH_GLES2:
1188 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1190 case RENDERPATH_D3D9:
1191 case RENDERPATH_D3D10:
1192 case RENDERPATH_D3D11:
1194 case RENDERPATH_SOFT:
1200 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1202 // 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)
1203 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)
1206 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1207 if (gl_state.d3drt_depthsurface != depthsurface)
1209 gl_state.d3drt_depthsurface = depthsurface;
1210 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1212 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1214 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1215 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1217 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1219 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1220 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1222 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1224 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1225 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1227 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1229 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1230 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1235 void R_Mesh_ResetRenderTargets(void)
1237 switch(vid.renderpath)
1239 case RENDERPATH_GL11:
1240 case RENDERPATH_GL13:
1241 case RENDERPATH_GL20:
1242 case RENDERPATH_GLES2:
1243 if (gl_state.framebufferobject)
1245 gl_state.framebufferobject = 0;
1246 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1249 case RENDERPATH_D3D9:
1251 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1254 case RENDERPATH_D3D10:
1255 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1257 case RENDERPATH_D3D11:
1258 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1260 case RENDERPATH_SOFT:
1261 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1266 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1270 rtexture_t *textures[5];
1271 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1272 textures[4] = depthtexture;
1273 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1274 for (j = 0;j < 5;j++)
1276 for (i = 0;i < vid.teximageunits;i++)
1277 if (gl_state.units[i].texture == textures[j])
1278 R_Mesh_TexBind(i, NULL);
1279 // set up framebuffer object or render targets for the active rendering API
1280 switch(vid.renderpath)
1282 case RENDERPATH_GL11:
1283 case RENDERPATH_GL13:
1284 case RENDERPATH_GL20:
1285 case RENDERPATH_GLES2:
1286 if (gl_state.framebufferobject != fbo)
1288 gl_state.framebufferobject = fbo;
1289 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1292 case RENDERPATH_D3D9:
1294 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1295 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1298 IDirect3DSurface9 *colorsurfaces[4];
1299 for (i = 0;i < 4;i++)
1301 colorsurfaces[i] = NULL;
1303 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1305 // set the render targets for real
1306 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1307 // release the texture surface levels (they won't be lost while bound...)
1308 for (i = 0;i < 4;i++)
1310 IDirect3DSurface9_Release(colorsurfaces[i]);
1313 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1316 case RENDERPATH_D3D10:
1317 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1319 case RENDERPATH_D3D11:
1320 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1322 case RENDERPATH_SOFT:
1326 unsigned int *pointers[5];
1327 memset(pointers, 0, sizeof(pointers));
1328 for (i = 0;i < 5;i++)
1329 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1330 width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1331 height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1332 DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1335 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1341 static int d3dcmpforglfunc(int f)
1345 case GL_NEVER: return D3DCMP_NEVER;
1346 case GL_LESS: return D3DCMP_LESS;
1347 case GL_EQUAL: return D3DCMP_EQUAL;
1348 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1349 case GL_GREATER: return D3DCMP_GREATER;
1350 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1351 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1352 case GL_ALWAYS: return D3DCMP_ALWAYS;
1353 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1357 static int d3dstencilopforglfunc(int f)
1361 case GL_KEEP: return D3DSTENCILOP_KEEP;
1362 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1363 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1364 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1370 static void GL_Backend_ResetState(void)
1373 gl_state.active = true;
1374 gl_state.depthtest = true;
1375 gl_state.alphatest = false;
1376 gl_state.alphafunc = GL_GEQUAL;
1377 gl_state.alphafuncvalue = 0.5f;
1378 gl_state.blendfunc1 = GL_ONE;
1379 gl_state.blendfunc2 = GL_ZERO;
1380 gl_state.blend = false;
1381 gl_state.depthmask = GL_TRUE;
1382 gl_state.colormask = 15;
1383 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1384 gl_state.lockrange_first = 0;
1385 gl_state.lockrange_count = 0;
1386 gl_state.cullface = GL_FRONT;
1387 gl_state.cullfaceenable = false;
1388 gl_state.polygonoffset[0] = 0;
1389 gl_state.polygonoffset[1] = 0;
1390 gl_state.framebufferobject = 0;
1391 gl_state.depthfunc = GL_LEQUAL;
1393 switch(vid.renderpath)
1395 case RENDERPATH_D3D9:
1398 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1399 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1400 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1401 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1402 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1403 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1404 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1405 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1406 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1407 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1411 case RENDERPATH_D3D10:
1412 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1414 case RENDERPATH_D3D11:
1415 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1417 case RENDERPATH_GL13:
1418 case RENDERPATH_GL11:
1421 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1422 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1423 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1424 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1425 qglDisable(GL_BLEND);CHECKGLERROR
1426 qglCullFace(gl_state.cullface);CHECKGLERROR
1427 qglDisable(GL_CULL_FACE);CHECKGLERROR
1428 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1429 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1430 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1431 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1433 if (vid.support.arb_vertex_buffer_object)
1435 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1436 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1439 if (vid.support.ext_framebuffer_object)
1441 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1442 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1445 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1446 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1448 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1449 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1450 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1452 if (vid.support.ext_framebuffer_object)
1453 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1455 gl_state.unit = MAX_TEXTUREUNITS;
1456 gl_state.clientunit = MAX_TEXTUREUNITS;
1457 for (i = 0;i < vid.texunits;i++)
1459 GL_ActiveTexture(i);
1460 GL_ClientActiveTexture(i);
1461 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1462 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1463 if (vid.support.ext_texture_3d)
1465 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1466 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1468 if (vid.support.arb_texture_cube_map)
1470 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1471 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1474 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1475 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1476 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1477 qglLoadIdentity();CHECKGLERROR
1478 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1479 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1483 case RENDERPATH_SOFT:
1484 DPSOFTRAST_ColorMask(1,1,1,1);
1485 DPSOFTRAST_AlphaTest(gl_state.alphatest);
1486 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1487 DPSOFTRAST_CullFace(gl_state.cullface);
1488 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1489 DPSOFTRAST_DepthMask(gl_state.depthmask);
1490 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1491 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1492 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1494 case RENDERPATH_GL20:
1495 case RENDERPATH_GLES2:
1497 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1498 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1499 qglDisable(GL_BLEND);CHECKGLERROR
1500 qglCullFace(gl_state.cullface);CHECKGLERROR
1501 qglDisable(GL_CULL_FACE);CHECKGLERROR
1502 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1503 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1504 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1505 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1506 // if (vid.renderpath == RENDERPATH_GL20)
1508 // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1509 // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1511 if (vid.support.arb_vertex_buffer_object)
1513 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1514 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1516 if (vid.support.ext_framebuffer_object)
1517 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1518 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1519 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1520 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1521 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1522 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1523 gl_state.unit = MAX_TEXTUREUNITS;
1524 gl_state.clientunit = MAX_TEXTUREUNITS;
1525 for (i = 0;i < vid.teximageunits;i++)
1527 GL_ActiveTexture(i);
1528 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1529 if (vid.support.ext_texture_3d)
1531 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1533 if (vid.support.arb_texture_cube_map)
1535 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1538 for (i = 0;i < vid.texarrayunits;i++)
1541 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1542 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1549 void GL_ActiveTexture(unsigned int num)
1551 if (gl_state.unit != num)
1553 gl_state.unit = num;
1554 switch(vid.renderpath)
1556 case RENDERPATH_GL11:
1557 case RENDERPATH_GL13:
1558 case RENDERPATH_GL20:
1559 case RENDERPATH_GLES2:
1560 if (qglActiveTexture)
1563 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1567 case RENDERPATH_D3D9:
1568 case RENDERPATH_D3D10:
1569 case RENDERPATH_D3D11:
1571 case RENDERPATH_SOFT:
1577 void GL_ClientActiveTexture(unsigned int num)
1579 if (gl_state.clientunit != num)
1581 gl_state.clientunit = num;
1582 switch(vid.renderpath)
1584 case RENDERPATH_GL11:
1585 case RENDERPATH_GL13:
1586 if (qglActiveTexture)
1589 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1593 case RENDERPATH_D3D9:
1594 case RENDERPATH_D3D10:
1595 case RENDERPATH_D3D11:
1597 case RENDERPATH_SOFT:
1599 case RENDERPATH_GL20:
1600 case RENDERPATH_GLES2:
1606 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1608 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1610 qboolean blendenable;
1611 gl_state.blendfunc1 = blendfunc1;
1612 gl_state.blendfunc2 = blendfunc2;
1613 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1614 switch(vid.renderpath)
1616 case RENDERPATH_GL11:
1617 case RENDERPATH_GL13:
1618 case RENDERPATH_GL20:
1619 case RENDERPATH_GLES2:
1621 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1622 if (gl_state.blend != blendenable)
1624 gl_state.blend = blendenable;
1625 if (!gl_state.blend)
1627 qglDisable(GL_BLEND);CHECKGLERROR
1631 qglEnable(GL_BLEND);CHECKGLERROR
1635 case RENDERPATH_D3D9:
1640 D3DBLEND d3dblendfunc[2];
1641 glblendfunc[0] = gl_state.blendfunc1;
1642 glblendfunc[1] = gl_state.blendfunc2;
1643 for (i = 0;i < 2;i++)
1645 switch(glblendfunc[i])
1647 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1648 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1649 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1650 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1651 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1652 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1653 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1654 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1655 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1656 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1659 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1660 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1661 if (gl_state.blend != blendenable)
1663 gl_state.blend = blendenable;
1664 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1669 case RENDERPATH_D3D10:
1670 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1672 case RENDERPATH_D3D11:
1673 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1675 case RENDERPATH_SOFT:
1676 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1682 void GL_DepthMask(int state)
1684 if (gl_state.depthmask != state)
1686 gl_state.depthmask = state;
1687 switch(vid.renderpath)
1689 case RENDERPATH_GL11:
1690 case RENDERPATH_GL13:
1691 case RENDERPATH_GL20:
1692 case RENDERPATH_GLES2:
1694 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1696 case RENDERPATH_D3D9:
1698 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1701 case RENDERPATH_D3D10:
1702 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1704 case RENDERPATH_D3D11:
1705 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1707 case RENDERPATH_SOFT:
1708 DPSOFTRAST_DepthMask(gl_state.depthmask);
1714 void GL_DepthTest(int state)
1716 if (gl_state.depthtest != state)
1718 gl_state.depthtest = state;
1719 switch(vid.renderpath)
1721 case RENDERPATH_GL11:
1722 case RENDERPATH_GL13:
1723 case RENDERPATH_GL20:
1724 case RENDERPATH_GLES2:
1726 if (gl_state.depthtest)
1728 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1732 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1735 case RENDERPATH_D3D9:
1737 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1740 case RENDERPATH_D3D10:
1741 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1743 case RENDERPATH_D3D11:
1744 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1746 case RENDERPATH_SOFT:
1747 DPSOFTRAST_DepthTest(gl_state.depthtest);
1753 void GL_DepthFunc(int state)
1755 if (gl_state.depthfunc != state)
1757 gl_state.depthfunc = state;
1758 switch(vid.renderpath)
1760 case RENDERPATH_GL11:
1761 case RENDERPATH_GL13:
1762 case RENDERPATH_GL20:
1763 case RENDERPATH_GLES2:
1765 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1767 case RENDERPATH_D3D9:
1769 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1772 case RENDERPATH_D3D10:
1773 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1775 case RENDERPATH_D3D11:
1776 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1778 case RENDERPATH_SOFT:
1779 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1785 void GL_DepthRange(float nearfrac, float farfrac)
1787 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1789 gl_state.depthrange[0] = nearfrac;
1790 gl_state.depthrange[1] = farfrac;
1791 switch(vid.renderpath)
1793 case RENDERPATH_GL11:
1794 case RENDERPATH_GL13:
1795 case RENDERPATH_GL20:
1796 case RENDERPATH_GLES2:
1797 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1799 case RENDERPATH_D3D9:
1802 D3DVIEWPORT9 d3dviewport;
1803 d3dviewport.X = gl_viewport.x;
1804 d3dviewport.Y = gl_viewport.y;
1805 d3dviewport.Width = gl_viewport.width;
1806 d3dviewport.Height = gl_viewport.height;
1807 d3dviewport.MinZ = gl_state.depthrange[0];
1808 d3dviewport.MaxZ = gl_state.depthrange[1];
1809 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1813 case RENDERPATH_D3D10:
1814 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1816 case RENDERPATH_D3D11:
1817 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1819 case RENDERPATH_SOFT:
1820 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1826 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)
1828 switch (vid.renderpath)
1830 case RENDERPATH_GL11:
1831 case RENDERPATH_GL13:
1832 case RENDERPATH_GL20:
1833 case RENDERPATH_GLES2:
1837 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1841 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1843 if (vid.support.ati_separate_stencil)
1845 qglStencilMask(writemask);CHECKGLERROR
1846 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1847 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1848 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1850 else if (vid.support.ext_stencil_two_side)
1852 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1853 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1854 qglStencilMask(writemask);CHECKGLERROR
1855 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1856 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1857 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1858 qglStencilMask(writemask);CHECKGLERROR
1859 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1860 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1863 case RENDERPATH_D3D9:
1865 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1866 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1867 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1868 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1869 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1870 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1871 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1872 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1873 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1874 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1875 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1876 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1877 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1880 case RENDERPATH_D3D10:
1881 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1883 case RENDERPATH_D3D11:
1884 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1886 case RENDERPATH_SOFT:
1887 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1894 switch (vid.renderpath)
1896 case RENDERPATH_GL11:
1897 case RENDERPATH_GL13:
1898 case RENDERPATH_GL20:
1899 case RENDERPATH_GLES2:
1903 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1907 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1909 if (vid.support.ext_stencil_two_side)
1911 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1913 qglStencilMask(writemask);CHECKGLERROR
1914 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1915 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1918 case RENDERPATH_D3D9:
1920 if (vid.support.ati_separate_stencil)
1921 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1922 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1923 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1924 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1925 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1926 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1927 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1928 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1929 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1932 case RENDERPATH_D3D10:
1933 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1935 case RENDERPATH_D3D11:
1936 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1938 case RENDERPATH_SOFT:
1939 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944 void GL_PolygonOffset(float planeoffset, float depthoffset)
1946 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1948 gl_state.polygonoffset[0] = planeoffset;
1949 gl_state.polygonoffset[1] = depthoffset;
1950 switch(vid.renderpath)
1952 case RENDERPATH_GL11:
1953 case RENDERPATH_GL13:
1954 case RENDERPATH_GL20:
1955 case RENDERPATH_GLES2:
1956 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1958 case RENDERPATH_D3D9:
1960 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1961 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1964 case RENDERPATH_D3D10:
1965 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1967 case RENDERPATH_D3D11:
1968 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1970 case RENDERPATH_SOFT:
1971 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1977 void GL_SetMirrorState(qboolean state)
1979 if (v_flipped_state != state)
1981 v_flipped_state = state;
1982 if (gl_state.cullface == GL_BACK)
1983 gl_state.cullface = GL_FRONT;
1984 else if (gl_state.cullface == GL_FRONT)
1985 gl_state.cullface = GL_BACK;
1988 switch(vid.renderpath)
1990 case RENDERPATH_GL11:
1991 case RENDERPATH_GL13:
1992 case RENDERPATH_GL20:
1993 case RENDERPATH_GLES2:
1994 qglCullFace(gl_state.cullface);CHECKGLERROR
1996 case RENDERPATH_D3D9:
1998 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2001 case RENDERPATH_D3D10:
2002 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2004 case RENDERPATH_D3D11:
2005 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2007 case RENDERPATH_SOFT:
2008 DPSOFTRAST_CullFace(gl_state.cullface);
2014 void GL_CullFace(int state)
2018 if(state == GL_FRONT)
2020 else if(state == GL_BACK)
2024 switch(vid.renderpath)
2026 case RENDERPATH_GL11:
2027 case RENDERPATH_GL13:
2028 case RENDERPATH_GL20:
2029 case RENDERPATH_GLES2:
2032 if (state != GL_NONE)
2034 if (!gl_state.cullfaceenable)
2036 gl_state.cullfaceenable = true;
2037 qglEnable(GL_CULL_FACE);CHECKGLERROR
2039 if (gl_state.cullface != state)
2041 gl_state.cullface = state;
2042 qglCullFace(gl_state.cullface);CHECKGLERROR
2047 if (gl_state.cullfaceenable)
2049 gl_state.cullfaceenable = false;
2050 qglDisable(GL_CULL_FACE);CHECKGLERROR
2054 case RENDERPATH_D3D9:
2056 if (gl_state.cullface != state)
2058 gl_state.cullface = state;
2059 switch(gl_state.cullface)
2062 gl_state.cullfaceenable = false;
2063 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2066 gl_state.cullfaceenable = true;
2067 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2070 gl_state.cullfaceenable = true;
2071 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2077 case RENDERPATH_D3D10:
2078 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2080 case RENDERPATH_D3D11:
2081 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2083 case RENDERPATH_SOFT:
2084 if (gl_state.cullface != state)
2086 gl_state.cullface = state;
2087 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2088 DPSOFTRAST_CullFace(gl_state.cullface);
2094 void GL_AlphaTest(int state)
2096 if (gl_state.alphatest != state)
2098 gl_state.alphatest = state;
2099 switch(vid.renderpath)
2101 case RENDERPATH_GL11:
2102 case RENDERPATH_GL13:
2103 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2105 if (gl_state.alphatest)
2107 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2111 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2114 case RENDERPATH_D3D9:
2116 // IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2119 case RENDERPATH_D3D10:
2121 case RENDERPATH_D3D11:
2123 case RENDERPATH_SOFT:
2124 // DPSOFTRAST_AlphaTest(gl_state.alphatest);
2126 case RENDERPATH_GL20:
2127 case RENDERPATH_GLES2:
2133 void GL_ColorMask(int r, int g, int b, int a)
2135 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2136 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2137 if (gl_state.colormask != state)
2139 gl_state.colormask = state;
2140 switch(vid.renderpath)
2142 case RENDERPATH_GL11:
2143 case RENDERPATH_GL13:
2144 case RENDERPATH_GL20:
2145 case RENDERPATH_GLES2:
2147 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2149 case RENDERPATH_D3D9:
2151 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2154 case RENDERPATH_D3D10:
2155 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2157 case RENDERPATH_D3D11:
2158 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2160 case RENDERPATH_SOFT:
2161 DPSOFTRAST_ColorMask(r, g, b, a);
2167 void GL_Color(float cr, float cg, float cb, float ca)
2169 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)
2171 gl_state.color4f[0] = cr;
2172 gl_state.color4f[1] = cg;
2173 gl_state.color4f[2] = cb;
2174 gl_state.color4f[3] = ca;
2175 switch(vid.renderpath)
2177 case RENDERPATH_GL11:
2178 case RENDERPATH_GL13:
2180 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2183 case RENDERPATH_D3D9:
2184 case RENDERPATH_D3D10:
2185 case RENDERPATH_D3D11:
2186 // no equivalent in D3D
2188 case RENDERPATH_SOFT:
2189 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2191 case RENDERPATH_GL20:
2192 case RENDERPATH_GLES2:
2193 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2199 void GL_Scissor (int x, int y, int width, int height)
2201 switch(vid.renderpath)
2203 case RENDERPATH_GL11:
2204 case RENDERPATH_GL13:
2205 case RENDERPATH_GL20:
2206 case RENDERPATH_GLES2:
2208 qglScissor(x, y,width,height);
2211 case RENDERPATH_D3D9:
2217 d3drect.right = x + width;
2218 d3drect.bottom = y + height;
2219 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2223 case RENDERPATH_D3D10:
2224 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2226 case RENDERPATH_D3D11:
2227 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2229 case RENDERPATH_SOFT:
2230 DPSOFTRAST_Scissor(x, y, width, height);
2235 void GL_ScissorTest(int state)
2237 if (gl_state.scissortest != state)
2239 gl_state.scissortest = state;
2240 switch(vid.renderpath)
2242 case RENDERPATH_GL11:
2243 case RENDERPATH_GL13:
2244 case RENDERPATH_GL20:
2245 case RENDERPATH_GLES2:
2247 if(gl_state.scissortest)
2248 qglEnable(GL_SCISSOR_TEST);
2250 qglDisable(GL_SCISSOR_TEST);
2253 case RENDERPATH_D3D9:
2255 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2258 case RENDERPATH_D3D10:
2259 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2261 case RENDERPATH_D3D11:
2262 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2264 case RENDERPATH_SOFT:
2265 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2271 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2273 static const float blackcolor[4] = {0, 0, 0, 0};
2274 // prevent warnings when trying to clear a buffer that does not exist
2276 colorvalue = blackcolor;
2279 mask &= ~GL_STENCIL_BUFFER_BIT;
2282 switch(vid.renderpath)
2284 case RENDERPATH_GL11:
2285 case RENDERPATH_GL13:
2286 case RENDERPATH_GL20:
2287 case RENDERPATH_GLES2:
2289 if (mask & GL_COLOR_BUFFER_BIT)
2291 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2293 if (mask & GL_DEPTH_BUFFER_BIT)
2295 qglClearDepth(depthvalue);CHECKGLERROR
2297 if (mask & GL_STENCIL_BUFFER_BIT)
2299 qglClearStencil(stencilvalue);CHECKGLERROR
2301 qglClear(mask);CHECKGLERROR
2303 case RENDERPATH_D3D9:
2305 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);
2308 case RENDERPATH_D3D10:
2309 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2311 case RENDERPATH_D3D11:
2312 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2314 case RENDERPATH_SOFT:
2315 if (mask & GL_COLOR_BUFFER_BIT)
2316 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2317 if (mask & GL_DEPTH_BUFFER_BIT)
2318 DPSOFTRAST_ClearDepth(depthvalue);
2323 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2325 switch(vid.renderpath)
2327 case RENDERPATH_GL11:
2328 case RENDERPATH_GL13:
2329 case RENDERPATH_GL20:
2330 case RENDERPATH_GLES2:
2332 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2334 case RENDERPATH_D3D9:
2337 // LordHavoc: we can't directly download the backbuffer because it may be
2338 // multisampled, and it may not be lockable, so we blit it to a lockable
2339 // surface of the same dimensions (but without multisample) to resolve the
2340 // multisample buffer to a normal image, and then lock that...
2341 IDirect3DSurface9 *stretchsurface = NULL;
2342 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2344 D3DLOCKED_RECT lockedrect;
2345 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2347 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2350 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2351 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2352 memcpy(outpixels + line * width * 4, row, width * 4);
2353 IDirect3DSurface9_UnlockRect(stretchsurface);
2356 IDirect3DSurface9_Release(stretchsurface);
2359 //IDirect3DSurface9 *syssurface = NULL;
2360 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2361 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2362 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2363 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2364 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2365 //IDirect3DSurface9_UnlockRect(syssurface);
2366 //IDirect3DSurface9_Release(syssurface);
2370 case RENDERPATH_D3D10:
2371 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2373 case RENDERPATH_D3D11:
2374 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2376 case RENDERPATH_SOFT:
2377 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2382 // called at beginning of frame
2383 void R_Mesh_Start(void)
2386 R_Mesh_ResetRenderTargets();
2388 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2390 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2391 Cvar_SetValueQuick(&gl_paranoid, 1);
2395 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2399 char compilelog[MAX_INPUTLINE];
2400 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2403 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2404 qglCompileShader(shaderobject);CHECKGLERROR
2405 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2406 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2407 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2409 int i, j, pretextlines = 0;
2410 for (i = 0;i < numstrings - 1;i++)
2411 for (j = 0;strings[i][j];j++)
2412 if (strings[i][j] == '\n')
2414 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2416 if (!shadercompiled)
2418 qglDeleteShader(shaderobject);CHECKGLERROR
2421 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2422 qglDeleteShader(shaderobject);CHECKGLERROR
2426 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)
2428 GLint programlinked;
2429 GLuint programobject = 0;
2430 char linklog[MAX_INPUTLINE];
2433 programobject = qglCreateProgram();CHECKGLERROR
2437 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2438 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2439 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2440 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2441 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2442 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2443 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2444 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2445 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2446 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2447 if(vid.support.gl20shaders130)
2448 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2450 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2453 #ifdef GL_GEOMETRY_SHADER
2454 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2458 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2461 qglLinkProgram(programobject);CHECKGLERROR
2462 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2463 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2466 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2467 Con_DPrintf("program link log:\n%s\n", linklog);
2468 // software vertex shader is ok but software fragment shader is WAY
2469 // too slow, fail program if so.
2470 // NOTE: this string might be ATI specific, but that's ok because the
2471 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2472 // software fragment shader due to low instruction and dependent
2474 if (strstr(linklog, "fragment shader will run in software"))
2475 programlinked = false;
2479 return programobject;
2481 qglDeleteProgram(programobject);CHECKGLERROR
2485 void GL_Backend_FreeProgram(unsigned int prog)
2488 qglDeleteProgram(prog);
2492 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2497 for (i = 0;i < count;i++)
2498 *out++ = *in++ + offset;
2501 memcpy(out, in, sizeof(*out) * count);
2504 // renders triangles using vertices from the active arrays
2505 int paranoidblah = 0;
2506 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)
2508 unsigned int numelements = numtriangles * 3;
2510 size_t bufferoffset3i;
2512 size_t bufferoffset3s;
2513 if (numvertices < 3 || numtriangles < 1)
2515 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2516 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);
2519 if (!gl_mesh_prefer_short_elements.integer)
2523 if (element3i_indexbuffer)
2524 element3i_indexbuffer = NULL;
2526 // adjust the pointers for firsttriangle
2528 element3i += firsttriangle * 3;
2529 if (element3i_indexbuffer)
2530 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2532 element3s += firsttriangle * 3;
2533 if (element3s_indexbuffer)
2534 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2535 switch(vid.renderpath)
2537 case RENDERPATH_GL11:
2538 case RENDERPATH_GL13:
2539 case RENDERPATH_GL20:
2540 case RENDERPATH_GLES2:
2541 // check if the user specified to ignore static index buffers
2542 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2544 element3i_indexbuffer = NULL;
2545 element3s_indexbuffer = NULL;
2548 case RENDERPATH_D3D9:
2549 case RENDERPATH_D3D10:
2550 case RENDERPATH_D3D11:
2552 case RENDERPATH_SOFT:
2555 // upload a dynamic index buffer if needed
2558 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2560 if (gl_state.draw_dynamicindexbuffer)
2561 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2563 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2564 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2565 element3s_bufferoffset = 0;
2570 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2572 if (gl_state.draw_dynamicindexbuffer)
2573 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2575 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2576 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2577 element3i_bufferoffset = 0;
2580 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2581 bufferoffset3i = element3i_bufferoffset;
2582 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2583 bufferoffset3s = element3s_bufferoffset;
2584 r_refdef.stats.draws++;
2585 r_refdef.stats.draws_vertices += numvertices;
2586 r_refdef.stats.draws_elements += numelements;
2587 if (gl_paranoid.integer)
2590 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2592 unsigned int j, size;
2594 // note: there's no validation done here on buffer objects because it
2595 // is somewhat difficult to get at the data, and gl_paranoid can be
2596 // used without buffer objects if the need arises
2597 // (the data could be gotten using glMapBuffer but it would be very
2598 // slow due to uncachable video memory reads)
2599 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2600 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2602 if (gl_state.pointer_vertex_pointer)
2603 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2605 if (gl_state.pointer_color_enabled)
2607 if (!qglIsEnabled(GL_COLOR_ARRAY))
2608 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2610 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2611 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2614 for (i = 0;i < vid.texarrayunits;i++)
2616 if (gl_state.units[i].arrayenabled)
2618 GL_ClientActiveTexture(i);
2619 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2620 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2622 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2623 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++)
2630 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2632 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2634 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2641 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2643 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2645 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2651 if (r_render.integer || r_refdef.draw2dstage)
2653 switch(vid.renderpath)
2655 case RENDERPATH_GL11:
2656 case RENDERPATH_GL13:
2657 case RENDERPATH_GL20:
2659 if (gl_mesh_testmanualfeeding.integer)
2661 unsigned int i, j, element;
2663 qglBegin(GL_TRIANGLES);
2664 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2667 element = element3i[i];
2669 element = element3s[i];
2671 element = firstvertex + i;
2672 for (j = 0;j < vid.texarrayunits;j++)
2674 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2676 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2678 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2679 if (vid.texarrayunits > 1)
2681 if (gl_state.units[j].pointer_texcoord_components == 4)
2682 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2683 else if (gl_state.units[j].pointer_texcoord_components == 3)
2684 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2685 else if (gl_state.units[j].pointer_texcoord_components == 2)
2686 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2688 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2692 if (gl_state.units[j].pointer_texcoord_components == 4)
2693 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2694 else if (gl_state.units[j].pointer_texcoord_components == 3)
2695 qglTexCoord3f(p[0], p[1], p[2]);
2696 else if (gl_state.units[j].pointer_texcoord_components == 2)
2697 qglTexCoord2f(p[0], p[1]);
2699 qglTexCoord1f(p[0]);
2702 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2704 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2705 if (vid.texarrayunits > 1)
2707 if (gl_state.units[j].pointer_texcoord_components == 4)
2708 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2709 else if (gl_state.units[j].pointer_texcoord_components == 3)
2710 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2711 else if (gl_state.units[j].pointer_texcoord_components == 2)
2712 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2713 else if (gl_state.units[j].pointer_texcoord_components == 1)
2714 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2718 if (gl_state.units[j].pointer_texcoord_components == 4)
2719 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2720 else if (gl_state.units[j].pointer_texcoord_components == 3)
2721 qglTexCoord3f(s[0], s[1], s[2]);
2722 else if (gl_state.units[j].pointer_texcoord_components == 2)
2723 qglTexCoord2f(s[0], s[1]);
2724 else if (gl_state.units[j].pointer_texcoord_components == 1)
2725 qglTexCoord1f(s[0]);
2728 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2730 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2731 if (vid.texarrayunits > 1)
2733 if (gl_state.units[j].pointer_texcoord_components == 4)
2734 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2735 else if (gl_state.units[j].pointer_texcoord_components == 3)
2736 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2737 else if (gl_state.units[j].pointer_texcoord_components == 2)
2738 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2739 else if (gl_state.units[j].pointer_texcoord_components == 1)
2740 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2744 if (gl_state.units[j].pointer_texcoord_components == 4)
2745 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2746 else if (gl_state.units[j].pointer_texcoord_components == 3)
2747 qglTexCoord3f(sb[0], sb[1], sb[2]);
2748 else if (gl_state.units[j].pointer_texcoord_components == 2)
2749 qglTexCoord2f(sb[0], sb[1]);
2750 else if (gl_state.units[j].pointer_texcoord_components == 1)
2751 qglTexCoord1f(sb[0]);
2756 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2758 if (gl_state.pointer_color_gltype == GL_FLOAT)
2760 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2761 qglColor4f(p[0], p[1], p[2], p[3]);
2763 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2765 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2766 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2769 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2771 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2772 if (gl_state.pointer_vertex_components == 4)
2773 qglVertex4f(p[0], p[1], p[2], p[3]);
2774 else if (gl_state.pointer_vertex_components == 3)
2775 qglVertex3f(p[0], p[1], p[2]);
2777 qglVertex2f(p[0], p[1]);
2783 else if (bufferobject3s)
2785 GL_BindEBO(bufferobject3s);
2786 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2788 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2793 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2797 else if (bufferobject3i)
2799 GL_BindEBO(bufferobject3i);
2800 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2802 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2807 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2814 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2816 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2821 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2828 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2830 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2835 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2841 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2845 case RENDERPATH_D3D9:
2847 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2849 if (element3s_indexbuffer)
2851 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2852 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2854 else if (element3i_indexbuffer)
2856 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2857 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2860 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2865 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2867 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2869 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2873 case RENDERPATH_D3D10:
2874 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2876 case RENDERPATH_D3D11:
2877 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2879 case RENDERPATH_SOFT:
2880 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2882 case RENDERPATH_GLES2:
2883 // GLES does not have glDrawRangeElements, and generally
2884 // underperforms with index buffers, so this code path is
2885 // relatively straightforward...
2887 if (gl_paranoid.integer)
2889 int r, prog, enabled, i;
2890 GLsizei attriblength;
2893 GLchar attribname[1024];
2894 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2895 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2896 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2897 #ifndef GL_CURRENT_PROGRAM
2898 #define GL_CURRENT_PROGRAM 0x8B8D
2900 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2901 if (r < 0 || r > 10000)
2902 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2904 for (i = 0;i < 8;i++)
2906 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2909 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2910 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);
2916 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2921 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2926 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2934 // restores backend state, used when done with 3D rendering
2935 void R_Mesh_Finish(void)
2937 R_Mesh_ResetRenderTargets();
2940 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2942 r_meshbuffer_t *buffer;
2943 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2945 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2946 memset(buffer, 0, sizeof(*buffer));
2947 buffer->bufferobject = 0;
2948 buffer->devicebuffer = NULL;
2950 buffer->isindexbuffer = isindexbuffer;
2951 buffer->isdynamic = isdynamic;
2952 buffer->isindex16 = isindex16;
2953 strlcpy(buffer->name, name, sizeof(buffer->name));
2954 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2958 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
2962 if (buffer->isindexbuffer)
2964 r_refdef.stats.indexbufferuploadcount++;
2965 r_refdef.stats.indexbufferuploadsize += size;
2969 r_refdef.stats.vertexbufferuploadcount++;
2970 r_refdef.stats.vertexbufferuploadsize += size;
2972 switch(vid.renderpath)
2974 case RENDERPATH_GL11:
2975 case RENDERPATH_GL13:
2976 case RENDERPATH_GL20:
2977 case RENDERPATH_GLES2:
2978 if (!buffer->bufferobject)
2979 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
2980 if (buffer->isindexbuffer)
2981 GL_BindEBO(buffer->bufferobject);
2983 GL_BindVBO(buffer->bufferobject);
2984 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
2986 case RENDERPATH_D3D9:
2990 void *datapointer = NULL;
2991 if (buffer->isindexbuffer)
2993 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
2994 if (size > buffer->size || !buffer->devicebuffer)
2996 if (buffer->devicebuffer)
2997 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
2998 buffer->devicebuffer = NULL;
2999 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)))
3000 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);
3001 buffer->devicebuffer = (void *)d3d9indexbuffer;
3002 buffer->size = size;
3004 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3007 memcpy(datapointer, data, size);
3009 memset(datapointer, 0, size);
3010 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3015 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3016 if (size > buffer->size || !buffer->devicebuffer)
3018 if (buffer->devicebuffer)
3019 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3020 buffer->devicebuffer = NULL;
3021 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3022 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);
3023 buffer->devicebuffer = (void *)d3d9vertexbuffer;
3024 buffer->size = size;
3026 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3029 memcpy(datapointer, data, size);
3031 memset(datapointer, 0, size);
3032 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3038 case RENDERPATH_D3D10:
3039 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3041 case RENDERPATH_D3D11:
3042 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3044 case RENDERPATH_SOFT:
3049 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3053 switch(vid.renderpath)
3055 case RENDERPATH_GL11:
3056 case RENDERPATH_GL13:
3057 case RENDERPATH_GL20:
3058 case RENDERPATH_GLES2:
3059 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3061 case RENDERPATH_D3D9:
3063 if (gl_state.d3dvertexbuffer == (void *)buffer)
3064 gl_state.d3dvertexbuffer = NULL;
3065 if (buffer->devicebuffer)
3067 if (buffer->isindexbuffer)
3068 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3070 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3071 buffer->devicebuffer = NULL;
3075 case RENDERPATH_D3D10:
3076 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3078 case RENDERPATH_D3D11:
3079 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3081 case RENDERPATH_SOFT:
3084 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3087 void GL_Mesh_ListVBOs(qboolean printeach)
3090 size_t ebocount = 0, ebomemory = 0;
3091 size_t vbocount = 0, vbomemory = 0;
3092 r_meshbuffer_t *buffer;
3093 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3094 for (i = 0;i < endindex;i++)
3096 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3099 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)");}
3100 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)");}
3102 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);
3107 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3109 switch(vid.renderpath)
3111 case RENDERPATH_GL11:
3112 case RENDERPATH_GL13:
3113 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)
3115 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3116 gl_state.pointer_vertex_components = components;
3117 gl_state.pointer_vertex_gltype = gltype;
3118 gl_state.pointer_vertex_stride = stride;
3119 gl_state.pointer_vertex_pointer = pointer;
3120 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3121 gl_state.pointer_vertex_offset = bufferoffset;
3123 GL_BindVBO(bufferobject);
3124 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3127 case RENDERPATH_GL20:
3128 case RENDERPATH_GLES2:
3129 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)
3131 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3132 gl_state.pointer_vertex_components = components;
3133 gl_state.pointer_vertex_gltype = gltype;
3134 gl_state.pointer_vertex_stride = stride;
3135 gl_state.pointer_vertex_pointer = pointer;
3136 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3137 gl_state.pointer_vertex_offset = bufferoffset;
3139 GL_BindVBO(bufferobject);
3140 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3143 case RENDERPATH_D3D9:
3144 case RENDERPATH_D3D10:
3145 case RENDERPATH_D3D11:
3146 case RENDERPATH_SOFT:
3151 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3153 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3154 // the pointer only.
3155 switch(vid.renderpath)
3157 case RENDERPATH_GL11:
3158 case RENDERPATH_GL13:
3162 // caller wants color array enabled
3163 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3164 if (!gl_state.pointer_color_enabled)
3166 gl_state.pointer_color_enabled = true;
3168 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3170 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)
3172 gl_state.pointer_color_components = components;
3173 gl_state.pointer_color_gltype = gltype;
3174 gl_state.pointer_color_stride = stride;
3175 gl_state.pointer_color_pointer = pointer;
3176 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3177 gl_state.pointer_color_offset = bufferoffset;
3179 GL_BindVBO(bufferobject);
3180 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3185 // caller wants color array disabled
3186 if (gl_state.pointer_color_enabled)
3188 gl_state.pointer_color_enabled = false;
3190 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3191 // when color array is on the glColor gets trashed, set it again
3192 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3196 case RENDERPATH_GL20:
3197 case RENDERPATH_GLES2:
3201 // caller wants color array enabled
3202 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3203 if (!gl_state.pointer_color_enabled)
3205 gl_state.pointer_color_enabled = true;
3207 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3209 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)
3211 gl_state.pointer_color_components = components;
3212 gl_state.pointer_color_gltype = gltype;
3213 gl_state.pointer_color_stride = stride;
3214 gl_state.pointer_color_pointer = pointer;
3215 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3216 gl_state.pointer_color_offset = bufferoffset;
3218 GL_BindVBO(bufferobject);
3219 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3224 // caller wants color array disabled
3225 if (gl_state.pointer_color_enabled)
3227 gl_state.pointer_color_enabled = false;
3229 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3230 // when color array is on the glColor gets trashed, set it again
3231 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3235 case RENDERPATH_D3D9:
3236 case RENDERPATH_D3D10:
3237 case RENDERPATH_D3D11:
3238 case RENDERPATH_SOFT:
3243 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)
3245 gltextureunit_t *unit = gl_state.units + unitnum;
3246 // update array settings
3247 // note: there is no need to check bufferobject here because all cases
3248 // that involve a valid bufferobject also supply a texcoord array
3249 switch(vid.renderpath)
3251 case RENDERPATH_GL11:
3252 case RENDERPATH_GL13:
3256 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3257 // texture array unit is enabled, enable the array
3258 if (!unit->arrayenabled)
3260 unit->arrayenabled = true;
3261 GL_ClientActiveTexture(unitnum);
3262 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3265 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)
3267 unit->pointer_texcoord_components = components;
3268 unit->pointer_texcoord_gltype = gltype;
3269 unit->pointer_texcoord_stride = stride;
3270 unit->pointer_texcoord_pointer = pointer;
3271 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3272 unit->pointer_texcoord_offset = bufferoffset;
3273 GL_ClientActiveTexture(unitnum);
3274 GL_BindVBO(bufferobject);
3275 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3280 // texture array unit is disabled, disable the array
3281 if (unit->arrayenabled)
3283 unit->arrayenabled = false;
3284 GL_ClientActiveTexture(unitnum);
3285 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3289 case RENDERPATH_GL20:
3290 case RENDERPATH_GLES2:
3294 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3295 // texture array unit is enabled, enable the array
3296 if (!unit->arrayenabled)
3298 unit->arrayenabled = true;
3299 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3302 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)
3304 unit->pointer_texcoord_components = components;
3305 unit->pointer_texcoord_gltype = gltype;
3306 unit->pointer_texcoord_stride = stride;
3307 unit->pointer_texcoord_pointer = pointer;
3308 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3309 unit->pointer_texcoord_offset = bufferoffset;
3310 GL_BindVBO(bufferobject);
3311 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3316 // texture array unit is disabled, disable the array
3317 if (unit->arrayenabled)
3319 unit->arrayenabled = false;
3320 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3324 case RENDERPATH_D3D9:
3325 case RENDERPATH_D3D10:
3326 case RENDERPATH_D3D11:
3327 case RENDERPATH_SOFT:
3332 int R_Mesh_TexBound(unsigned int unitnum, int id)
3334 gltextureunit_t *unit = gl_state.units + unitnum;
3335 if (unitnum >= vid.teximageunits)
3337 if (id == GL_TEXTURE_2D)
3339 if (id == GL_TEXTURE_3D)
3341 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3342 return unit->tcubemap;
3346 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3348 switch(vid.renderpath)
3350 case RENDERPATH_GL11:
3351 case RENDERPATH_GL13:
3352 case RENDERPATH_GL20:
3353 case RENDERPATH_GLES2:
3354 R_Mesh_TexBind(0, tex);
3355 GL_ActiveTexture(0);CHECKGLERROR
3356 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3358 case RENDERPATH_D3D9:
3361 IDirect3DSurface9 *currentsurface = NULL;
3362 IDirect3DSurface9 *texturesurface = NULL;
3365 sourcerect.left = sx;
3366 sourcerect.top = sy;
3367 sourcerect.right = sx + width;
3368 sourcerect.bottom = sy + height;
3371 destrect.right = tx + width;
3372 destrect.bottom = ty + height;
3373 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3375 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3377 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3378 IDirect3DSurface9_Release(currentsurface);
3380 IDirect3DSurface9_Release(texturesurface);
3385 case RENDERPATH_D3D10:
3386 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3388 case RENDERPATH_D3D11:
3389 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3391 case RENDERPATH_SOFT:
3392 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3398 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};
3401 void R_Mesh_ClearBindingsForTexture(int texnum)
3403 gltextureunit_t *unit;
3404 unsigned int unitnum;
3405 // 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)
3406 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3408 unit = gl_state.units + unitnum;
3409 if (unit->t2d == texnum)
3411 if (unit->t3d == texnum)
3413 if (unit->tcubemap == texnum)
3414 unit->tcubemap = -1;
3418 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3420 gltextureunit_t *unit = gl_state.units + unitnum;
3421 int tex2d, tex3d, texcubemap, texnum;
3422 if (unitnum >= vid.teximageunits)
3424 // if (unit->texture == tex)
3426 switch(vid.renderpath)
3428 case RENDERPATH_GL20:
3429 case RENDERPATH_GLES2:
3432 tex = r_texture_white;
3433 // not initialized enough yet...
3437 unit->texture = tex;
3438 texnum = R_GetTexture(tex);
3439 switch(tex->gltexturetypeenum)
3441 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3442 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3443 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;
3446 case RENDERPATH_GL13:
3447 case RENDERPATH_GL11:
3448 unit->texture = tex;
3454 texnum = R_GetTexture(tex);
3455 switch(tex->gltexturetypeenum)
3463 case GL_TEXTURE_CUBE_MAP_ARB:
3464 texcubemap = texnum;
3468 // update 2d texture binding
3469 if (unit->t2d != tex2d)
3471 GL_ActiveTexture(unitnum);
3476 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3483 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3487 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3489 // update 3d texture binding
3490 if (unit->t3d != tex3d)
3492 GL_ActiveTexture(unitnum);
3497 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3504 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3508 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3510 // update cubemap texture binding
3511 if (unit->tcubemap != texcubemap)
3513 GL_ActiveTexture(unitnum);
3516 if (unit->tcubemap == 0)
3518 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3525 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3528 unit->tcubemap = texcubemap;
3529 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3532 case RENDERPATH_D3D9:
3535 extern cvar_t gl_texture_anisotropy;
3538 tex = r_texture_white;
3539 // not initialized enough yet...
3543 // upload texture if needed
3545 if (unit->texture == tex)
3547 unit->texture = tex;
3548 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3549 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3550 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3551 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3552 if (tex->d3daddressw)
3553 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3554 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3555 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3556 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3557 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3558 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3559 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3563 case RENDERPATH_D3D10:
3564 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3566 case RENDERPATH_D3D11:
3567 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3569 case RENDERPATH_SOFT:
3572 tex = r_texture_white;
3573 // not initialized enough yet...
3577 texnum = R_GetTexture(tex);
3578 if (unit->texture == tex)
3580 unit->texture = tex;
3581 DPSOFTRAST_SetTexture(unitnum, texnum);
3586 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3588 gltextureunit_t *unit = gl_state.units + unitnum;
3589 switch(vid.renderpath)
3591 case RENDERPATH_GL11:
3592 case RENDERPATH_GL13:
3593 case RENDERPATH_GL20:
3594 case RENDERPATH_GLES2:
3595 if (matrix && matrix->m[3][3])
3597 // texmatrix specified, check if it is different
3598 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3601 unit->texmatrixenabled = true;
3602 unit->matrix = *matrix;
3604 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3605 GL_ActiveTexture(unitnum);
3606 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3607 qglLoadMatrixf(glmatrix);CHECKGLERROR
3608 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3613 // no texmatrix specified, revert to identity
3614 if (unit->texmatrixenabled)
3616 unit->texmatrixenabled = false;
3617 unit->matrix = identitymatrix;
3619 GL_ActiveTexture(unitnum);
3620 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3621 qglLoadIdentity();CHECKGLERROR
3622 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3626 case RENDERPATH_D3D9:
3627 case RENDERPATH_D3D10:
3628 case RENDERPATH_D3D11:
3630 case RENDERPATH_SOFT:
3635 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3637 gltextureunit_t *unit = gl_state.units + unitnum;
3639 switch(vid.renderpath)
3641 case RENDERPATH_GL20:
3642 case RENDERPATH_GLES2:
3645 case RENDERPATH_GL13:
3646 // GL_ARB_texture_env_combine
3648 combinergb = GL_MODULATE;
3650 combinealpha = GL_MODULATE;
3655 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3657 if (combinergb == GL_DECAL)
3658 combinergb = GL_INTERPOLATE_ARB;
3659 if (unit->combine != GL_COMBINE_ARB)
3661 unit->combine = GL_COMBINE_ARB;
3662 GL_ActiveTexture(unitnum);
3663 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3664 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3666 if (unit->combinergb != combinergb)
3668 unit->combinergb = combinergb;
3669 GL_ActiveTexture(unitnum);
3670 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3672 if (unit->combinealpha != combinealpha)
3674 unit->combinealpha = combinealpha;
3675 GL_ActiveTexture(unitnum);
3676 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3678 if (unit->rgbscale != rgbscale)
3680 unit->rgbscale = rgbscale;
3681 GL_ActiveTexture(unitnum);
3682 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3684 if (unit->alphascale != alphascale)
3686 unit->alphascale = alphascale;
3687 GL_ActiveTexture(unitnum);
3688 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3693 if (unit->combine != combinergb)
3695 unit->combine = combinergb;
3696 GL_ActiveTexture(unitnum);
3697 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3701 case RENDERPATH_GL11:
3704 combinergb = GL_MODULATE;
3705 if (unit->combine != combinergb)
3707 unit->combine = combinergb;
3708 GL_ActiveTexture(unitnum);
3709 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3712 case RENDERPATH_D3D9:
3713 case RENDERPATH_D3D10:
3714 case RENDERPATH_D3D11:
3716 case RENDERPATH_SOFT:
3721 void R_Mesh_ResetTextureState(void)
3723 unsigned int unitnum;
3727 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3728 R_Mesh_TexBind(unitnum, NULL);
3729 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3730 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3731 switch(vid.renderpath)
3733 case RENDERPATH_GL20:
3734 case RENDERPATH_GLES2:
3735 case RENDERPATH_D3D9:
3736 case RENDERPATH_D3D10:
3737 case RENDERPATH_D3D11:
3738 case RENDERPATH_SOFT:
3740 case RENDERPATH_GL13:
3741 case RENDERPATH_GL11:
3742 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3744 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3745 R_Mesh_TexMatrix(unitnum, NULL);
3754 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3755 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3756 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3758 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3760 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3764 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3766 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3767 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3768 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3772 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3774 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3775 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3776 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3777 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3778 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3779 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3780 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3784 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3785 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3786 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3789 static void R_Mesh_InitVertexDeclarations(void)
3792 r_vertex3f_d3d9decl = NULL;
3793 r_vertexgeneric_d3d9decl = NULL;
3794 r_vertexmesh_d3d9decl = NULL;
3795 switch(vid.renderpath)
3797 case RENDERPATH_GL20:
3798 case RENDERPATH_GL13:
3799 case RENDERPATH_GL11:
3800 case RENDERPATH_GLES2:
3802 case RENDERPATH_D3D9:
3803 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3804 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3805 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3807 case RENDERPATH_D3D10:
3808 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3810 case RENDERPATH_D3D11:
3811 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3813 case RENDERPATH_SOFT:
3819 static void R_Mesh_DestroyVertexDeclarations(void)
3822 if (r_vertex3f_d3d9decl)
3823 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3824 r_vertex3f_d3d9decl = NULL;
3825 if (r_vertexgeneric_d3d9decl)
3826 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3827 r_vertexgeneric_d3d9decl = NULL;
3828 if (r_vertexmesh_d3d9decl)
3829 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3830 r_vertexmesh_d3d9decl = NULL;
3834 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3836 // upload temporary vertexbuffer for this rendering
3837 if (!gl_state.usevbo_staticvertex)
3838 vertexbuffer = NULL;
3839 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3841 if (gl_state.preparevertices_dynamicvertexbuffer)
3842 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3844 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3845 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3847 switch(vid.renderpath)
3849 case RENDERPATH_GL20:
3850 case RENDERPATH_GLES2:
3853 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3854 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3855 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3856 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3857 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3858 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3859 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3863 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3864 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3865 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3866 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3867 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3868 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3869 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3872 case RENDERPATH_GL13:
3875 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3876 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3877 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3878 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3882 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3883 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3884 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3885 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3888 case RENDERPATH_GL11:
3891 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3892 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3893 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3897 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3898 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3899 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3902 case RENDERPATH_D3D9:
3904 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3906 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3908 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3909 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3910 gl_state.d3dvertexdata = (void *)vertex3f;
3911 gl_state.d3dvertexsize = sizeof(float[3]);
3914 case RENDERPATH_D3D10:
3915 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3917 case RENDERPATH_D3D11:
3918 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3920 case RENDERPATH_SOFT:
3921 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3922 DPSOFTRAST_SetColorPointer(NULL, 0);
3923 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3924 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3925 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3926 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3927 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3934 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3937 size = sizeof(r_vertexgeneric_t) * numvertices;
3938 if (gl_state.preparevertices_tempdatamaxsize < size)
3940 gl_state.preparevertices_tempdatamaxsize = size;
3941 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3943 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3944 gl_state.preparevertices_numvertices = numvertices;
3945 return gl_state.preparevertices_vertexgeneric;
3948 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
3950 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
3951 gl_state.preparevertices_vertexgeneric = NULL;
3952 gl_state.preparevertices_numvertices = 0;
3956 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
3959 r_vertexgeneric_t *vertex;
3960 switch(vid.renderpath)
3962 case RENDERPATH_GL20:
3963 case RENDERPATH_GLES2:
3964 if (!vid.useinterleavedarrays)
3966 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3967 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3968 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3969 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3970 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3971 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3972 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3976 case RENDERPATH_GL13:
3977 case RENDERPATH_GL11:
3978 if (!vid.useinterleavedarrays)
3980 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3981 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3982 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3983 if (vid.texunits >= 2)
3984 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3985 if (vid.texunits >= 3)
3986 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3990 case RENDERPATH_D3D9:
3991 case RENDERPATH_D3D10:
3992 case RENDERPATH_D3D11:
3994 case RENDERPATH_SOFT:
3995 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3996 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
3997 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
3998 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3999 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4000 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4001 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4005 // no quick path for this case, convert to vertex structs
4006 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4007 for (i = 0;i < numvertices;i++)
4008 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4011 for (i = 0;i < numvertices;i++)
4012 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4016 for (i = 0;i < numvertices;i++)
4017 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4020 for (i = 0;i < numvertices;i++)
4021 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4022 R_Mesh_PrepareVertices_Generic_Unlock();
4023 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4026 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4028 // upload temporary vertexbuffer for this rendering
4029 if (!gl_state.usevbo_staticvertex)
4030 vertexbuffer = NULL;
4031 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4033 if (gl_state.preparevertices_dynamicvertexbuffer)
4034 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4036 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4037 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4039 switch(vid.renderpath)
4041 case RENDERPATH_GL20:
4042 case RENDERPATH_GLES2:
4045 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4046 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4047 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4048 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4049 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4050 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4051 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4055 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4056 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4057 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4058 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4059 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4060 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4061 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4064 case RENDERPATH_GL13:
4067 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4068 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4069 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4070 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4074 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4075 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4076 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4077 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4080 case RENDERPATH_GL11:
4083 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4084 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4085 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4089 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4090 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4091 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4094 case RENDERPATH_D3D9:
4096 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4098 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4100 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4101 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4102 gl_state.d3dvertexdata = (void *)vertex;
4103 gl_state.d3dvertexsize = sizeof(*vertex);
4106 case RENDERPATH_D3D10:
4107 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4109 case RENDERPATH_D3D11:
4110 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4112 case RENDERPATH_SOFT:
4113 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4114 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4115 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4116 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4117 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4118 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4119 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4126 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4129 size = sizeof(r_vertexmesh_t) * numvertices;
4130 if (gl_state.preparevertices_tempdatamaxsize < size)
4132 gl_state.preparevertices_tempdatamaxsize = size;
4133 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4135 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4136 gl_state.preparevertices_numvertices = numvertices;
4137 return gl_state.preparevertices_vertexmesh;
4140 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4142 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4143 gl_state.preparevertices_vertexmesh = NULL;
4144 gl_state.preparevertices_numvertices = 0;
4148 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)
4151 r_vertexmesh_t *vertex;
4152 switch(vid.renderpath)
4154 case RENDERPATH_GL20:
4155 case RENDERPATH_GLES2:
4156 if (!vid.useinterleavedarrays)
4158 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4159 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4160 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4161 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4162 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4163 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4164 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4168 case RENDERPATH_GL13:
4169 case RENDERPATH_GL11:
4170 if (!vid.useinterleavedarrays)
4172 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4173 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4174 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4175 if (vid.texunits >= 2)
4176 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4177 if (vid.texunits >= 3)
4178 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4182 case RENDERPATH_D3D9:
4183 case RENDERPATH_D3D10:
4184 case RENDERPATH_D3D11:
4186 case RENDERPATH_SOFT:
4187 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4188 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4189 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4190 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4191 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4192 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4193 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4197 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4198 for (i = 0;i < numvertices;i++)
4199 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4201 for (i = 0;i < numvertices;i++)
4202 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4204 for (i = 0;i < numvertices;i++)
4205 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4207 for (i = 0;i < numvertices;i++)
4208 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4211 for (i = 0;i < numvertices;i++)
4212 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4216 for (i = 0;i < numvertices;i++)
4217 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4219 if (texcoordtexture2f)
4220 for (i = 0;i < numvertices;i++)
4221 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4222 if (texcoordlightmap2f)
4223 for (i = 0;i < numvertices;i++)
4224 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4225 R_Mesh_PrepareVertices_Mesh_Unlock();
4226 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4229 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4231 // upload temporary vertexbuffer for this rendering
4232 if (!gl_state.usevbo_staticvertex)
4233 vertexbuffer = NULL;
4234 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4236 if (gl_state.preparevertices_dynamicvertexbuffer)
4237 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4239 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4240 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4242 switch(vid.renderpath)
4244 case RENDERPATH_GL20:
4245 case RENDERPATH_GLES2:
4248 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4249 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4250 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4251 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4252 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4253 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4254 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4258 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4259 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4260 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4261 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4262 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4263 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4264 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4267 case RENDERPATH_GL13:
4270 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4271 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4272 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4273 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4277 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4278 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4279 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4280 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4283 case RENDERPATH_GL11:
4286 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4287 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4288 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4292 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4293 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4294 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4297 case RENDERPATH_D3D9:
4299 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4301 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4303 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4304 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4305 gl_state.d3dvertexdata = (void *)vertex;
4306 gl_state.d3dvertexsize = sizeof(*vertex);
4309 case RENDERPATH_D3D10:
4310 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4312 case RENDERPATH_D3D11:
4313 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4315 case RENDERPATH_SOFT:
4316 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4317 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4318 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4319 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4320 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4321 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4322 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);