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;
140 qboolean alphatocoverage;
143 unsigned int clientunit;
144 gltextureunit_t units[MAX_TEXTUREUNITS];
148 int vertexbufferobject;
149 int elementbufferobject;
150 int framebufferobject;
151 int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
152 qboolean pointer_color_enabled;
154 int pointer_vertex_components;
155 int pointer_vertex_gltype;
156 size_t pointer_vertex_stride;
157 const void *pointer_vertex_pointer;
158 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
159 size_t pointer_vertex_offset;
161 int pointer_color_components;
162 int pointer_color_gltype;
163 size_t pointer_color_stride;
164 const void *pointer_color_pointer;
165 const r_meshbuffer_t *pointer_color_vertexbuffer;
166 size_t pointer_color_offset;
168 void *preparevertices_tempdata;
169 size_t preparevertices_tempdatamaxsize;
170 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
171 r_vertexgeneric_t *preparevertices_vertexgeneric;
172 r_vertexmesh_t *preparevertices_vertexmesh;
173 int preparevertices_numvertices;
175 r_meshbuffer_t *draw_dynamicindexbuffer;
177 qboolean usevbo_staticvertex;
178 qboolean usevbo_staticindex;
179 qboolean usevbo_dynamicvertex;
180 qboolean usevbo_dynamicindex;
182 memexpandablearray_t meshbufferarray;
187 // rtexture_t *d3drt_depthtexture;
188 // rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
189 IDirect3DSurface9 *d3drt_depthsurface;
190 IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
191 IDirect3DSurface9 *d3drt_backbufferdepthsurface;
192 IDirect3DSurface9 *d3drt_backbuffercolorsurface;
193 void *d3dvertexbuffer;
195 size_t d3dvertexsize;
200 static gl_state_t gl_state;
204 note: here's strip order for a terrain row:
211 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
213 *elements++ = i + row;
215 *elements++ = i + row + 1;
218 *elements++ = i + row + 1;
221 for (y = 0;y < rows - 1;y++)
223 for (x = 0;x < columns - 1;x++)
226 *elements++ = i + columns;
228 *elements++ = i + columns + 1;
231 *elements++ = i + columns + 1;
242 for (y = 0;y < rows - 1;y++)
244 for (x = 0;x < columns - 1;x++)
248 *elements++ = i + columns;
249 *elements++ = i + columns + 1;
250 *elements++ = i + columns;
251 *elements++ = i + columns + 1;
257 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
258 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
259 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
260 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
262 void GL_VBOStats_f(void)
264 GL_Mesh_ListVBOs(true);
267 static void GL_Backend_ResetState(void);
269 static void R_Mesh_InitVertexDeclarations(void);
270 static void R_Mesh_DestroyVertexDeclarations(void);
272 static void R_Mesh_SetUseVBO(void)
274 switch(vid.renderpath)
276 case RENDERPATH_GL11:
277 case RENDERPATH_GL13:
278 case RENDERPATH_GL20:
279 case RENDERPATH_GLES1:
280 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
281 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
282 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
283 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
285 case RENDERPATH_D3D9:
286 gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
287 gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo;
289 case RENDERPATH_D3D10:
290 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
292 case RENDERPATH_D3D11:
293 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
295 case RENDERPATH_SOFT:
296 gl_state.usevbo_staticvertex = false;
297 gl_state.usevbo_staticindex = false;
298 gl_state.usevbo_dynamicvertex = false;
299 gl_state.usevbo_dynamicindex = false;
301 case RENDERPATH_GLES2:
302 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
303 gl_state.usevbo_staticindex = false;
304 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
305 gl_state.usevbo_dynamicindex = false;
310 static void gl_backend_start(void)
312 memset(&gl_state, 0, sizeof(gl_state));
314 R_Mesh_InitVertexDeclarations();
317 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
319 Con_DPrintf("OpenGL backend started.\n");
323 GL_Backend_ResetState();
325 switch(vid.renderpath)
327 case RENDERPATH_GL11:
328 case RENDERPATH_GL13:
329 case RENDERPATH_GL20:
330 case RENDERPATH_GLES1:
331 case RENDERPATH_GLES2:
332 // fetch current fbo here (default fbo is not 0 on some GLES devices)
333 if (vid.support.ext_framebuffer_object)
334 qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
336 case RENDERPATH_D3D9:
338 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
339 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
342 case RENDERPATH_D3D10:
343 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
345 case RENDERPATH_D3D11:
346 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
348 case RENDERPATH_SOFT:
353 static void gl_backend_shutdown(void)
355 Con_DPrint("OpenGL Backend shutting down\n");
357 switch(vid.renderpath)
359 case RENDERPATH_GL11:
360 case RENDERPATH_GL13:
361 case RENDERPATH_GL20:
362 case RENDERPATH_SOFT:
363 case RENDERPATH_GLES1:
364 case RENDERPATH_GLES2:
366 case RENDERPATH_D3D9:
368 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
369 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
372 case RENDERPATH_D3D10:
373 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
375 case RENDERPATH_D3D11:
376 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
380 if (gl_state.preparevertices_tempdata)
381 Mem_Free(gl_state.preparevertices_tempdata);
382 if (gl_state.preparevertices_dynamicvertexbuffer)
383 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
385 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
387 R_Mesh_DestroyVertexDeclarations();
389 memset(&gl_state, 0, sizeof(gl_state));
392 static void gl_backend_newmap(void)
396 static void gl_backend_devicelost(void)
399 r_meshbuffer_t *buffer;
401 gl_state.d3dvertexbuffer = NULL;
403 switch(vid.renderpath)
405 case RENDERPATH_GL11:
406 case RENDERPATH_GL13:
407 case RENDERPATH_GL20:
408 case RENDERPATH_SOFT:
409 case RENDERPATH_GLES1:
410 case RENDERPATH_GLES2:
412 case RENDERPATH_D3D9:
414 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
415 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
418 case RENDERPATH_D3D10:
419 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
421 case RENDERPATH_D3D11:
422 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
425 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
426 for (i = 0;i < endindex;i++)
428 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
429 if (!buffer || !buffer->isdynamic)
431 switch(vid.renderpath)
433 case RENDERPATH_GL11:
434 case RENDERPATH_GL13:
435 case RENDERPATH_GL20:
436 case RENDERPATH_SOFT:
437 case RENDERPATH_GLES1:
438 case RENDERPATH_GLES2:
440 case RENDERPATH_D3D9:
442 if (buffer->devicebuffer)
444 if (buffer->isindexbuffer)
445 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
447 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
448 buffer->devicebuffer = NULL;
452 case RENDERPATH_D3D10:
453 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
455 case RENDERPATH_D3D11:
456 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
462 static void gl_backend_devicerestored(void)
464 switch(vid.renderpath)
466 case RENDERPATH_GL11:
467 case RENDERPATH_GL13:
468 case RENDERPATH_GL20:
469 case RENDERPATH_SOFT:
470 case RENDERPATH_GLES1:
471 case RENDERPATH_GLES2:
473 case RENDERPATH_D3D9:
475 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
476 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
479 case RENDERPATH_D3D10:
480 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
482 case RENDERPATH_D3D11:
483 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
488 void gl_backend_init(void)
492 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
494 polygonelement3s[i * 3 + 0] = 0;
495 polygonelement3s[i * 3 + 1] = i + 1;
496 polygonelement3s[i * 3 + 2] = i + 2;
498 // elements for rendering a series of quads as triangles
499 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
501 quadelement3s[i * 6 + 0] = i * 4;
502 quadelement3s[i * 6 + 1] = i * 4 + 1;
503 quadelement3s[i * 6 + 2] = i * 4 + 2;
504 quadelement3s[i * 6 + 3] = i * 4;
505 quadelement3s[i * 6 + 4] = i * 4 + 2;
506 quadelement3s[i * 6 + 5] = i * 4 + 3;
509 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
510 polygonelement3i[i] = polygonelement3s[i];
511 for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
512 quadelement3i[i] = quadelement3s[i];
514 Cvar_RegisterVariable(&r_render);
515 Cvar_RegisterVariable(&r_renderview);
516 Cvar_RegisterVariable(&r_waterwarp);
517 Cvar_RegisterVariable(&gl_polyblend);
518 Cvar_RegisterVariable(&v_flipped);
519 Cvar_RegisterVariable(&gl_dither);
520 Cvar_RegisterVariable(&gl_vbo);
521 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
522 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
523 Cvar_RegisterVariable(&gl_paranoid);
524 Cvar_RegisterVariable(&gl_printcheckerror);
526 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
527 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
528 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
530 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");
532 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
535 void GL_SetMirrorState(qboolean state);
537 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
541 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
542 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
544 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
546 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
547 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
548 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
550 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
555 switch(vid.renderpath)
557 case RENDERPATH_GL11:
558 case RENDERPATH_GL13:
559 case RENDERPATH_GL20:
560 case RENDERPATH_GLES1:
561 case RENDERPATH_GLES2:
564 case RENDERPATH_D3D9:
565 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
567 case RENDERPATH_D3D10:
568 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
570 case RENDERPATH_D3D11:
571 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
573 case RENDERPATH_SOFT:
579 static int bboxedges[12][2] =
598 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
600 int i, ix1, iy1, ix2, iy2;
601 float x1, y1, x2, y2;
612 scissor[0] = r_refdef.view.viewport.x;
613 scissor[1] = r_refdef.view.viewport.y;
614 scissor[2] = r_refdef.view.viewport.width;
615 scissor[3] = r_refdef.view.viewport.height;
617 // if view is inside the box, just say yes it's visible
618 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
621 x1 = y1 = x2 = y2 = 0;
623 // transform all corners that are infront of the nearclip plane
624 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
625 plane4f[3] = r_refdef.view.frustum[4].dist;
627 for (i = 0;i < 8;i++)
629 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
630 dist[i] = DotProduct4(corner[i], plane4f);
631 sign[i] = dist[i] > 0;
634 VectorCopy(corner[i], vertex[numvertices]);
638 // if some points are behind the nearclip, add clipped edge points to make
639 // sure that the scissor boundary is complete
640 if (numvertices > 0 && numvertices < 8)
642 // add clipped edge points
643 for (i = 0;i < 12;i++)
647 if (sign[j] != sign[k])
649 f = dist[j] / (dist[j] - dist[k]);
650 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
656 // if we have no points to check, it is behind the view plane
660 // if we have some points to transform, check what screen area is covered
661 x1 = y1 = x2 = y2 = 0;
663 //Con_Printf("%i vertices to transform...\n", numvertices);
664 for (i = 0;i < numvertices;i++)
666 VectorCopy(vertex[i], v);
667 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
668 //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]);
671 if (x1 > v2[0]) x1 = v2[0];
672 if (x2 < v2[0]) x2 = v2[0];
673 if (y1 > v2[1]) y1 = v2[1];
674 if (y2 < v2[1]) y2 = v2[1];
683 // now convert the scissor rectangle to integer screen coordinates
684 ix1 = (int)(x1 - 1.0f);
685 //iy1 = vid.height - (int)(y2 - 1.0f);
686 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
687 iy1 = (int)(y1 - 1.0f);
688 ix2 = (int)(x2 + 1.0f);
689 //iy2 = vid.height - (int)(y1 + 1.0f);
690 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
691 iy2 = (int)(y2 + 1.0f);
692 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
694 // clamp it to the screen
695 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
696 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
697 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
698 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
700 // if it is inside out, it's not visible
701 if (ix2 <= ix1 || iy2 <= iy1)
704 // the light area is visible, set up the scissor rectangle
707 scissor[2] = ix2 - ix1;
708 scissor[3] = iy2 - iy1;
710 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
711 switch(vid.renderpath)
713 case RENDERPATH_D3D9:
714 case RENDERPATH_D3D10:
715 case RENDERPATH_D3D11:
716 scissor[1] = vid.height - scissor[1] - scissor[3];
718 case RENDERPATH_GL11:
719 case RENDERPATH_GL13:
720 case RENDERPATH_GL20:
721 case RENDERPATH_SOFT:
722 case RENDERPATH_GLES1:
723 case RENDERPATH_GLES2:
731 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
735 float clipPlane[4], v3[3], v4[3];
738 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
740 VectorSet(normal, normalx, normaly, normalz);
741 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
742 VectorScale(normal, -dist, v3);
743 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
744 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
745 clipPlane[3] = -DotProduct(v4, clipPlane);
749 // testing code for comparing results
751 VectorCopy4(clipPlane, clipPlane2);
752 R_EntityMatrix(&identitymatrix);
753 VectorSet(q, normal[0], normal[1], normal[2], -dist);
754 qglClipPlane(GL_CLIP_PLANE0, q);
755 qglGetClipPlane(GL_CLIP_PLANE0, q);
756 VectorCopy4(q, clipPlane);
760 // Calculate the clip-space corner point opposite the clipping plane
761 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
762 // transform it into camera space by multiplying it
763 // by the inverse of the projection matrix
764 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
765 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
767 q[3] = (1.0f + m[10]) / m[14];
769 // Calculate the scaled plane vector
770 d = 2.0f / DotProduct4(clipPlane, q);
772 // Replace the third row of the projection matrix
773 m[2] = clipPlane[0] * d;
774 m[6] = clipPlane[1] * d;
775 m[10] = clipPlane[2] * d + 1.0f;
776 m[14] = clipPlane[3] * d;
779 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)
781 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
783 memset(v, 0, sizeof(*v));
784 v->type = R_VIEWPORTTYPE_ORTHO;
785 v->cameramatrix = *cameramatrix;
792 memset(m, 0, sizeof(m));
793 m[0] = 2/(right - left);
794 m[5] = 2/(top - bottom);
795 m[10] = -2/(zFar - zNear);
796 m[12] = - (right + left)/(right - left);
797 m[13] = - (top + bottom)/(top - bottom);
798 m[14] = - (zFar + zNear)/(zFar - zNear);
800 switch(vid.renderpath)
802 case RENDERPATH_GL11:
803 case RENDERPATH_GL13:
804 case RENDERPATH_GL20:
805 case RENDERPATH_SOFT:
806 case RENDERPATH_GLES1:
807 case RENDERPATH_GLES2:
809 case RENDERPATH_D3D9:
810 case RENDERPATH_D3D10:
811 case RENDERPATH_D3D11:
812 m[10] = -1/(zFar - zNear);
813 m[14] = -zNear/(zFar-zNear);
816 v->screentodepth[0] = -farclip / (farclip - nearclip);
817 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
819 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
822 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
824 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
830 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
831 R_Viewport_TransformToScreen(v, test1, test2);
832 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
837 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)
839 matrix4x4_t tempmatrix, basematrix;
841 memset(v, 0, sizeof(*v));
843 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
844 v->cameramatrix = *cameramatrix;
851 memset(m, 0, sizeof(m));
852 m[0] = 1.0 / frustumx;
853 m[5] = 1.0 / frustumy;
854 m[10] = -(farclip + nearclip) / (farclip - nearclip);
856 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
857 v->screentodepth[0] = -farclip / (farclip - nearclip);
858 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
860 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
861 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
862 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
863 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
866 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
868 if(v_flipped.integer)
876 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
879 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)
881 matrix4x4_t tempmatrix, basematrix;
882 const float nudge = 1.0 - 1.0 / (1<<23);
884 memset(v, 0, sizeof(*v));
886 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
887 v->cameramatrix = *cameramatrix;
894 memset(m, 0, sizeof(m));
895 m[ 0] = 1.0 / frustumx;
896 m[ 5] = 1.0 / frustumy;
899 m[14] = -2 * nearclip * nudge;
900 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
901 v->screentodepth[1] = m[14] * -0.5;
903 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
904 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
905 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
906 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
909 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
911 if(v_flipped.integer)
919 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
922 float cubeviewmatrix[6][16] =
924 // standard cubemap projections
962 float rectviewmatrix[6][16] =
964 // sign-preserving cubemap projections
1003 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
1005 matrix4x4_t tempmatrix, basematrix;
1007 memset(v, 0, sizeof(*v));
1008 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1009 v->cameramatrix = *cameramatrix;
1013 memset(m, 0, sizeof(m));
1015 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1017 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1019 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
1020 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1021 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1024 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1026 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1029 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)
1031 matrix4x4_t tempmatrix, basematrix;
1033 memset(v, 0, sizeof(*v));
1034 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1035 v->cameramatrix = *cameramatrix;
1036 v->x = (side & 1) * size;
1037 v->y = (side >> 1) * size;
1041 memset(m, 0, sizeof(m));
1042 m[0] = m[5] = 1.0f * ((float)size - border) / size;
1043 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1045 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1047 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1048 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1049 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1051 switch(vid.renderpath)
1053 case RENDERPATH_GL20:
1054 case RENDERPATH_GL13:
1055 case RENDERPATH_GL11:
1056 case RENDERPATH_SOFT:
1057 case RENDERPATH_GLES1:
1058 case RENDERPATH_GLES2:
1060 case RENDERPATH_D3D9:
1063 case RENDERPATH_D3D10:
1064 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1066 case RENDERPATH_D3D11:
1067 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1072 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1074 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1077 void R_SetViewport(const r_viewport_t *v)
1082 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1083 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1085 // copy over the matrices to our state
1086 gl_viewmatrix = v->viewmatrix;
1087 gl_projectionmatrix = v->projectmatrix;
1089 switch(vid.renderpath)
1091 case RENDERPATH_GL13:
1092 case RENDERPATH_GL11:
1093 case RENDERPATH_GLES1:
1095 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1096 // Load the projection matrix into OpenGL
1097 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1098 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1099 qglLoadMatrixf(m);CHECKGLERROR
1100 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1102 case RENDERPATH_D3D9:
1105 D3DVIEWPORT9 d3dviewport;
1106 d3dviewport.X = gl_viewport.x;
1107 d3dviewport.Y = gl_viewport.y;
1108 d3dviewport.Width = gl_viewport.width;
1109 d3dviewport.Height = gl_viewport.height;
1110 d3dviewport.MinZ = gl_state.depthrange[0];
1111 d3dviewport.MaxZ = gl_state.depthrange[1];
1112 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1116 case RENDERPATH_D3D10:
1117 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1119 case RENDERPATH_D3D11:
1120 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1122 case RENDERPATH_SOFT:
1123 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1125 case RENDERPATH_GL20:
1126 case RENDERPATH_GLES2:
1128 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1132 // force an update of the derived matrices
1133 gl_modelmatrixchanged = true;
1134 R_EntityMatrix(&gl_modelmatrix);
1137 void R_GetViewport(r_viewport_t *v)
1142 static void GL_BindVBO(int bufferobject)
1144 if (gl_state.vertexbufferobject != bufferobject)
1146 gl_state.vertexbufferobject = bufferobject;
1148 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1152 static void GL_BindEBO(int bufferobject)
1154 if (gl_state.elementbufferobject != bufferobject)
1156 gl_state.elementbufferobject = bufferobject;
1158 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1162 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1165 switch(vid.renderpath)
1167 case RENDERPATH_GL11:
1168 case RENDERPATH_GL13:
1169 case RENDERPATH_GL20:
1170 case RENDERPATH_GLES1:
1171 case RENDERPATH_GLES2:
1172 if (!vid.support.ext_framebuffer_object)
1174 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1175 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1176 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1177 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1178 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1179 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1180 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1182 case RENDERPATH_D3D9:
1183 case RENDERPATH_D3D10:
1184 case RENDERPATH_D3D11:
1186 case RENDERPATH_SOFT:
1192 void R_Mesh_DestroyFramebufferObject(int fbo)
1194 switch(vid.renderpath)
1196 case RENDERPATH_GL11:
1197 case RENDERPATH_GL13:
1198 case RENDERPATH_GL20:
1199 case RENDERPATH_GLES1:
1200 case RENDERPATH_GLES2:
1202 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1204 case RENDERPATH_D3D9:
1205 case RENDERPATH_D3D10:
1206 case RENDERPATH_D3D11:
1208 case RENDERPATH_SOFT:
1214 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1216 // 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)
1217 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)
1220 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1221 if (gl_state.d3drt_depthsurface != depthsurface)
1223 gl_state.d3drt_depthsurface = depthsurface;
1224 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1226 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1228 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1229 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1231 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1233 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1234 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1236 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1238 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1239 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1241 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1243 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1244 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1249 void R_Mesh_ResetRenderTargets(void)
1251 switch(vid.renderpath)
1253 case RENDERPATH_GL11:
1254 case RENDERPATH_GL13:
1255 case RENDERPATH_GL20:
1256 case RENDERPATH_GLES1:
1257 case RENDERPATH_GLES2:
1258 if (gl_state.framebufferobject)
1260 gl_state.framebufferobject = 0;
1261 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1264 case RENDERPATH_D3D9:
1266 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1269 case RENDERPATH_D3D10:
1270 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1272 case RENDERPATH_D3D11:
1273 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1275 case RENDERPATH_SOFT:
1276 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1281 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1285 rtexture_t *textures[5];
1286 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1287 textures[4] = depthtexture;
1288 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1289 for (j = 0;j < 5;j++)
1291 for (i = 0;i < vid.teximageunits;i++)
1292 if (gl_state.units[i].texture == textures[j])
1293 R_Mesh_TexBind(i, NULL);
1294 // set up framebuffer object or render targets for the active rendering API
1295 switch(vid.renderpath)
1297 case RENDERPATH_GL11:
1298 case RENDERPATH_GL13:
1299 case RENDERPATH_GL20:
1300 case RENDERPATH_GLES1:
1301 case RENDERPATH_GLES2:
1302 if (gl_state.framebufferobject != fbo)
1304 gl_state.framebufferobject = fbo;
1305 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1308 case RENDERPATH_D3D9:
1310 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1311 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1314 IDirect3DSurface9 *colorsurfaces[4];
1315 for (i = 0;i < 4;i++)
1317 colorsurfaces[i] = NULL;
1319 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1321 // set the render targets for real
1322 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1323 // release the texture surface levels (they won't be lost while bound...)
1324 for (i = 0;i < 4;i++)
1326 IDirect3DSurface9_Release(colorsurfaces[i]);
1329 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1332 case RENDERPATH_D3D10:
1333 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1335 case RENDERPATH_D3D11:
1336 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1338 case RENDERPATH_SOFT:
1342 unsigned int *pointers[5];
1343 memset(pointers, 0, sizeof(pointers));
1344 for (i = 0;i < 5;i++)
1345 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1346 width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1347 height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1348 DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1351 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1357 static int d3dcmpforglfunc(int f)
1361 case GL_NEVER: return D3DCMP_NEVER;
1362 case GL_LESS: return D3DCMP_LESS;
1363 case GL_EQUAL: return D3DCMP_EQUAL;
1364 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1365 case GL_GREATER: return D3DCMP_GREATER;
1366 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1367 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1368 case GL_ALWAYS: return D3DCMP_ALWAYS;
1369 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1373 static int d3dstencilopforglfunc(int f)
1377 case GL_KEEP: return D3DSTENCILOP_KEEP;
1378 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1379 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1380 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1385 extern cvar_t r_transparent_alphatocoverage;
1387 static void GL_Backend_ResetState(void)
1390 gl_state.active = true;
1391 gl_state.depthtest = true;
1392 gl_state.alphatest = false;
1393 gl_state.alphafunc = GL_GEQUAL;
1394 gl_state.alphafuncvalue = 0.5f;
1395 gl_state.alphatocoverage = false;
1396 gl_state.blendfunc1 = GL_ONE;
1397 gl_state.blendfunc2 = GL_ZERO;
1398 gl_state.blend = false;
1399 gl_state.depthmask = GL_TRUE;
1400 gl_state.colormask = 15;
1401 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1402 gl_state.lockrange_first = 0;
1403 gl_state.lockrange_count = 0;
1404 gl_state.cullface = GL_FRONT;
1405 gl_state.cullfaceenable = false;
1406 gl_state.polygonoffset[0] = 0;
1407 gl_state.polygonoffset[1] = 0;
1408 gl_state.framebufferobject = 0;
1409 gl_state.depthfunc = GL_LEQUAL;
1411 switch(vid.renderpath)
1413 case RENDERPATH_D3D9:
1416 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1417 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1418 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1419 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1420 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1421 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1422 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1426 case RENDERPATH_D3D10:
1427 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1429 case RENDERPATH_D3D11:
1430 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1432 case RENDERPATH_GL11:
1433 case RENDERPATH_GL13:
1434 case RENDERPATH_GLES1:
1437 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1438 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1439 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1440 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1441 qglDisable(GL_BLEND);CHECKGLERROR
1442 qglCullFace(gl_state.cullface);CHECKGLERROR
1443 qglDisable(GL_CULL_FACE);CHECKGLERROR
1444 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1445 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1446 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1447 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1449 if (vid.support.arb_vertex_buffer_object)
1451 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1452 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1455 if (vid.support.ext_framebuffer_object)
1457 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1458 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1461 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1462 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1464 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1465 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1466 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1468 if (vid.support.ext_framebuffer_object)
1469 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1471 gl_state.unit = MAX_TEXTUREUNITS;
1472 gl_state.clientunit = MAX_TEXTUREUNITS;
1473 for (i = 0;i < vid.texunits;i++)
1475 GL_ActiveTexture(i);
1476 GL_ClientActiveTexture(i);
1477 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1478 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1479 if (vid.support.ext_texture_3d)
1481 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1482 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1484 if (vid.support.arb_texture_cube_map)
1486 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1487 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1490 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1491 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1492 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1493 qglLoadIdentity();CHECKGLERROR
1494 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1495 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1499 case RENDERPATH_SOFT:
1500 DPSOFTRAST_ColorMask(1,1,1,1);
1501 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1502 DPSOFTRAST_CullFace(gl_state.cullface);
1503 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1504 DPSOFTRAST_DepthMask(gl_state.depthmask);
1505 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1506 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1507 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1509 case RENDERPATH_GL20:
1510 case RENDERPATH_GLES2:
1512 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1513 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1514 qglDisable(GL_BLEND);CHECKGLERROR
1515 qglCullFace(gl_state.cullface);CHECKGLERROR
1516 qglDisable(GL_CULL_FACE);CHECKGLERROR
1517 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1518 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1519 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1520 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1521 if (vid.support.arb_vertex_buffer_object)
1523 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1524 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1526 if (vid.support.ext_framebuffer_object)
1527 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1528 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1529 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1530 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1531 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1532 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1533 gl_state.unit = MAX_TEXTUREUNITS;
1534 gl_state.clientunit = MAX_TEXTUREUNITS;
1535 for (i = 0;i < vid.teximageunits;i++)
1537 GL_ActiveTexture(i);
1538 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1539 if (vid.support.ext_texture_3d)
1541 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1543 if (vid.support.arb_texture_cube_map)
1545 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1548 for (i = 0;i < vid.texarrayunits;i++)
1551 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1552 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1559 void GL_ActiveTexture(unsigned int num)
1561 if (gl_state.unit != num)
1563 gl_state.unit = num;
1564 switch(vid.renderpath)
1566 case RENDERPATH_GL11:
1567 case RENDERPATH_GL13:
1568 case RENDERPATH_GL20:
1569 case RENDERPATH_GLES1:
1570 case RENDERPATH_GLES2:
1571 if (qglActiveTexture)
1574 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1578 case RENDERPATH_D3D9:
1579 case RENDERPATH_D3D10:
1580 case RENDERPATH_D3D11:
1582 case RENDERPATH_SOFT:
1588 void GL_ClientActiveTexture(unsigned int num)
1590 if (gl_state.clientunit != num)
1592 gl_state.clientunit = num;
1593 switch(vid.renderpath)
1595 case RENDERPATH_GL11:
1596 case RENDERPATH_GL13:
1597 case RENDERPATH_GLES1:
1598 if (qglActiveTexture)
1601 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1605 case RENDERPATH_D3D9:
1606 case RENDERPATH_D3D10:
1607 case RENDERPATH_D3D11:
1609 case RENDERPATH_SOFT:
1611 case RENDERPATH_GL20:
1612 case RENDERPATH_GLES2:
1618 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1620 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1622 qboolean blendenable;
1623 gl_state.blendfunc1 = blendfunc1;
1624 gl_state.blendfunc2 = blendfunc2;
1625 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1626 switch(vid.renderpath)
1628 case RENDERPATH_GL11:
1629 case RENDERPATH_GL13:
1630 case RENDERPATH_GL20:
1631 case RENDERPATH_GLES1:
1632 case RENDERPATH_GLES2:
1634 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1635 if (gl_state.blend != blendenable)
1637 gl_state.blend = blendenable;
1638 if (!gl_state.blend)
1640 qglDisable(GL_BLEND);CHECKGLERROR
1644 qglEnable(GL_BLEND);CHECKGLERROR
1648 case RENDERPATH_D3D9:
1653 D3DBLEND d3dblendfunc[2];
1654 glblendfunc[0] = gl_state.blendfunc1;
1655 glblendfunc[1] = gl_state.blendfunc2;
1656 for (i = 0;i < 2;i++)
1658 switch(glblendfunc[i])
1660 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1661 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1662 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1663 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1664 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1665 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1666 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1667 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1668 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1669 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1672 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1673 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1674 if (gl_state.blend != blendenable)
1676 gl_state.blend = blendenable;
1677 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1682 case RENDERPATH_D3D10:
1683 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1685 case RENDERPATH_D3D11:
1686 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1688 case RENDERPATH_SOFT:
1689 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1695 void GL_DepthMask(int state)
1697 if (gl_state.depthmask != state)
1699 gl_state.depthmask = state;
1700 switch(vid.renderpath)
1702 case RENDERPATH_GL11:
1703 case RENDERPATH_GL13:
1704 case RENDERPATH_GL20:
1705 case RENDERPATH_GLES1:
1706 case RENDERPATH_GLES2:
1708 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1710 case RENDERPATH_D3D9:
1712 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1715 case RENDERPATH_D3D10:
1716 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1718 case RENDERPATH_D3D11:
1719 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1721 case RENDERPATH_SOFT:
1722 DPSOFTRAST_DepthMask(gl_state.depthmask);
1728 void GL_DepthTest(int state)
1730 if (gl_state.depthtest != state)
1732 gl_state.depthtest = state;
1733 switch(vid.renderpath)
1735 case RENDERPATH_GL11:
1736 case RENDERPATH_GL13:
1737 case RENDERPATH_GL20:
1738 case RENDERPATH_GLES1:
1739 case RENDERPATH_GLES2:
1741 if (gl_state.depthtest)
1743 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1747 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1750 case RENDERPATH_D3D9:
1752 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1755 case RENDERPATH_D3D10:
1756 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1758 case RENDERPATH_D3D11:
1759 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1761 case RENDERPATH_SOFT:
1762 DPSOFTRAST_DepthTest(gl_state.depthtest);
1768 void GL_DepthFunc(int state)
1770 if (gl_state.depthfunc != state)
1772 gl_state.depthfunc = state;
1773 switch(vid.renderpath)
1775 case RENDERPATH_GL11:
1776 case RENDERPATH_GL13:
1777 case RENDERPATH_GL20:
1778 case RENDERPATH_GLES1:
1779 case RENDERPATH_GLES2:
1781 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1783 case RENDERPATH_D3D9:
1785 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1788 case RENDERPATH_D3D10:
1789 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1791 case RENDERPATH_D3D11:
1792 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1794 case RENDERPATH_SOFT:
1795 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1801 void GL_DepthRange(float nearfrac, float farfrac)
1803 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1805 gl_state.depthrange[0] = nearfrac;
1806 gl_state.depthrange[1] = farfrac;
1807 switch(vid.renderpath)
1809 case RENDERPATH_GL11:
1810 case RENDERPATH_GL13:
1811 case RENDERPATH_GL20:
1812 case RENDERPATH_GLES1:
1813 case RENDERPATH_GLES2:
1814 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1816 case RENDERPATH_D3D9:
1819 D3DVIEWPORT9 d3dviewport;
1820 d3dviewport.X = gl_viewport.x;
1821 d3dviewport.Y = gl_viewport.y;
1822 d3dviewport.Width = gl_viewport.width;
1823 d3dviewport.Height = gl_viewport.height;
1824 d3dviewport.MinZ = gl_state.depthrange[0];
1825 d3dviewport.MaxZ = gl_state.depthrange[1];
1826 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1830 case RENDERPATH_D3D10:
1831 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1833 case RENDERPATH_D3D11:
1834 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836 case RENDERPATH_SOFT:
1837 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1843 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)
1845 switch (vid.renderpath)
1847 case RENDERPATH_GL11:
1848 case RENDERPATH_GL13:
1849 case RENDERPATH_GL20:
1850 case RENDERPATH_GLES1:
1851 case RENDERPATH_GLES2:
1855 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1859 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1861 if (vid.support.ati_separate_stencil)
1863 qglStencilMask(writemask);CHECKGLERROR
1864 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1865 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1866 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1868 else if (vid.support.ext_stencil_two_side)
1870 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1871 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1872 qglStencilMask(writemask);CHECKGLERROR
1873 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1874 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1875 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1876 qglStencilMask(writemask);CHECKGLERROR
1877 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1878 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1881 case RENDERPATH_D3D9:
1883 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1884 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1885 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1886 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1887 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1888 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1889 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1890 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1891 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1892 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1893 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1894 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1895 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1898 case RENDERPATH_D3D10:
1899 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1901 case RENDERPATH_D3D11:
1902 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1904 case RENDERPATH_SOFT:
1905 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1910 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1912 switch (vid.renderpath)
1914 case RENDERPATH_GL11:
1915 case RENDERPATH_GL13:
1916 case RENDERPATH_GL20:
1917 case RENDERPATH_GLES1:
1918 case RENDERPATH_GLES2:
1922 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1926 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1928 if (vid.support.ext_stencil_two_side)
1930 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1932 qglStencilMask(writemask);CHECKGLERROR
1933 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1934 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1937 case RENDERPATH_D3D9:
1939 if (vid.support.ati_separate_stencil)
1940 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1941 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1942 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1943 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1944 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1945 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1946 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1947 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1948 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1951 case RENDERPATH_D3D10:
1952 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1954 case RENDERPATH_D3D11:
1955 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957 case RENDERPATH_SOFT:
1958 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1963 void GL_PolygonOffset(float planeoffset, float depthoffset)
1965 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1967 gl_state.polygonoffset[0] = planeoffset;
1968 gl_state.polygonoffset[1] = depthoffset;
1969 switch(vid.renderpath)
1971 case RENDERPATH_GL11:
1972 case RENDERPATH_GL13:
1973 case RENDERPATH_GL20:
1974 case RENDERPATH_GLES1:
1975 case RENDERPATH_GLES2:
1976 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1978 case RENDERPATH_D3D9:
1980 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1981 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1984 case RENDERPATH_D3D10:
1985 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1987 case RENDERPATH_D3D11:
1988 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990 case RENDERPATH_SOFT:
1991 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1997 void GL_SetMirrorState(qboolean state)
1999 if (v_flipped_state != state)
2001 v_flipped_state = state;
2002 if (gl_state.cullface == GL_BACK)
2003 gl_state.cullface = GL_FRONT;
2004 else if (gl_state.cullface == GL_FRONT)
2005 gl_state.cullface = GL_BACK;
2008 switch(vid.renderpath)
2010 case RENDERPATH_GL11:
2011 case RENDERPATH_GL13:
2012 case RENDERPATH_GL20:
2013 case RENDERPATH_GLES1:
2014 case RENDERPATH_GLES2:
2015 qglCullFace(gl_state.cullface);CHECKGLERROR
2017 case RENDERPATH_D3D9:
2019 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2022 case RENDERPATH_D3D10:
2023 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2025 case RENDERPATH_D3D11:
2026 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2028 case RENDERPATH_SOFT:
2029 DPSOFTRAST_CullFace(gl_state.cullface);
2035 void GL_CullFace(int state)
2039 if(state == GL_FRONT)
2041 else if(state == GL_BACK)
2045 switch(vid.renderpath)
2047 case RENDERPATH_GL11:
2048 case RENDERPATH_GL13:
2049 case RENDERPATH_GL20:
2050 case RENDERPATH_GLES1:
2051 case RENDERPATH_GLES2:
2054 if (state != GL_NONE)
2056 if (!gl_state.cullfaceenable)
2058 gl_state.cullfaceenable = true;
2059 qglEnable(GL_CULL_FACE);CHECKGLERROR
2061 if (gl_state.cullface != state)
2063 gl_state.cullface = state;
2064 qglCullFace(gl_state.cullface);CHECKGLERROR
2069 if (gl_state.cullfaceenable)
2071 gl_state.cullfaceenable = false;
2072 qglDisable(GL_CULL_FACE);CHECKGLERROR
2076 case RENDERPATH_D3D9:
2078 if (gl_state.cullface != state)
2080 gl_state.cullface = state;
2081 switch(gl_state.cullface)
2084 gl_state.cullfaceenable = false;
2085 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2088 gl_state.cullfaceenable = true;
2089 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2092 gl_state.cullfaceenable = true;
2093 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2099 case RENDERPATH_D3D10:
2100 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2102 case RENDERPATH_D3D11:
2103 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2105 case RENDERPATH_SOFT:
2106 if (gl_state.cullface != state)
2108 gl_state.cullface = state;
2109 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2110 DPSOFTRAST_CullFace(gl_state.cullface);
2116 void GL_MultiSampling(qboolean state)
2118 switch(vid.renderpath)
2120 case RENDERPATH_GL11:
2121 case RENDERPATH_GL13:
2122 case RENDERPATH_GLES1:
2123 case RENDERPATH_GL20:
2124 case RENDERPATH_GLES2:
2125 if (vid.support.arb_multisample && vid.mode.samples > 1)
2128 qglEnable(GL_MULTISAMPLE_ARB);
2130 qglDisable(GL_MULTISAMPLE_ARB);
2134 case RENDERPATH_D3D9:
2136 case RENDERPATH_D3D10:
2138 case RENDERPATH_D3D11:
2140 case RENDERPATH_SOFT:
2145 void GL_AlphaTest(int state)
2147 if (gl_state.alphatest != state)
2149 gl_state.alphatest = state;
2150 switch(vid.renderpath)
2152 case RENDERPATH_GL11:
2153 case RENDERPATH_GL13:
2154 case RENDERPATH_GLES1:
2155 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2157 if (gl_state.alphatest)
2159 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2163 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2166 case RENDERPATH_D3D9:
2167 case RENDERPATH_D3D10:
2168 case RENDERPATH_D3D11:
2169 case RENDERPATH_SOFT:
2170 case RENDERPATH_GL20:
2171 case RENDERPATH_GLES2:
2177 void GL_AlphaToCoverage(qboolean state)
2179 if (gl_state.alphatocoverage != state)
2181 gl_state.alphatocoverage = state;
2182 switch(vid.renderpath)
2184 case RENDERPATH_GL11:
2185 case RENDERPATH_GL13:
2186 case RENDERPATH_GLES1:
2187 case RENDERPATH_GLES2:
2188 case RENDERPATH_D3D9:
2189 case RENDERPATH_D3D10:
2190 case RENDERPATH_D3D11:
2191 case RENDERPATH_SOFT:
2193 case RENDERPATH_GL20:
2194 // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
2195 if (vid.support.arb_multisample && vid.mode.samples > 1)
2198 if (gl_state.alphatocoverage)
2200 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2201 qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2205 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2206 qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2214 void GL_ColorMask(int r, int g, int b, int a)
2216 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2217 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2218 if (gl_state.colormask != state)
2220 gl_state.colormask = state;
2221 switch(vid.renderpath)
2223 case RENDERPATH_GL11:
2224 case RENDERPATH_GL13:
2225 case RENDERPATH_GL20:
2226 case RENDERPATH_GLES1:
2227 case RENDERPATH_GLES2:
2229 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2231 case RENDERPATH_D3D9:
2233 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2236 case RENDERPATH_D3D10:
2237 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2239 case RENDERPATH_D3D11:
2240 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2242 case RENDERPATH_SOFT:
2243 DPSOFTRAST_ColorMask(r, g, b, a);
2249 void GL_Color(float cr, float cg, float cb, float ca)
2251 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)
2253 gl_state.color4f[0] = cr;
2254 gl_state.color4f[1] = cg;
2255 gl_state.color4f[2] = cb;
2256 gl_state.color4f[3] = ca;
2257 switch(vid.renderpath)
2259 case RENDERPATH_GL11:
2260 case RENDERPATH_GL13:
2261 case RENDERPATH_GLES1:
2263 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2266 case RENDERPATH_D3D9:
2267 case RENDERPATH_D3D10:
2268 case RENDERPATH_D3D11:
2269 // no equivalent in D3D
2271 case RENDERPATH_SOFT:
2272 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2274 case RENDERPATH_GL20:
2275 case RENDERPATH_GLES2:
2276 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2282 void GL_Scissor (int x, int y, int width, int height)
2284 switch(vid.renderpath)
2286 case RENDERPATH_GL11:
2287 case RENDERPATH_GL13:
2288 case RENDERPATH_GL20:
2289 case RENDERPATH_GLES1:
2290 case RENDERPATH_GLES2:
2292 qglScissor(x, y,width,height);
2295 case RENDERPATH_D3D9:
2301 d3drect.right = x + width;
2302 d3drect.bottom = y + height;
2303 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2307 case RENDERPATH_D3D10:
2308 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2310 case RENDERPATH_D3D11:
2311 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2313 case RENDERPATH_SOFT:
2314 DPSOFTRAST_Scissor(x, y, width, height);
2319 void GL_ScissorTest(int state)
2321 if (gl_state.scissortest != state)
2323 gl_state.scissortest = state;
2324 switch(vid.renderpath)
2326 case RENDERPATH_GL11:
2327 case RENDERPATH_GL13:
2328 case RENDERPATH_GL20:
2329 case RENDERPATH_GLES1:
2330 case RENDERPATH_GLES2:
2332 if(gl_state.scissortest)
2333 qglEnable(GL_SCISSOR_TEST);
2335 qglDisable(GL_SCISSOR_TEST);
2338 case RENDERPATH_D3D9:
2340 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2343 case RENDERPATH_D3D10:
2344 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2346 case RENDERPATH_D3D11:
2347 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2349 case RENDERPATH_SOFT:
2350 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2356 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2358 static const float blackcolor[4] = {0, 0, 0, 0};
2359 // prevent warnings when trying to clear a buffer that does not exist
2361 colorvalue = blackcolor;
2364 mask &= ~GL_STENCIL_BUFFER_BIT;
2367 switch(vid.renderpath)
2369 case RENDERPATH_GL11:
2370 case RENDERPATH_GL13:
2371 case RENDERPATH_GL20:
2372 case RENDERPATH_GLES1:
2373 case RENDERPATH_GLES2:
2375 if (mask & GL_COLOR_BUFFER_BIT)
2377 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2379 if (mask & GL_DEPTH_BUFFER_BIT)
2381 qglClearDepth(depthvalue);CHECKGLERROR
2383 if (mask & GL_STENCIL_BUFFER_BIT)
2385 qglClearStencil(stencilvalue);CHECKGLERROR
2387 qglClear(mask);CHECKGLERROR
2389 case RENDERPATH_D3D9:
2391 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);
2394 case RENDERPATH_D3D10:
2395 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2397 case RENDERPATH_D3D11:
2398 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2400 case RENDERPATH_SOFT:
2401 if (mask & GL_COLOR_BUFFER_BIT)
2402 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2403 if (mask & GL_DEPTH_BUFFER_BIT)
2404 DPSOFTRAST_ClearDepth(depthvalue);
2409 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2411 switch(vid.renderpath)
2413 case RENDERPATH_GL11:
2414 case RENDERPATH_GL13:
2415 case RENDERPATH_GL20:
2416 case RENDERPATH_GLES1:
2417 case RENDERPATH_GLES2:
2419 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2421 case RENDERPATH_D3D9:
2424 // LordHavoc: we can't directly download the backbuffer because it may be
2425 // multisampled, and it may not be lockable, so we blit it to a lockable
2426 // surface of the same dimensions (but without multisample) to resolve the
2427 // multisample buffer to a normal image, and then lock that...
2428 IDirect3DSurface9 *stretchsurface = NULL;
2429 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2431 D3DLOCKED_RECT lockedrect;
2432 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2434 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2437 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2438 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2439 memcpy(outpixels + line * width * 4, row, width * 4);
2440 IDirect3DSurface9_UnlockRect(stretchsurface);
2443 IDirect3DSurface9_Release(stretchsurface);
2446 //IDirect3DSurface9 *syssurface = NULL;
2447 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2448 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2449 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2450 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2451 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2452 //IDirect3DSurface9_UnlockRect(syssurface);
2453 //IDirect3DSurface9_Release(syssurface);
2457 case RENDERPATH_D3D10:
2458 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2460 case RENDERPATH_D3D11:
2461 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2463 case RENDERPATH_SOFT:
2464 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2469 // called at beginning of frame
2470 void R_Mesh_Start(void)
2473 R_Mesh_ResetRenderTargets();
2475 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2477 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2478 Cvar_SetValueQuick(&gl_paranoid, 1);
2482 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2486 char compilelog[MAX_INPUTLINE];
2487 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2490 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2491 qglCompileShader(shaderobject);CHECKGLERROR
2492 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2493 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2494 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2496 int i, j, pretextlines = 0;
2497 for (i = 0;i < numstrings - 1;i++)
2498 for (j = 0;strings[i][j];j++)
2499 if (strings[i][j] == '\n')
2501 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2503 if (!shadercompiled)
2505 qglDeleteShader(shaderobject);CHECKGLERROR
2508 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2509 qglDeleteShader(shaderobject);CHECKGLERROR
2513 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)
2515 GLint programlinked;
2516 GLuint programobject = 0;
2517 char linklog[MAX_INPUTLINE];
2520 programobject = qglCreateProgram();CHECKGLERROR
2524 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2525 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2526 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2527 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2528 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2529 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2530 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2531 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2532 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2533 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2534 if(vid.support.gl20shaders130)
2535 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2537 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2540 #ifdef GL_GEOMETRY_SHADER
2541 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2545 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2548 qglLinkProgram(programobject);CHECKGLERROR
2549 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2550 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2553 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2554 Con_DPrintf("program link log:\n%s\n", linklog);
2555 // software vertex shader is ok but software fragment shader is WAY
2556 // too slow, fail program if so.
2557 // NOTE: this string might be ATI specific, but that's ok because the
2558 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2559 // software fragment shader due to low instruction and dependent
2561 if (strstr(linklog, "fragment shader will run in software"))
2562 programlinked = false;
2566 return programobject;
2568 qglDeleteProgram(programobject);CHECKGLERROR
2572 void GL_Backend_FreeProgram(unsigned int prog)
2575 qglDeleteProgram(prog);
2579 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2584 for (i = 0;i < count;i++)
2585 *out++ = *in++ + offset;
2588 memcpy(out, in, sizeof(*out) * count);
2591 // renders triangles using vertices from the active arrays
2592 int paranoidblah = 0;
2593 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)
2595 unsigned int numelements = numtriangles * 3;
2597 size_t bufferoffset3i;
2599 size_t bufferoffset3s;
2600 if (numvertices < 3 || numtriangles < 1)
2602 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2603 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);
2606 if (!gl_mesh_prefer_short_elements.integer)
2610 if (element3i_indexbuffer)
2611 element3i_indexbuffer = NULL;
2613 // adjust the pointers for firsttriangle
2615 element3i += firsttriangle * 3;
2616 if (element3i_indexbuffer)
2617 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2619 element3s += firsttriangle * 3;
2620 if (element3s_indexbuffer)
2621 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2622 switch(vid.renderpath)
2624 case RENDERPATH_GL11:
2625 case RENDERPATH_GL13:
2626 case RENDERPATH_GL20:
2627 case RENDERPATH_GLES1:
2628 case RENDERPATH_GLES2:
2629 // check if the user specified to ignore static index buffers
2630 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2632 element3i_indexbuffer = NULL;
2633 element3s_indexbuffer = NULL;
2636 case RENDERPATH_D3D9:
2637 case RENDERPATH_D3D10:
2638 case RENDERPATH_D3D11:
2640 case RENDERPATH_SOFT:
2643 // upload a dynamic index buffer if needed
2646 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2648 if (gl_state.draw_dynamicindexbuffer)
2649 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2651 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2652 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2653 element3s_bufferoffset = 0;
2658 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2660 if (gl_state.draw_dynamicindexbuffer)
2661 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2663 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2664 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2665 element3i_bufferoffset = 0;
2668 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2669 bufferoffset3i = element3i_bufferoffset;
2670 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2671 bufferoffset3s = element3s_bufferoffset;
2672 r_refdef.stats.draws++;
2673 r_refdef.stats.draws_vertices += numvertices;
2674 r_refdef.stats.draws_elements += numelements;
2675 if (gl_paranoid.integer)
2678 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2680 unsigned int j, size;
2682 // note: there's no validation done here on buffer objects because it
2683 // is somewhat difficult to get at the data, and gl_paranoid can be
2684 // used without buffer objects if the need arises
2685 // (the data could be gotten using glMapBuffer but it would be very
2686 // slow due to uncachable video memory reads)
2687 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2688 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2690 if (gl_state.pointer_vertex_pointer)
2691 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2693 if (gl_state.pointer_color_enabled)
2695 if (!qglIsEnabled(GL_COLOR_ARRAY))
2696 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2698 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2699 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2702 for (i = 0;i < vid.texarrayunits;i++)
2704 if (gl_state.units[i].arrayenabled)
2706 GL_ClientActiveTexture(i);
2707 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2708 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2710 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2711 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++)
2718 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2720 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2722 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2729 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2731 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2733 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2739 if (r_render.integer || r_refdef.draw2dstage)
2741 switch(vid.renderpath)
2743 case RENDERPATH_GL11:
2744 case RENDERPATH_GL13:
2745 case RENDERPATH_GL20:
2747 if (gl_mesh_testmanualfeeding.integer)
2749 unsigned int i, j, element;
2751 qglBegin(GL_TRIANGLES);
2752 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2755 element = element3i[i];
2757 element = element3s[i];
2759 element = firstvertex + i;
2760 for (j = 0;j < vid.texarrayunits;j++)
2762 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2764 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2766 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2767 if (vid.texarrayunits > 1)
2769 if (gl_state.units[j].pointer_texcoord_components == 4)
2770 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2771 else if (gl_state.units[j].pointer_texcoord_components == 3)
2772 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2773 else if (gl_state.units[j].pointer_texcoord_components == 2)
2774 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2776 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2780 if (gl_state.units[j].pointer_texcoord_components == 4)
2781 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2782 else if (gl_state.units[j].pointer_texcoord_components == 3)
2783 qglTexCoord3f(p[0], p[1], p[2]);
2784 else if (gl_state.units[j].pointer_texcoord_components == 2)
2785 qglTexCoord2f(p[0], p[1]);
2787 qglTexCoord1f(p[0]);
2790 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2792 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2793 if (vid.texarrayunits > 1)
2795 if (gl_state.units[j].pointer_texcoord_components == 4)
2796 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2797 else if (gl_state.units[j].pointer_texcoord_components == 3)
2798 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2799 else if (gl_state.units[j].pointer_texcoord_components == 2)
2800 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2801 else if (gl_state.units[j].pointer_texcoord_components == 1)
2802 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2806 if (gl_state.units[j].pointer_texcoord_components == 4)
2807 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2808 else if (gl_state.units[j].pointer_texcoord_components == 3)
2809 qglTexCoord3f(s[0], s[1], s[2]);
2810 else if (gl_state.units[j].pointer_texcoord_components == 2)
2811 qglTexCoord2f(s[0], s[1]);
2812 else if (gl_state.units[j].pointer_texcoord_components == 1)
2813 qglTexCoord1f(s[0]);
2816 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2818 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2819 if (vid.texarrayunits > 1)
2821 if (gl_state.units[j].pointer_texcoord_components == 4)
2822 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2823 else if (gl_state.units[j].pointer_texcoord_components == 3)
2824 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2825 else if (gl_state.units[j].pointer_texcoord_components == 2)
2826 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2827 else if (gl_state.units[j].pointer_texcoord_components == 1)
2828 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2832 if (gl_state.units[j].pointer_texcoord_components == 4)
2833 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2834 else if (gl_state.units[j].pointer_texcoord_components == 3)
2835 qglTexCoord3f(sb[0], sb[1], sb[2]);
2836 else if (gl_state.units[j].pointer_texcoord_components == 2)
2837 qglTexCoord2f(sb[0], sb[1]);
2838 else if (gl_state.units[j].pointer_texcoord_components == 1)
2839 qglTexCoord1f(sb[0]);
2844 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2846 if (gl_state.pointer_color_gltype == GL_FLOAT)
2848 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2849 qglColor4f(p[0], p[1], p[2], p[3]);
2851 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2853 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2854 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2857 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2859 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2860 if (gl_state.pointer_vertex_components == 4)
2861 qglVertex4f(p[0], p[1], p[2], p[3]);
2862 else if (gl_state.pointer_vertex_components == 3)
2863 qglVertex3f(p[0], p[1], p[2]);
2865 qglVertex2f(p[0], p[1]);
2871 else if (bufferobject3s)
2873 GL_BindEBO(bufferobject3s);
2874 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2876 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2881 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2885 else if (bufferobject3i)
2887 GL_BindEBO(bufferobject3i);
2888 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2890 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2895 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2902 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2904 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2909 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2916 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2918 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2923 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2929 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2933 case RENDERPATH_D3D9:
2935 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2937 if (element3s_indexbuffer)
2939 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2940 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2942 else if (element3i_indexbuffer)
2944 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2945 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2948 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2953 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2955 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2957 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2961 case RENDERPATH_D3D10:
2962 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2964 case RENDERPATH_D3D11:
2965 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2967 case RENDERPATH_SOFT:
2968 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2970 case RENDERPATH_GLES1:
2971 case RENDERPATH_GLES2:
2972 // GLES does not have glDrawRangeElements, and generally
2973 // underperforms with index buffers, so this code path is
2974 // relatively straightforward...
2976 if (gl_paranoid.integer)
2978 int r, prog, enabled, i;
2979 GLsizei attriblength;
2982 GLchar attribname[1024];
2983 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2984 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2985 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2986 #ifndef GL_CURRENT_PROGRAM
2987 #define GL_CURRENT_PROGRAM 0x8B8D
2989 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2990 if (r < 0 || r > 10000)
2991 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2993 for (i = 0;i < 8;i++)
2995 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2998 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2999 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);
3005 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
3010 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
3015 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
3023 // restores backend state, used when done with 3D rendering
3024 void R_Mesh_Finish(void)
3026 R_Mesh_ResetRenderTargets();
3029 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
3031 r_meshbuffer_t *buffer;
3032 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
3034 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
3035 memset(buffer, 0, sizeof(*buffer));
3036 buffer->bufferobject = 0;
3037 buffer->devicebuffer = NULL;
3039 buffer->isindexbuffer = isindexbuffer;
3040 buffer->isdynamic = isdynamic;
3041 buffer->isindex16 = isindex16;
3042 strlcpy(buffer->name, name, sizeof(buffer->name));
3043 R_Mesh_UpdateMeshBuffer(buffer, data, size);
3047 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
3051 if (buffer->isindexbuffer)
3053 r_refdef.stats.indexbufferuploadcount++;
3054 r_refdef.stats.indexbufferuploadsize += size;
3058 r_refdef.stats.vertexbufferuploadcount++;
3059 r_refdef.stats.vertexbufferuploadsize += size;
3061 switch(vid.renderpath)
3063 case RENDERPATH_GL11:
3064 case RENDERPATH_GL13:
3065 case RENDERPATH_GL20:
3066 case RENDERPATH_GLES1:
3067 case RENDERPATH_GLES2:
3068 if (!buffer->bufferobject)
3069 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3070 if (buffer->isindexbuffer)
3071 GL_BindEBO(buffer->bufferobject);
3073 GL_BindVBO(buffer->bufferobject);
3074 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
3076 case RENDERPATH_D3D9:
3080 void *datapointer = NULL;
3081 if (buffer->isindexbuffer)
3083 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3084 if (size > buffer->size || !buffer->devicebuffer)
3086 if (buffer->devicebuffer)
3087 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3088 buffer->devicebuffer = NULL;
3089 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)))
3090 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);
3091 buffer->devicebuffer = (void *)d3d9indexbuffer;
3092 buffer->size = size;
3094 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3097 memcpy(datapointer, data, size);
3099 memset(datapointer, 0, size);
3100 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3105 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3106 if (size > buffer->size || !buffer->devicebuffer)
3108 if (buffer->devicebuffer)
3109 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3110 buffer->devicebuffer = NULL;
3111 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3112 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);
3113 buffer->devicebuffer = (void *)d3d9vertexbuffer;
3114 buffer->size = size;
3116 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3119 memcpy(datapointer, data, size);
3121 memset(datapointer, 0, size);
3122 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3128 case RENDERPATH_D3D10:
3129 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3131 case RENDERPATH_D3D11:
3132 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3134 case RENDERPATH_SOFT:
3139 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3143 switch(vid.renderpath)
3145 case RENDERPATH_GL11:
3146 case RENDERPATH_GL13:
3147 case RENDERPATH_GL20:
3148 case RENDERPATH_GLES1:
3149 case RENDERPATH_GLES2:
3150 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3152 case RENDERPATH_D3D9:
3154 if (gl_state.d3dvertexbuffer == (void *)buffer)
3155 gl_state.d3dvertexbuffer = NULL;
3156 if (buffer->devicebuffer)
3158 if (buffer->isindexbuffer)
3159 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3161 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3162 buffer->devicebuffer = NULL;
3166 case RENDERPATH_D3D10:
3167 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3169 case RENDERPATH_D3D11:
3170 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3172 case RENDERPATH_SOFT:
3175 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3178 void GL_Mesh_ListVBOs(qboolean printeach)
3181 size_t ebocount = 0, ebomemory = 0;
3182 size_t vbocount = 0, vbomemory = 0;
3183 r_meshbuffer_t *buffer;
3184 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3185 for (i = 0;i < endindex;i++)
3187 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3190 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)");}
3191 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)");}
3193 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);
3198 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3200 switch(vid.renderpath)
3202 case RENDERPATH_GL11:
3203 case RENDERPATH_GL13:
3204 case RENDERPATH_GLES1:
3205 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)
3207 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3208 gl_state.pointer_vertex_components = components;
3209 gl_state.pointer_vertex_gltype = gltype;
3210 gl_state.pointer_vertex_stride = stride;
3211 gl_state.pointer_vertex_pointer = pointer;
3212 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3213 gl_state.pointer_vertex_offset = bufferoffset;
3215 GL_BindVBO(bufferobject);
3216 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3219 case RENDERPATH_GL20:
3220 case RENDERPATH_GLES2:
3221 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)
3223 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3224 gl_state.pointer_vertex_components = components;
3225 gl_state.pointer_vertex_gltype = gltype;
3226 gl_state.pointer_vertex_stride = stride;
3227 gl_state.pointer_vertex_pointer = pointer;
3228 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3229 gl_state.pointer_vertex_offset = bufferoffset;
3231 GL_BindVBO(bufferobject);
3232 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3235 case RENDERPATH_D3D9:
3236 case RENDERPATH_D3D10:
3237 case RENDERPATH_D3D11:
3238 case RENDERPATH_SOFT:
3243 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3245 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3246 // the pointer only.
3247 switch(vid.renderpath)
3249 case RENDERPATH_GL11:
3250 case RENDERPATH_GL13:
3251 case RENDERPATH_GLES1:
3255 // caller wants color array enabled
3256 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3257 if (!gl_state.pointer_color_enabled)
3259 gl_state.pointer_color_enabled = true;
3261 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3263 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)
3265 gl_state.pointer_color_components = components;
3266 gl_state.pointer_color_gltype = gltype;
3267 gl_state.pointer_color_stride = stride;
3268 gl_state.pointer_color_pointer = pointer;
3269 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3270 gl_state.pointer_color_offset = bufferoffset;
3272 GL_BindVBO(bufferobject);
3273 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3278 // caller wants color array disabled
3279 if (gl_state.pointer_color_enabled)
3281 gl_state.pointer_color_enabled = false;
3283 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3284 // when color array is on the glColor gets trashed, set it again
3285 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3289 case RENDERPATH_GL20:
3290 case RENDERPATH_GLES2:
3294 // caller wants color array enabled
3295 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3296 if (!gl_state.pointer_color_enabled)
3298 gl_state.pointer_color_enabled = true;
3300 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3302 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)
3304 gl_state.pointer_color_components = components;
3305 gl_state.pointer_color_gltype = gltype;
3306 gl_state.pointer_color_stride = stride;
3307 gl_state.pointer_color_pointer = pointer;
3308 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3309 gl_state.pointer_color_offset = bufferoffset;
3311 GL_BindVBO(bufferobject);
3312 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3317 // caller wants color array disabled
3318 if (gl_state.pointer_color_enabled)
3320 gl_state.pointer_color_enabled = false;
3322 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3323 // when color array is on the glColor gets trashed, set it again
3324 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3328 case RENDERPATH_D3D9:
3329 case RENDERPATH_D3D10:
3330 case RENDERPATH_D3D11:
3331 case RENDERPATH_SOFT:
3336 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)
3338 gltextureunit_t *unit = gl_state.units + unitnum;
3339 // update array settings
3340 // note: there is no need to check bufferobject here because all cases
3341 // that involve a valid bufferobject also supply a texcoord array
3342 switch(vid.renderpath)
3344 case RENDERPATH_GL11:
3345 case RENDERPATH_GL13:
3346 case RENDERPATH_GLES1:
3350 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3351 // texture array unit is enabled, enable the array
3352 if (!unit->arrayenabled)
3354 unit->arrayenabled = true;
3355 GL_ClientActiveTexture(unitnum);
3356 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3359 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)
3361 unit->pointer_texcoord_components = components;
3362 unit->pointer_texcoord_gltype = gltype;
3363 unit->pointer_texcoord_stride = stride;
3364 unit->pointer_texcoord_pointer = pointer;
3365 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3366 unit->pointer_texcoord_offset = bufferoffset;
3367 GL_ClientActiveTexture(unitnum);
3368 GL_BindVBO(bufferobject);
3369 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3374 // texture array unit is disabled, disable the array
3375 if (unit->arrayenabled)
3377 unit->arrayenabled = false;
3378 GL_ClientActiveTexture(unitnum);
3379 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3383 case RENDERPATH_GL20:
3384 case RENDERPATH_GLES2:
3388 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3389 // texture array unit is enabled, enable the array
3390 if (!unit->arrayenabled)
3392 unit->arrayenabled = true;
3393 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3396 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)
3398 unit->pointer_texcoord_components = components;
3399 unit->pointer_texcoord_gltype = gltype;
3400 unit->pointer_texcoord_stride = stride;
3401 unit->pointer_texcoord_pointer = pointer;
3402 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3403 unit->pointer_texcoord_offset = bufferoffset;
3404 GL_BindVBO(bufferobject);
3405 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3410 // texture array unit is disabled, disable the array
3411 if (unit->arrayenabled)
3413 unit->arrayenabled = false;
3414 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3418 case RENDERPATH_D3D9:
3419 case RENDERPATH_D3D10:
3420 case RENDERPATH_D3D11:
3421 case RENDERPATH_SOFT:
3426 int R_Mesh_TexBound(unsigned int unitnum, int id)
3428 gltextureunit_t *unit = gl_state.units + unitnum;
3429 if (unitnum >= vid.teximageunits)
3431 if (id == GL_TEXTURE_2D)
3433 if (id == GL_TEXTURE_3D)
3435 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3436 return unit->tcubemap;
3440 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3442 switch(vid.renderpath)
3444 case RENDERPATH_GL11:
3445 case RENDERPATH_GL13:
3446 case RENDERPATH_GL20:
3447 case RENDERPATH_GLES1:
3448 case RENDERPATH_GLES2:
3449 R_Mesh_TexBind(0, tex);
3450 GL_ActiveTexture(0);CHECKGLERROR
3451 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3453 case RENDERPATH_D3D9:
3456 IDirect3DSurface9 *currentsurface = NULL;
3457 IDirect3DSurface9 *texturesurface = NULL;
3460 sourcerect.left = sx;
3461 sourcerect.top = sy;
3462 sourcerect.right = sx + width;
3463 sourcerect.bottom = sy + height;
3466 destrect.right = tx + width;
3467 destrect.bottom = ty + height;
3468 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3470 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3472 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3473 IDirect3DSurface9_Release(currentsurface);
3475 IDirect3DSurface9_Release(texturesurface);
3480 case RENDERPATH_D3D10:
3481 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3483 case RENDERPATH_D3D11:
3484 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3486 case RENDERPATH_SOFT:
3487 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3493 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};
3496 void R_Mesh_ClearBindingsForTexture(int texnum)
3498 gltextureunit_t *unit;
3499 unsigned int unitnum;
3500 // 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)
3501 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3503 unit = gl_state.units + unitnum;
3504 if (unit->t2d == texnum)
3506 if (unit->t3d == texnum)
3508 if (unit->tcubemap == texnum)
3509 unit->tcubemap = -1;
3513 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3515 gltextureunit_t *unit = gl_state.units + unitnum;
3516 int tex2d, tex3d, texcubemap, texnum;
3517 if (unitnum >= vid.teximageunits)
3519 // if (unit->texture == tex)
3521 switch(vid.renderpath)
3523 case RENDERPATH_GL20:
3524 case RENDERPATH_GLES2:
3527 tex = r_texture_white;
3528 // not initialized enough yet...
3532 unit->texture = tex;
3533 texnum = R_GetTexture(tex);
3534 switch(tex->gltexturetypeenum)
3536 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3537 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3538 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;
3541 case RENDERPATH_GL11:
3542 case RENDERPATH_GL13:
3543 case RENDERPATH_GLES1:
3544 unit->texture = tex;
3550 texnum = R_GetTexture(tex);
3551 switch(tex->gltexturetypeenum)
3559 case GL_TEXTURE_CUBE_MAP_ARB:
3560 texcubemap = texnum;
3564 // update 2d texture binding
3565 if (unit->t2d != tex2d)
3567 GL_ActiveTexture(unitnum);
3572 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3579 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3583 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3585 // update 3d texture binding
3586 if (unit->t3d != tex3d)
3588 GL_ActiveTexture(unitnum);
3593 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3600 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3604 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3606 // update cubemap texture binding
3607 if (unit->tcubemap != texcubemap)
3609 GL_ActiveTexture(unitnum);
3612 if (unit->tcubemap == 0)
3614 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3621 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3624 unit->tcubemap = texcubemap;
3625 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3628 case RENDERPATH_D3D9:
3631 extern cvar_t gl_texture_anisotropy;
3634 tex = r_texture_white;
3635 // not initialized enough yet...
3639 // upload texture if needed
3641 if (unit->texture == tex)
3643 unit->texture = tex;
3644 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3645 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3646 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3647 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3648 if (tex->d3daddressw)
3649 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3650 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3651 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3652 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3653 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3654 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3655 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3659 case RENDERPATH_D3D10:
3660 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3662 case RENDERPATH_D3D11:
3663 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3665 case RENDERPATH_SOFT:
3668 tex = r_texture_white;
3669 // not initialized enough yet...
3673 texnum = R_GetTexture(tex);
3674 if (unit->texture == tex)
3676 unit->texture = tex;
3677 DPSOFTRAST_SetTexture(unitnum, texnum);
3682 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3684 gltextureunit_t *unit = gl_state.units + unitnum;
3685 switch(vid.renderpath)
3687 case RENDERPATH_GL11:
3688 case RENDERPATH_GL13:
3689 case RENDERPATH_GL20:
3690 case RENDERPATH_GLES1:
3691 case RENDERPATH_GLES2:
3692 if (matrix && matrix->m[3][3])
3694 // texmatrix specified, check if it is different
3695 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3698 unit->texmatrixenabled = true;
3699 unit->matrix = *matrix;
3701 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3702 GL_ActiveTexture(unitnum);
3703 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3704 qglLoadMatrixf(glmatrix);CHECKGLERROR
3705 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3710 // no texmatrix specified, revert to identity
3711 if (unit->texmatrixenabled)
3713 unit->texmatrixenabled = false;
3714 unit->matrix = identitymatrix;
3716 GL_ActiveTexture(unitnum);
3717 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3718 qglLoadIdentity();CHECKGLERROR
3719 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3723 case RENDERPATH_D3D9:
3724 case RENDERPATH_D3D10:
3725 case RENDERPATH_D3D11:
3727 case RENDERPATH_SOFT:
3732 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3734 gltextureunit_t *unit = gl_state.units + unitnum;
3736 switch(vid.renderpath)
3738 case RENDERPATH_GL20:
3739 case RENDERPATH_GLES2:
3742 case RENDERPATH_GL13:
3743 case RENDERPATH_GLES1:
3744 // GL_ARB_texture_env_combine
3746 combinergb = GL_MODULATE;
3748 combinealpha = GL_MODULATE;
3753 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3755 if (combinergb == GL_DECAL)
3756 combinergb = GL_INTERPOLATE_ARB;
3757 if (unit->combine != GL_COMBINE_ARB)
3759 unit->combine = GL_COMBINE_ARB;
3760 GL_ActiveTexture(unitnum);
3761 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3762 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3764 if (unit->combinergb != combinergb)
3766 unit->combinergb = combinergb;
3767 GL_ActiveTexture(unitnum);
3768 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3770 if (unit->combinealpha != combinealpha)
3772 unit->combinealpha = combinealpha;
3773 GL_ActiveTexture(unitnum);
3774 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3776 if (unit->rgbscale != rgbscale)
3778 unit->rgbscale = rgbscale;
3779 GL_ActiveTexture(unitnum);
3780 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3782 if (unit->alphascale != alphascale)
3784 unit->alphascale = alphascale;
3785 GL_ActiveTexture(unitnum);
3786 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3791 if (unit->combine != combinergb)
3793 unit->combine = combinergb;
3794 GL_ActiveTexture(unitnum);
3795 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3799 case RENDERPATH_GL11:
3802 combinergb = GL_MODULATE;
3803 if (unit->combine != combinergb)
3805 unit->combine = combinergb;
3806 GL_ActiveTexture(unitnum);
3807 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3810 case RENDERPATH_D3D9:
3811 case RENDERPATH_D3D10:
3812 case RENDERPATH_D3D11:
3814 case RENDERPATH_SOFT:
3819 void R_Mesh_ResetTextureState(void)
3821 unsigned int unitnum;
3825 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3826 R_Mesh_TexBind(unitnum, NULL);
3827 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3828 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3829 switch(vid.renderpath)
3831 case RENDERPATH_GL20:
3832 case RENDERPATH_GLES2:
3833 case RENDERPATH_D3D9:
3834 case RENDERPATH_D3D10:
3835 case RENDERPATH_D3D11:
3836 case RENDERPATH_SOFT:
3838 case RENDERPATH_GL11:
3839 case RENDERPATH_GL13:
3840 case RENDERPATH_GLES1:
3841 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3843 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3844 R_Mesh_TexMatrix(unitnum, NULL);
3853 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3854 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3855 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3857 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3859 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3863 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3865 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3866 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3867 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3871 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3873 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3874 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3875 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3876 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3877 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3878 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3879 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3883 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3884 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3885 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3888 static void R_Mesh_InitVertexDeclarations(void)
3891 r_vertex3f_d3d9decl = NULL;
3892 r_vertexgeneric_d3d9decl = NULL;
3893 r_vertexmesh_d3d9decl = NULL;
3894 switch(vid.renderpath)
3896 case RENDERPATH_GL20:
3897 case RENDERPATH_GL13:
3898 case RENDERPATH_GL11:
3899 case RENDERPATH_GLES1:
3900 case RENDERPATH_GLES2:
3902 case RENDERPATH_D3D9:
3903 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3904 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3905 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3907 case RENDERPATH_D3D10:
3908 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3910 case RENDERPATH_D3D11:
3911 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3913 case RENDERPATH_SOFT:
3919 static void R_Mesh_DestroyVertexDeclarations(void)
3922 if (r_vertex3f_d3d9decl)
3923 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3924 r_vertex3f_d3d9decl = NULL;
3925 if (r_vertexgeneric_d3d9decl)
3926 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3927 r_vertexgeneric_d3d9decl = NULL;
3928 if (r_vertexmesh_d3d9decl)
3929 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3930 r_vertexmesh_d3d9decl = NULL;
3934 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3936 // upload temporary vertexbuffer for this rendering
3937 if (!gl_state.usevbo_staticvertex)
3938 vertexbuffer = NULL;
3939 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3941 if (gl_state.preparevertices_dynamicvertexbuffer)
3942 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3944 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3945 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3947 switch(vid.renderpath)
3949 case RENDERPATH_GL20:
3950 case RENDERPATH_GLES2:
3953 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3954 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3955 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3956 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3957 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3958 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3959 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3963 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3964 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3965 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3966 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3967 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3968 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3969 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3972 case RENDERPATH_GL13:
3973 case RENDERPATH_GLES1:
3976 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3977 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3978 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3979 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3983 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3984 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3985 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3986 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3989 case RENDERPATH_GL11:
3992 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3993 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3994 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3998 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3999 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
4000 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4003 case RENDERPATH_D3D9:
4005 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
4007 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
4009 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4010 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4011 gl_state.d3dvertexdata = (void *)vertex3f;
4012 gl_state.d3dvertexsize = sizeof(float[3]);
4015 case RENDERPATH_D3D10:
4016 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4018 case RENDERPATH_D3D11:
4019 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4021 case RENDERPATH_SOFT:
4022 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4023 DPSOFTRAST_SetColorPointer(NULL, 0);
4024 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
4025 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4026 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4027 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4028 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4035 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
4038 size = sizeof(r_vertexgeneric_t) * numvertices;
4039 if (gl_state.preparevertices_tempdatamaxsize < size)
4041 gl_state.preparevertices_tempdatamaxsize = size;
4042 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4044 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
4045 gl_state.preparevertices_numvertices = numvertices;
4046 return gl_state.preparevertices_vertexgeneric;
4049 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
4051 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4052 gl_state.preparevertices_vertexgeneric = NULL;
4053 gl_state.preparevertices_numvertices = 0;
4057 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4060 r_vertexgeneric_t *vertex;
4061 switch(vid.renderpath)
4063 case RENDERPATH_GL20:
4064 case RENDERPATH_GLES2:
4065 if (!vid.useinterleavedarrays)
4067 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4068 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4069 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4070 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4071 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4072 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4073 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4077 case RENDERPATH_GL11:
4078 case RENDERPATH_GL13:
4079 case RENDERPATH_GLES1:
4080 if (!vid.useinterleavedarrays)
4082 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4083 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4084 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4085 if (vid.texunits >= 2)
4086 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4087 if (vid.texunits >= 3)
4088 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4092 case RENDERPATH_D3D9:
4093 case RENDERPATH_D3D10:
4094 case RENDERPATH_D3D11:
4096 case RENDERPATH_SOFT:
4097 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4098 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4099 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4100 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4101 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4102 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4103 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4107 // no quick path for this case, convert to vertex structs
4108 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4109 for (i = 0;i < numvertices;i++)
4110 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4113 for (i = 0;i < numvertices;i++)
4114 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4118 for (i = 0;i < numvertices;i++)
4119 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4122 for (i = 0;i < numvertices;i++)
4123 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4124 R_Mesh_PrepareVertices_Generic_Unlock();
4125 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4128 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4130 // upload temporary vertexbuffer for this rendering
4131 if (!gl_state.usevbo_staticvertex)
4132 vertexbuffer = NULL;
4133 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4135 if (gl_state.preparevertices_dynamicvertexbuffer)
4136 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4138 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4139 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4141 switch(vid.renderpath)
4143 case RENDERPATH_GL20:
4144 case RENDERPATH_GLES2:
4147 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4148 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4149 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4150 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4151 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4152 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4153 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4157 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4158 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4159 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4160 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4161 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4162 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4163 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4166 case RENDERPATH_GL13:
4167 case RENDERPATH_GLES1:
4170 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4171 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4172 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4173 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4177 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4178 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4179 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4180 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4183 case RENDERPATH_GL11:
4186 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4187 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4188 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4192 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4193 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4194 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4197 case RENDERPATH_D3D9:
4199 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4201 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4203 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4204 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4205 gl_state.d3dvertexdata = (void *)vertex;
4206 gl_state.d3dvertexsize = sizeof(*vertex);
4209 case RENDERPATH_D3D10:
4210 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4212 case RENDERPATH_D3D11:
4213 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4215 case RENDERPATH_SOFT:
4216 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4217 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4218 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4219 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4220 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4221 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4222 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4229 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4232 size = sizeof(r_vertexmesh_t) * numvertices;
4233 if (gl_state.preparevertices_tempdatamaxsize < size)
4235 gl_state.preparevertices_tempdatamaxsize = size;
4236 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4238 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4239 gl_state.preparevertices_numvertices = numvertices;
4240 return gl_state.preparevertices_vertexmesh;
4243 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4245 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4246 gl_state.preparevertices_vertexmesh = NULL;
4247 gl_state.preparevertices_numvertices = 0;
4251 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)
4254 r_vertexmesh_t *vertex;
4255 switch(vid.renderpath)
4257 case RENDERPATH_GL20:
4258 case RENDERPATH_GLES2:
4259 if (!vid.useinterleavedarrays)
4261 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4262 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4263 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4264 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4265 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4266 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4267 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4271 case RENDERPATH_GL11:
4272 case RENDERPATH_GL13:
4273 case RENDERPATH_GLES1:
4274 if (!vid.useinterleavedarrays)
4276 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4277 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4278 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4279 if (vid.texunits >= 2)
4280 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4281 if (vid.texunits >= 3)
4282 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4286 case RENDERPATH_D3D9:
4287 case RENDERPATH_D3D10:
4288 case RENDERPATH_D3D11:
4290 case RENDERPATH_SOFT:
4291 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4292 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4293 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4294 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4295 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4296 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4297 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4301 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4302 for (i = 0;i < numvertices;i++)
4303 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4305 for (i = 0;i < numvertices;i++)
4306 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4308 for (i = 0;i < numvertices;i++)
4309 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4311 for (i = 0;i < numvertices;i++)
4312 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4315 for (i = 0;i < numvertices;i++)
4316 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4320 for (i = 0;i < numvertices;i++)
4321 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4323 if (texcoordtexture2f)
4324 for (i = 0;i < numvertices;i++)
4325 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4326 if (texcoordlightmap2f)
4327 for (i = 0;i < numvertices;i++)
4328 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4329 R_Mesh_PrepareVertices_Mesh_Unlock();
4330 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4333 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4335 // upload temporary vertexbuffer for this rendering
4336 if (!gl_state.usevbo_staticvertex)
4337 vertexbuffer = NULL;
4338 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4340 if (gl_state.preparevertices_dynamicvertexbuffer)
4341 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4343 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4344 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4346 switch(vid.renderpath)
4348 case RENDERPATH_GL20:
4349 case RENDERPATH_GLES2:
4352 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4353 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4354 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4355 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4356 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4357 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4358 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4362 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4363 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4364 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4365 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4366 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4367 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4368 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4371 case RENDERPATH_GL13:
4372 case RENDERPATH_GLES1:
4375 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4376 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4377 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4378 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4382 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4383 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4384 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4385 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4388 case RENDERPATH_GL11:
4391 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4392 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4393 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4397 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4398 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4399 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4402 case RENDERPATH_D3D9:
4404 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4406 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4408 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4409 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4410 gl_state.d3dvertexdata = (void *)vertex;
4411 gl_state.d3dvertexsize = sizeof(*vertex);
4414 case RENDERPATH_D3D10:
4415 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4417 case RENDERPATH_D3D11:
4418 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4420 case RENDERPATH_SOFT:
4421 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4422 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4423 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4424 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4425 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4426 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4427 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);