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_AlphaTest(int state)
2118 if (gl_state.alphatest != state)
2120 gl_state.alphatest = state;
2121 switch(vid.renderpath)
2123 case RENDERPATH_GL11:
2124 case RENDERPATH_GL13:
2125 case RENDERPATH_GLES1:
2126 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2128 if (gl_state.alphatest)
2130 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2134 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2137 case RENDERPATH_D3D9:
2138 case RENDERPATH_D3D10:
2139 case RENDERPATH_D3D11:
2140 case RENDERPATH_SOFT:
2141 case RENDERPATH_GL20:
2142 case RENDERPATH_GLES2:
2148 void GL_AlphaToCoverage(qboolean state)
2150 if (gl_state.alphatocoverage != state)
2152 gl_state.alphatocoverage = state;
2153 switch(vid.renderpath)
2155 case RENDERPATH_GL11:
2156 case RENDERPATH_GL13:
2157 case RENDERPATH_GLES1:
2158 case RENDERPATH_GLES2:
2159 case RENDERPATH_D3D9:
2160 case RENDERPATH_D3D10:
2161 case RENDERPATH_D3D11:
2162 case RENDERPATH_SOFT:
2164 case RENDERPATH_GL20:
2165 // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
2167 if (gl_state.alphatocoverage)
2169 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2170 // qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2174 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2175 // qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
2182 void GL_ColorMask(int r, int g, int b, int a)
2184 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2185 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2186 if (gl_state.colormask != state)
2188 gl_state.colormask = state;
2189 switch(vid.renderpath)
2191 case RENDERPATH_GL11:
2192 case RENDERPATH_GL13:
2193 case RENDERPATH_GL20:
2194 case RENDERPATH_GLES1:
2195 case RENDERPATH_GLES2:
2197 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2199 case RENDERPATH_D3D9:
2201 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2204 case RENDERPATH_D3D10:
2205 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2207 case RENDERPATH_D3D11:
2208 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2210 case RENDERPATH_SOFT:
2211 DPSOFTRAST_ColorMask(r, g, b, a);
2217 void GL_Color(float cr, float cg, float cb, float ca)
2219 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)
2221 gl_state.color4f[0] = cr;
2222 gl_state.color4f[1] = cg;
2223 gl_state.color4f[2] = cb;
2224 gl_state.color4f[3] = ca;
2225 switch(vid.renderpath)
2227 case RENDERPATH_GL11:
2228 case RENDERPATH_GL13:
2229 case RENDERPATH_GLES1:
2231 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2234 case RENDERPATH_D3D9:
2235 case RENDERPATH_D3D10:
2236 case RENDERPATH_D3D11:
2237 // no equivalent in D3D
2239 case RENDERPATH_SOFT:
2240 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2242 case RENDERPATH_GL20:
2243 case RENDERPATH_GLES2:
2244 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2250 void GL_Scissor (int x, int y, int width, int height)
2252 switch(vid.renderpath)
2254 case RENDERPATH_GL11:
2255 case RENDERPATH_GL13:
2256 case RENDERPATH_GL20:
2257 case RENDERPATH_GLES1:
2258 case RENDERPATH_GLES2:
2260 qglScissor(x, y,width,height);
2263 case RENDERPATH_D3D9:
2269 d3drect.right = x + width;
2270 d3drect.bottom = y + height;
2271 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2275 case RENDERPATH_D3D10:
2276 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2278 case RENDERPATH_D3D11:
2279 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2281 case RENDERPATH_SOFT:
2282 DPSOFTRAST_Scissor(x, y, width, height);
2287 void GL_ScissorTest(int state)
2289 if (gl_state.scissortest != state)
2291 gl_state.scissortest = state;
2292 switch(vid.renderpath)
2294 case RENDERPATH_GL11:
2295 case RENDERPATH_GL13:
2296 case RENDERPATH_GL20:
2297 case RENDERPATH_GLES1:
2298 case RENDERPATH_GLES2:
2300 if(gl_state.scissortest)
2301 qglEnable(GL_SCISSOR_TEST);
2303 qglDisable(GL_SCISSOR_TEST);
2306 case RENDERPATH_D3D9:
2308 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2311 case RENDERPATH_D3D10:
2312 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2314 case RENDERPATH_D3D11:
2315 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2317 case RENDERPATH_SOFT:
2318 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2324 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2326 static const float blackcolor[4] = {0, 0, 0, 0};
2327 // prevent warnings when trying to clear a buffer that does not exist
2329 colorvalue = blackcolor;
2332 mask &= ~GL_STENCIL_BUFFER_BIT;
2335 switch(vid.renderpath)
2337 case RENDERPATH_GL11:
2338 case RENDERPATH_GL13:
2339 case RENDERPATH_GL20:
2340 case RENDERPATH_GLES1:
2341 case RENDERPATH_GLES2:
2343 if (mask & GL_COLOR_BUFFER_BIT)
2345 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2347 if (mask & GL_DEPTH_BUFFER_BIT)
2349 qglClearDepth(depthvalue);CHECKGLERROR
2351 if (mask & GL_STENCIL_BUFFER_BIT)
2353 qglClearStencil(stencilvalue);CHECKGLERROR
2355 qglClear(mask);CHECKGLERROR
2357 case RENDERPATH_D3D9:
2359 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);
2362 case RENDERPATH_D3D10:
2363 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2365 case RENDERPATH_D3D11:
2366 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2368 case RENDERPATH_SOFT:
2369 if (mask & GL_COLOR_BUFFER_BIT)
2370 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2371 if (mask & GL_DEPTH_BUFFER_BIT)
2372 DPSOFTRAST_ClearDepth(depthvalue);
2377 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2379 switch(vid.renderpath)
2381 case RENDERPATH_GL11:
2382 case RENDERPATH_GL13:
2383 case RENDERPATH_GL20:
2384 case RENDERPATH_GLES1:
2385 case RENDERPATH_GLES2:
2387 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2389 case RENDERPATH_D3D9:
2392 // LordHavoc: we can't directly download the backbuffer because it may be
2393 // multisampled, and it may not be lockable, so we blit it to a lockable
2394 // surface of the same dimensions (but without multisample) to resolve the
2395 // multisample buffer to a normal image, and then lock that...
2396 IDirect3DSurface9 *stretchsurface = NULL;
2397 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2399 D3DLOCKED_RECT lockedrect;
2400 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2402 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2405 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2406 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2407 memcpy(outpixels + line * width * 4, row, width * 4);
2408 IDirect3DSurface9_UnlockRect(stretchsurface);
2411 IDirect3DSurface9_Release(stretchsurface);
2414 //IDirect3DSurface9 *syssurface = NULL;
2415 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2416 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2417 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2418 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2419 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2420 //IDirect3DSurface9_UnlockRect(syssurface);
2421 //IDirect3DSurface9_Release(syssurface);
2425 case RENDERPATH_D3D10:
2426 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2428 case RENDERPATH_D3D11:
2429 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2431 case RENDERPATH_SOFT:
2432 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2437 // called at beginning of frame
2438 void R_Mesh_Start(void)
2441 R_Mesh_ResetRenderTargets();
2443 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2445 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2446 Cvar_SetValueQuick(&gl_paranoid, 1);
2450 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2454 char compilelog[MAX_INPUTLINE];
2455 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2458 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2459 qglCompileShader(shaderobject);CHECKGLERROR
2460 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2461 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2462 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2464 int i, j, pretextlines = 0;
2465 for (i = 0;i < numstrings - 1;i++)
2466 for (j = 0;strings[i][j];j++)
2467 if (strings[i][j] == '\n')
2469 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2471 if (!shadercompiled)
2473 qglDeleteShader(shaderobject);CHECKGLERROR
2476 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2477 qglDeleteShader(shaderobject);CHECKGLERROR
2481 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)
2483 GLint programlinked;
2484 GLuint programobject = 0;
2485 char linklog[MAX_INPUTLINE];
2488 programobject = qglCreateProgram();CHECKGLERROR
2492 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2493 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2494 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2495 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2496 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2497 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2498 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2499 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2500 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2501 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2502 if(vid.support.gl20shaders130)
2503 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2505 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2508 #ifdef GL_GEOMETRY_SHADER
2509 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2513 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2516 qglLinkProgram(programobject);CHECKGLERROR
2517 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2518 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2521 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2522 Con_DPrintf("program link log:\n%s\n", linklog);
2523 // software vertex shader is ok but software fragment shader is WAY
2524 // too slow, fail program if so.
2525 // NOTE: this string might be ATI specific, but that's ok because the
2526 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2527 // software fragment shader due to low instruction and dependent
2529 if (strstr(linklog, "fragment shader will run in software"))
2530 programlinked = false;
2534 return programobject;
2536 qglDeleteProgram(programobject);CHECKGLERROR
2540 void GL_Backend_FreeProgram(unsigned int prog)
2543 qglDeleteProgram(prog);
2547 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2552 for (i = 0;i < count;i++)
2553 *out++ = *in++ + offset;
2556 memcpy(out, in, sizeof(*out) * count);
2559 // renders triangles using vertices from the active arrays
2560 int paranoidblah = 0;
2561 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)
2563 unsigned int numelements = numtriangles * 3;
2565 size_t bufferoffset3i;
2567 size_t bufferoffset3s;
2568 if (numvertices < 3 || numtriangles < 1)
2570 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2571 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);
2574 if (!gl_mesh_prefer_short_elements.integer)
2578 if (element3i_indexbuffer)
2579 element3i_indexbuffer = NULL;
2581 // adjust the pointers for firsttriangle
2583 element3i += firsttriangle * 3;
2584 if (element3i_indexbuffer)
2585 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2587 element3s += firsttriangle * 3;
2588 if (element3s_indexbuffer)
2589 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2590 switch(vid.renderpath)
2592 case RENDERPATH_GL11:
2593 case RENDERPATH_GL13:
2594 case RENDERPATH_GL20:
2595 case RENDERPATH_GLES1:
2596 case RENDERPATH_GLES2:
2597 // check if the user specified to ignore static index buffers
2598 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2600 element3i_indexbuffer = NULL;
2601 element3s_indexbuffer = NULL;
2604 case RENDERPATH_D3D9:
2605 case RENDERPATH_D3D10:
2606 case RENDERPATH_D3D11:
2608 case RENDERPATH_SOFT:
2611 // upload a dynamic index buffer if needed
2614 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2616 if (gl_state.draw_dynamicindexbuffer)
2617 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2619 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2620 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2621 element3s_bufferoffset = 0;
2626 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2628 if (gl_state.draw_dynamicindexbuffer)
2629 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2631 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2632 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2633 element3i_bufferoffset = 0;
2636 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2637 bufferoffset3i = element3i_bufferoffset;
2638 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2639 bufferoffset3s = element3s_bufferoffset;
2640 r_refdef.stats.draws++;
2641 r_refdef.stats.draws_vertices += numvertices;
2642 r_refdef.stats.draws_elements += numelements;
2643 if (gl_paranoid.integer)
2646 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2648 unsigned int j, size;
2650 // note: there's no validation done here on buffer objects because it
2651 // is somewhat difficult to get at the data, and gl_paranoid can be
2652 // used without buffer objects if the need arises
2653 // (the data could be gotten using glMapBuffer but it would be very
2654 // slow due to uncachable video memory reads)
2655 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2656 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2658 if (gl_state.pointer_vertex_pointer)
2659 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2661 if (gl_state.pointer_color_enabled)
2663 if (!qglIsEnabled(GL_COLOR_ARRAY))
2664 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2666 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2667 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2670 for (i = 0;i < vid.texarrayunits;i++)
2672 if (gl_state.units[i].arrayenabled)
2674 GL_ClientActiveTexture(i);
2675 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2676 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2678 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2679 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++)
2686 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2688 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2690 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2697 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2699 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2701 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2707 if (r_render.integer || r_refdef.draw2dstage)
2709 switch(vid.renderpath)
2711 case RENDERPATH_GL11:
2712 case RENDERPATH_GL13:
2713 case RENDERPATH_GL20:
2715 if (gl_mesh_testmanualfeeding.integer)
2717 unsigned int i, j, element;
2719 qglBegin(GL_TRIANGLES);
2720 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2723 element = element3i[i];
2725 element = element3s[i];
2727 element = firstvertex + i;
2728 for (j = 0;j < vid.texarrayunits;j++)
2730 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2732 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2734 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2735 if (vid.texarrayunits > 1)
2737 if (gl_state.units[j].pointer_texcoord_components == 4)
2738 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2739 else if (gl_state.units[j].pointer_texcoord_components == 3)
2740 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2741 else if (gl_state.units[j].pointer_texcoord_components == 2)
2742 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2744 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2748 if (gl_state.units[j].pointer_texcoord_components == 4)
2749 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2750 else if (gl_state.units[j].pointer_texcoord_components == 3)
2751 qglTexCoord3f(p[0], p[1], p[2]);
2752 else if (gl_state.units[j].pointer_texcoord_components == 2)
2753 qglTexCoord2f(p[0], p[1]);
2755 qglTexCoord1f(p[0]);
2758 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2760 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2761 if (vid.texarrayunits > 1)
2763 if (gl_state.units[j].pointer_texcoord_components == 4)
2764 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2765 else if (gl_state.units[j].pointer_texcoord_components == 3)
2766 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2767 else if (gl_state.units[j].pointer_texcoord_components == 2)
2768 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2769 else if (gl_state.units[j].pointer_texcoord_components == 1)
2770 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2774 if (gl_state.units[j].pointer_texcoord_components == 4)
2775 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2776 else if (gl_state.units[j].pointer_texcoord_components == 3)
2777 qglTexCoord3f(s[0], s[1], s[2]);
2778 else if (gl_state.units[j].pointer_texcoord_components == 2)
2779 qglTexCoord2f(s[0], s[1]);
2780 else if (gl_state.units[j].pointer_texcoord_components == 1)
2781 qglTexCoord1f(s[0]);
2784 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2786 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2787 if (vid.texarrayunits > 1)
2789 if (gl_state.units[j].pointer_texcoord_components == 4)
2790 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2791 else if (gl_state.units[j].pointer_texcoord_components == 3)
2792 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2793 else if (gl_state.units[j].pointer_texcoord_components == 2)
2794 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2795 else if (gl_state.units[j].pointer_texcoord_components == 1)
2796 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2800 if (gl_state.units[j].pointer_texcoord_components == 4)
2801 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2802 else if (gl_state.units[j].pointer_texcoord_components == 3)
2803 qglTexCoord3f(sb[0], sb[1], sb[2]);
2804 else if (gl_state.units[j].pointer_texcoord_components == 2)
2805 qglTexCoord2f(sb[0], sb[1]);
2806 else if (gl_state.units[j].pointer_texcoord_components == 1)
2807 qglTexCoord1f(sb[0]);
2812 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2814 if (gl_state.pointer_color_gltype == GL_FLOAT)
2816 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2817 qglColor4f(p[0], p[1], p[2], p[3]);
2819 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2821 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2822 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2825 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2827 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2828 if (gl_state.pointer_vertex_components == 4)
2829 qglVertex4f(p[0], p[1], p[2], p[3]);
2830 else if (gl_state.pointer_vertex_components == 3)
2831 qglVertex3f(p[0], p[1], p[2]);
2833 qglVertex2f(p[0], p[1]);
2839 else if (bufferobject3s)
2841 GL_BindEBO(bufferobject3s);
2842 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2844 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2849 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2853 else if (bufferobject3i)
2855 GL_BindEBO(bufferobject3i);
2856 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2858 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2863 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2870 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2872 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2877 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2884 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2886 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2891 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2897 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2901 case RENDERPATH_D3D9:
2903 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2905 if (element3s_indexbuffer)
2907 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2908 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2910 else if (element3i_indexbuffer)
2912 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2913 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2916 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2921 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2923 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2925 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2929 case RENDERPATH_D3D10:
2930 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2932 case RENDERPATH_D3D11:
2933 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2935 case RENDERPATH_SOFT:
2936 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2938 case RENDERPATH_GLES1:
2939 case RENDERPATH_GLES2:
2940 // GLES does not have glDrawRangeElements, and generally
2941 // underperforms with index buffers, so this code path is
2942 // relatively straightforward...
2944 if (gl_paranoid.integer)
2946 int r, prog, enabled, i;
2947 GLsizei attriblength;
2950 GLchar attribname[1024];
2951 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2952 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2953 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2954 #ifndef GL_CURRENT_PROGRAM
2955 #define GL_CURRENT_PROGRAM 0x8B8D
2957 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2958 if (r < 0 || r > 10000)
2959 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2961 for (i = 0;i < 8;i++)
2963 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2966 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2967 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);
2973 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2978 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2983 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2991 // restores backend state, used when done with 3D rendering
2992 void R_Mesh_Finish(void)
2994 R_Mesh_ResetRenderTargets();
2997 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2999 r_meshbuffer_t *buffer;
3000 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
3002 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
3003 memset(buffer, 0, sizeof(*buffer));
3004 buffer->bufferobject = 0;
3005 buffer->devicebuffer = NULL;
3007 buffer->isindexbuffer = isindexbuffer;
3008 buffer->isdynamic = isdynamic;
3009 buffer->isindex16 = isindex16;
3010 strlcpy(buffer->name, name, sizeof(buffer->name));
3011 R_Mesh_UpdateMeshBuffer(buffer, data, size);
3015 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
3019 if (buffer->isindexbuffer)
3021 r_refdef.stats.indexbufferuploadcount++;
3022 r_refdef.stats.indexbufferuploadsize += size;
3026 r_refdef.stats.vertexbufferuploadcount++;
3027 r_refdef.stats.vertexbufferuploadsize += size;
3029 switch(vid.renderpath)
3031 case RENDERPATH_GL11:
3032 case RENDERPATH_GL13:
3033 case RENDERPATH_GL20:
3034 case RENDERPATH_GLES1:
3035 case RENDERPATH_GLES2:
3036 if (!buffer->bufferobject)
3037 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3038 if (buffer->isindexbuffer)
3039 GL_BindEBO(buffer->bufferobject);
3041 GL_BindVBO(buffer->bufferobject);
3042 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
3044 case RENDERPATH_D3D9:
3048 void *datapointer = NULL;
3049 if (buffer->isindexbuffer)
3051 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3052 if (size > buffer->size || !buffer->devicebuffer)
3054 if (buffer->devicebuffer)
3055 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3056 buffer->devicebuffer = NULL;
3057 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)))
3058 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);
3059 buffer->devicebuffer = (void *)d3d9indexbuffer;
3060 buffer->size = size;
3062 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3065 memcpy(datapointer, data, size);
3067 memset(datapointer, 0, size);
3068 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3073 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3074 if (size > buffer->size || !buffer->devicebuffer)
3076 if (buffer->devicebuffer)
3077 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3078 buffer->devicebuffer = NULL;
3079 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3080 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);
3081 buffer->devicebuffer = (void *)d3d9vertexbuffer;
3082 buffer->size = size;
3084 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3087 memcpy(datapointer, data, size);
3089 memset(datapointer, 0, size);
3090 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3096 case RENDERPATH_D3D10:
3097 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3099 case RENDERPATH_D3D11:
3100 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3102 case RENDERPATH_SOFT:
3107 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3111 switch(vid.renderpath)
3113 case RENDERPATH_GL11:
3114 case RENDERPATH_GL13:
3115 case RENDERPATH_GL20:
3116 case RENDERPATH_GLES1:
3117 case RENDERPATH_GLES2:
3118 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3120 case RENDERPATH_D3D9:
3122 if (gl_state.d3dvertexbuffer == (void *)buffer)
3123 gl_state.d3dvertexbuffer = NULL;
3124 if (buffer->devicebuffer)
3126 if (buffer->isindexbuffer)
3127 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3129 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3130 buffer->devicebuffer = NULL;
3134 case RENDERPATH_D3D10:
3135 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3137 case RENDERPATH_D3D11:
3138 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3140 case RENDERPATH_SOFT:
3143 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3146 void GL_Mesh_ListVBOs(qboolean printeach)
3149 size_t ebocount = 0, ebomemory = 0;
3150 size_t vbocount = 0, vbomemory = 0;
3151 r_meshbuffer_t *buffer;
3152 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3153 for (i = 0;i < endindex;i++)
3155 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3158 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)");}
3159 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)");}
3161 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);
3166 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3168 switch(vid.renderpath)
3170 case RENDERPATH_GL11:
3171 case RENDERPATH_GL13:
3172 case RENDERPATH_GLES1:
3173 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)
3175 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3176 gl_state.pointer_vertex_components = components;
3177 gl_state.pointer_vertex_gltype = gltype;
3178 gl_state.pointer_vertex_stride = stride;
3179 gl_state.pointer_vertex_pointer = pointer;
3180 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3181 gl_state.pointer_vertex_offset = bufferoffset;
3183 GL_BindVBO(bufferobject);
3184 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3187 case RENDERPATH_GL20:
3188 case RENDERPATH_GLES2:
3189 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)
3191 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3192 gl_state.pointer_vertex_components = components;
3193 gl_state.pointer_vertex_gltype = gltype;
3194 gl_state.pointer_vertex_stride = stride;
3195 gl_state.pointer_vertex_pointer = pointer;
3196 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3197 gl_state.pointer_vertex_offset = bufferoffset;
3199 GL_BindVBO(bufferobject);
3200 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3203 case RENDERPATH_D3D9:
3204 case RENDERPATH_D3D10:
3205 case RENDERPATH_D3D11:
3206 case RENDERPATH_SOFT:
3211 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3213 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3214 // the pointer only.
3215 switch(vid.renderpath)
3217 case RENDERPATH_GL11:
3218 case RENDERPATH_GL13:
3219 case RENDERPATH_GLES1:
3223 // caller wants color array enabled
3224 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3225 if (!gl_state.pointer_color_enabled)
3227 gl_state.pointer_color_enabled = true;
3229 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3231 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)
3233 gl_state.pointer_color_components = components;
3234 gl_state.pointer_color_gltype = gltype;
3235 gl_state.pointer_color_stride = stride;
3236 gl_state.pointer_color_pointer = pointer;
3237 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3238 gl_state.pointer_color_offset = bufferoffset;
3240 GL_BindVBO(bufferobject);
3241 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3246 // caller wants color array disabled
3247 if (gl_state.pointer_color_enabled)
3249 gl_state.pointer_color_enabled = false;
3251 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3252 // when color array is on the glColor gets trashed, set it again
3253 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3257 case RENDERPATH_GL20:
3258 case RENDERPATH_GLES2:
3262 // caller wants color array enabled
3263 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3264 if (!gl_state.pointer_color_enabled)
3266 gl_state.pointer_color_enabled = true;
3268 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3270 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)
3272 gl_state.pointer_color_components = components;
3273 gl_state.pointer_color_gltype = gltype;
3274 gl_state.pointer_color_stride = stride;
3275 gl_state.pointer_color_pointer = pointer;
3276 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3277 gl_state.pointer_color_offset = bufferoffset;
3279 GL_BindVBO(bufferobject);
3280 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3285 // caller wants color array disabled
3286 if (gl_state.pointer_color_enabled)
3288 gl_state.pointer_color_enabled = false;
3290 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3291 // when color array is on the glColor gets trashed, set it again
3292 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3296 case RENDERPATH_D3D9:
3297 case RENDERPATH_D3D10:
3298 case RENDERPATH_D3D11:
3299 case RENDERPATH_SOFT:
3304 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)
3306 gltextureunit_t *unit = gl_state.units + unitnum;
3307 // update array settings
3308 // note: there is no need to check bufferobject here because all cases
3309 // that involve a valid bufferobject also supply a texcoord array
3310 switch(vid.renderpath)
3312 case RENDERPATH_GL11:
3313 case RENDERPATH_GL13:
3314 case RENDERPATH_GLES1:
3318 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3319 // texture array unit is enabled, enable the array
3320 if (!unit->arrayenabled)
3322 unit->arrayenabled = true;
3323 GL_ClientActiveTexture(unitnum);
3324 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3327 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)
3329 unit->pointer_texcoord_components = components;
3330 unit->pointer_texcoord_gltype = gltype;
3331 unit->pointer_texcoord_stride = stride;
3332 unit->pointer_texcoord_pointer = pointer;
3333 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3334 unit->pointer_texcoord_offset = bufferoffset;
3335 GL_ClientActiveTexture(unitnum);
3336 GL_BindVBO(bufferobject);
3337 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3342 // texture array unit is disabled, disable the array
3343 if (unit->arrayenabled)
3345 unit->arrayenabled = false;
3346 GL_ClientActiveTexture(unitnum);
3347 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3351 case RENDERPATH_GL20:
3352 case RENDERPATH_GLES2:
3356 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3357 // texture array unit is enabled, enable the array
3358 if (!unit->arrayenabled)
3360 unit->arrayenabled = true;
3361 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3364 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)
3366 unit->pointer_texcoord_components = components;
3367 unit->pointer_texcoord_gltype = gltype;
3368 unit->pointer_texcoord_stride = stride;
3369 unit->pointer_texcoord_pointer = pointer;
3370 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3371 unit->pointer_texcoord_offset = bufferoffset;
3372 GL_BindVBO(bufferobject);
3373 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3378 // texture array unit is disabled, disable the array
3379 if (unit->arrayenabled)
3381 unit->arrayenabled = false;
3382 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3386 case RENDERPATH_D3D9:
3387 case RENDERPATH_D3D10:
3388 case RENDERPATH_D3D11:
3389 case RENDERPATH_SOFT:
3394 int R_Mesh_TexBound(unsigned int unitnum, int id)
3396 gltextureunit_t *unit = gl_state.units + unitnum;
3397 if (unitnum >= vid.teximageunits)
3399 if (id == GL_TEXTURE_2D)
3401 if (id == GL_TEXTURE_3D)
3403 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3404 return unit->tcubemap;
3408 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3410 switch(vid.renderpath)
3412 case RENDERPATH_GL11:
3413 case RENDERPATH_GL13:
3414 case RENDERPATH_GL20:
3415 case RENDERPATH_GLES1:
3416 case RENDERPATH_GLES2:
3417 R_Mesh_TexBind(0, tex);
3418 GL_ActiveTexture(0);CHECKGLERROR
3419 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3421 case RENDERPATH_D3D9:
3424 IDirect3DSurface9 *currentsurface = NULL;
3425 IDirect3DSurface9 *texturesurface = NULL;
3428 sourcerect.left = sx;
3429 sourcerect.top = sy;
3430 sourcerect.right = sx + width;
3431 sourcerect.bottom = sy + height;
3434 destrect.right = tx + width;
3435 destrect.bottom = ty + height;
3436 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3438 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3440 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3441 IDirect3DSurface9_Release(currentsurface);
3443 IDirect3DSurface9_Release(texturesurface);
3448 case RENDERPATH_D3D10:
3449 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3451 case RENDERPATH_D3D11:
3452 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3454 case RENDERPATH_SOFT:
3455 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3461 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};
3464 void R_Mesh_ClearBindingsForTexture(int texnum)
3466 gltextureunit_t *unit;
3467 unsigned int unitnum;
3468 // 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)
3469 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3471 unit = gl_state.units + unitnum;
3472 if (unit->t2d == texnum)
3474 if (unit->t3d == texnum)
3476 if (unit->tcubemap == texnum)
3477 unit->tcubemap = -1;
3481 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3483 gltextureunit_t *unit = gl_state.units + unitnum;
3484 int tex2d, tex3d, texcubemap, texnum;
3485 if (unitnum >= vid.teximageunits)
3487 // if (unit->texture == tex)
3489 switch(vid.renderpath)
3491 case RENDERPATH_GL20:
3492 case RENDERPATH_GLES2:
3495 tex = r_texture_white;
3496 // not initialized enough yet...
3500 unit->texture = tex;
3501 texnum = R_GetTexture(tex);
3502 switch(tex->gltexturetypeenum)
3504 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3505 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3506 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;
3509 case RENDERPATH_GL11:
3510 case RENDERPATH_GL13:
3511 case RENDERPATH_GLES1:
3512 unit->texture = tex;
3518 texnum = R_GetTexture(tex);
3519 switch(tex->gltexturetypeenum)
3527 case GL_TEXTURE_CUBE_MAP_ARB:
3528 texcubemap = texnum;
3532 // update 2d texture binding
3533 if (unit->t2d != tex2d)
3535 GL_ActiveTexture(unitnum);
3540 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3547 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3551 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3553 // update 3d texture binding
3554 if (unit->t3d != tex3d)
3556 GL_ActiveTexture(unitnum);
3561 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3568 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3572 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3574 // update cubemap texture binding
3575 if (unit->tcubemap != texcubemap)
3577 GL_ActiveTexture(unitnum);
3580 if (unit->tcubemap == 0)
3582 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3589 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3592 unit->tcubemap = texcubemap;
3593 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3596 case RENDERPATH_D3D9:
3599 extern cvar_t gl_texture_anisotropy;
3602 tex = r_texture_white;
3603 // not initialized enough yet...
3607 // upload texture if needed
3609 if (unit->texture == tex)
3611 unit->texture = tex;
3612 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3613 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3614 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3615 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3616 if (tex->d3daddressw)
3617 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3618 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3619 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3620 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3621 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3622 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3623 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3627 case RENDERPATH_D3D10:
3628 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3630 case RENDERPATH_D3D11:
3631 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3633 case RENDERPATH_SOFT:
3636 tex = r_texture_white;
3637 // not initialized enough yet...
3641 texnum = R_GetTexture(tex);
3642 if (unit->texture == tex)
3644 unit->texture = tex;
3645 DPSOFTRAST_SetTexture(unitnum, texnum);
3650 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3652 gltextureunit_t *unit = gl_state.units + unitnum;
3653 switch(vid.renderpath)
3655 case RENDERPATH_GL11:
3656 case RENDERPATH_GL13:
3657 case RENDERPATH_GL20:
3658 case RENDERPATH_GLES1:
3659 case RENDERPATH_GLES2:
3660 if (matrix && matrix->m[3][3])
3662 // texmatrix specified, check if it is different
3663 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3666 unit->texmatrixenabled = true;
3667 unit->matrix = *matrix;
3669 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3670 GL_ActiveTexture(unitnum);
3671 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3672 qglLoadMatrixf(glmatrix);CHECKGLERROR
3673 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3678 // no texmatrix specified, revert to identity
3679 if (unit->texmatrixenabled)
3681 unit->texmatrixenabled = false;
3682 unit->matrix = identitymatrix;
3684 GL_ActiveTexture(unitnum);
3685 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3686 qglLoadIdentity();CHECKGLERROR
3687 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3691 case RENDERPATH_D3D9:
3692 case RENDERPATH_D3D10:
3693 case RENDERPATH_D3D11:
3695 case RENDERPATH_SOFT:
3700 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3702 gltextureunit_t *unit = gl_state.units + unitnum;
3704 switch(vid.renderpath)
3706 case RENDERPATH_GL20:
3707 case RENDERPATH_GLES2:
3710 case RENDERPATH_GL13:
3711 case RENDERPATH_GLES1:
3712 // GL_ARB_texture_env_combine
3714 combinergb = GL_MODULATE;
3716 combinealpha = GL_MODULATE;
3721 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3723 if (combinergb == GL_DECAL)
3724 combinergb = GL_INTERPOLATE_ARB;
3725 if (unit->combine != GL_COMBINE_ARB)
3727 unit->combine = GL_COMBINE_ARB;
3728 GL_ActiveTexture(unitnum);
3729 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3730 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3732 if (unit->combinergb != combinergb)
3734 unit->combinergb = combinergb;
3735 GL_ActiveTexture(unitnum);
3736 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3738 if (unit->combinealpha != combinealpha)
3740 unit->combinealpha = combinealpha;
3741 GL_ActiveTexture(unitnum);
3742 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3744 if (unit->rgbscale != rgbscale)
3746 unit->rgbscale = rgbscale;
3747 GL_ActiveTexture(unitnum);
3748 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3750 if (unit->alphascale != alphascale)
3752 unit->alphascale = alphascale;
3753 GL_ActiveTexture(unitnum);
3754 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3759 if (unit->combine != combinergb)
3761 unit->combine = combinergb;
3762 GL_ActiveTexture(unitnum);
3763 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3767 case RENDERPATH_GL11:
3770 combinergb = GL_MODULATE;
3771 if (unit->combine != combinergb)
3773 unit->combine = combinergb;
3774 GL_ActiveTexture(unitnum);
3775 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3778 case RENDERPATH_D3D9:
3779 case RENDERPATH_D3D10:
3780 case RENDERPATH_D3D11:
3782 case RENDERPATH_SOFT:
3787 void R_Mesh_ResetTextureState(void)
3789 unsigned int unitnum;
3793 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3794 R_Mesh_TexBind(unitnum, NULL);
3795 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3796 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3797 switch(vid.renderpath)
3799 case RENDERPATH_GL20:
3800 case RENDERPATH_GLES2:
3801 case RENDERPATH_D3D9:
3802 case RENDERPATH_D3D10:
3803 case RENDERPATH_D3D11:
3804 case RENDERPATH_SOFT:
3806 case RENDERPATH_GL11:
3807 case RENDERPATH_GL13:
3808 case RENDERPATH_GLES1:
3809 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3811 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3812 R_Mesh_TexMatrix(unitnum, NULL);
3821 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3822 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3823 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3825 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3827 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3831 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3833 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3834 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3835 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3839 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3841 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3842 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3843 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3844 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3845 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3846 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3847 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3851 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3852 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3853 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3856 static void R_Mesh_InitVertexDeclarations(void)
3859 r_vertex3f_d3d9decl = NULL;
3860 r_vertexgeneric_d3d9decl = NULL;
3861 r_vertexmesh_d3d9decl = NULL;
3862 switch(vid.renderpath)
3864 case RENDERPATH_GL20:
3865 case RENDERPATH_GL13:
3866 case RENDERPATH_GL11:
3867 case RENDERPATH_GLES1:
3868 case RENDERPATH_GLES2:
3870 case RENDERPATH_D3D9:
3871 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3872 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3873 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3875 case RENDERPATH_D3D10:
3876 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3878 case RENDERPATH_D3D11:
3879 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3881 case RENDERPATH_SOFT:
3887 static void R_Mesh_DestroyVertexDeclarations(void)
3890 if (r_vertex3f_d3d9decl)
3891 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3892 r_vertex3f_d3d9decl = NULL;
3893 if (r_vertexgeneric_d3d9decl)
3894 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3895 r_vertexgeneric_d3d9decl = NULL;
3896 if (r_vertexmesh_d3d9decl)
3897 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3898 r_vertexmesh_d3d9decl = NULL;
3902 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3904 // upload temporary vertexbuffer for this rendering
3905 if (!gl_state.usevbo_staticvertex)
3906 vertexbuffer = NULL;
3907 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3909 if (gl_state.preparevertices_dynamicvertexbuffer)
3910 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3912 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3913 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3915 switch(vid.renderpath)
3917 case RENDERPATH_GL20:
3918 case RENDERPATH_GLES2:
3921 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3922 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3923 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3924 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3925 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3926 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3927 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3931 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3932 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3933 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3934 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3935 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3936 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3937 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3940 case RENDERPATH_GL13:
3941 case RENDERPATH_GLES1:
3944 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3945 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3946 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3947 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3951 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3952 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3953 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3954 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3957 case RENDERPATH_GL11:
3960 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3961 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3962 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3966 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3967 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3968 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3971 case RENDERPATH_D3D9:
3973 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3975 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3977 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3978 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3979 gl_state.d3dvertexdata = (void *)vertex3f;
3980 gl_state.d3dvertexsize = sizeof(float[3]);
3983 case RENDERPATH_D3D10:
3984 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3986 case RENDERPATH_D3D11:
3987 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3989 case RENDERPATH_SOFT:
3990 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3991 DPSOFTRAST_SetColorPointer(NULL, 0);
3992 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3993 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3994 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3995 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3996 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4003 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
4006 size = sizeof(r_vertexgeneric_t) * numvertices;
4007 if (gl_state.preparevertices_tempdatamaxsize < size)
4009 gl_state.preparevertices_tempdatamaxsize = size;
4010 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4012 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
4013 gl_state.preparevertices_numvertices = numvertices;
4014 return gl_state.preparevertices_vertexgeneric;
4017 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
4019 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4020 gl_state.preparevertices_vertexgeneric = NULL;
4021 gl_state.preparevertices_numvertices = 0;
4025 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4028 r_vertexgeneric_t *vertex;
4029 switch(vid.renderpath)
4031 case RENDERPATH_GL20:
4032 case RENDERPATH_GLES2:
4033 if (!vid.useinterleavedarrays)
4035 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4036 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4037 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4038 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4039 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4040 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4041 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4045 case RENDERPATH_GL11:
4046 case RENDERPATH_GL13:
4047 case RENDERPATH_GLES1:
4048 if (!vid.useinterleavedarrays)
4050 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4051 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4052 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4053 if (vid.texunits >= 2)
4054 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4055 if (vid.texunits >= 3)
4056 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4060 case RENDERPATH_D3D9:
4061 case RENDERPATH_D3D10:
4062 case RENDERPATH_D3D11:
4064 case RENDERPATH_SOFT:
4065 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4066 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4067 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4068 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4069 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4070 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4071 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4075 // no quick path for this case, convert to vertex structs
4076 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4077 for (i = 0;i < numvertices;i++)
4078 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4081 for (i = 0;i < numvertices;i++)
4082 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4086 for (i = 0;i < numvertices;i++)
4087 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4090 for (i = 0;i < numvertices;i++)
4091 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4092 R_Mesh_PrepareVertices_Generic_Unlock();
4093 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4096 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4098 // upload temporary vertexbuffer for this rendering
4099 if (!gl_state.usevbo_staticvertex)
4100 vertexbuffer = NULL;
4101 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4103 if (gl_state.preparevertices_dynamicvertexbuffer)
4104 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4106 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4107 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4109 switch(vid.renderpath)
4111 case RENDERPATH_GL20:
4112 case RENDERPATH_GLES2:
4115 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4116 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4117 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4118 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4119 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4120 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4121 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4125 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4126 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4127 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4128 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4129 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4130 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4131 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4134 case RENDERPATH_GL13:
4135 case RENDERPATH_GLES1:
4138 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4139 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4140 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4141 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4145 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4146 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4147 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4148 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4151 case RENDERPATH_GL11:
4154 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4155 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4156 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4160 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4161 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4162 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4165 case RENDERPATH_D3D9:
4167 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4169 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4171 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4172 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4173 gl_state.d3dvertexdata = (void *)vertex;
4174 gl_state.d3dvertexsize = sizeof(*vertex);
4177 case RENDERPATH_D3D10:
4178 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4180 case RENDERPATH_D3D11:
4181 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4183 case RENDERPATH_SOFT:
4184 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4185 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4186 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4187 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4188 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4189 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4190 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4197 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4200 size = sizeof(r_vertexmesh_t) * numvertices;
4201 if (gl_state.preparevertices_tempdatamaxsize < size)
4203 gl_state.preparevertices_tempdatamaxsize = size;
4204 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4206 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4207 gl_state.preparevertices_numvertices = numvertices;
4208 return gl_state.preparevertices_vertexmesh;
4211 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4213 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4214 gl_state.preparevertices_vertexmesh = NULL;
4215 gl_state.preparevertices_numvertices = 0;
4219 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)
4222 r_vertexmesh_t *vertex;
4223 switch(vid.renderpath)
4225 case RENDERPATH_GL20:
4226 case RENDERPATH_GLES2:
4227 if (!vid.useinterleavedarrays)
4229 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4230 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4231 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4232 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4233 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4234 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4235 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4239 case RENDERPATH_GL11:
4240 case RENDERPATH_GL13:
4241 case RENDERPATH_GLES1:
4242 if (!vid.useinterleavedarrays)
4244 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4245 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4246 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4247 if (vid.texunits >= 2)
4248 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4249 if (vid.texunits >= 3)
4250 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4254 case RENDERPATH_D3D9:
4255 case RENDERPATH_D3D10:
4256 case RENDERPATH_D3D11:
4258 case RENDERPATH_SOFT:
4259 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4260 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4261 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4262 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4263 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4264 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4265 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4269 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4270 for (i = 0;i < numvertices;i++)
4271 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4273 for (i = 0;i < numvertices;i++)
4274 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4276 for (i = 0;i < numvertices;i++)
4277 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4279 for (i = 0;i < numvertices;i++)
4280 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4283 for (i = 0;i < numvertices;i++)
4284 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4288 for (i = 0;i < numvertices;i++)
4289 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4291 if (texcoordtexture2f)
4292 for (i = 0;i < numvertices;i++)
4293 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4294 if (texcoordlightmap2f)
4295 for (i = 0;i < numvertices;i++)
4296 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4297 R_Mesh_PrepareVertices_Mesh_Unlock();
4298 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4301 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4303 // upload temporary vertexbuffer for this rendering
4304 if (!gl_state.usevbo_staticvertex)
4305 vertexbuffer = NULL;
4306 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4308 if (gl_state.preparevertices_dynamicvertexbuffer)
4309 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4311 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4312 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4314 switch(vid.renderpath)
4316 case RENDERPATH_GL20:
4317 case RENDERPATH_GLES2:
4320 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4321 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4322 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4323 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4324 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4325 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4326 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4330 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4331 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4332 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4333 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4334 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4335 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4336 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4339 case RENDERPATH_GL13:
4340 case RENDERPATH_GLES1:
4343 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4344 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4345 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4346 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4350 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4351 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4352 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4353 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4356 case RENDERPATH_GL11:
4359 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4360 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4361 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4365 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4366 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4367 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4370 case RENDERPATH_D3D9:
4372 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4374 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4376 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4377 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4378 gl_state.d3dvertexdata = (void *)vertex;
4379 gl_state.d3dvertexsize = sizeof(*vertex);
4382 case RENDERPATH_D3D10:
4383 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4385 case RENDERPATH_D3D11:
4386 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4388 case RENDERPATH_SOFT:
4389 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4390 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4391 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4392 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4393 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4394 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4395 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);