3 #include "cl_collision.h"
4 #include "dpsoftrast.h"
7 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
8 extern D3DCAPS9 vid_d3d9caps;
11 #define MAX_RENDERTARGETS 4
13 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
14 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
15 cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
16 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
17 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
19 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
20 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
21 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
22 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
23 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
24 cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
25 cvar_t gl_vbo_dynamicvertex = {CVAR_SAVE, "gl_vbo_dynamicvertex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
26 cvar_t gl_vbo_dynamicindex = {CVAR_SAVE, "gl_vbo_dynamicindex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
27 cvar_t gl_fbo = {CVAR_SAVE, "gl_fbo", "1", "make use of GL_ARB_framebuffer_object extension to enable shadowmaps and other features using pixel formats different from the framebuffer"};
29 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
30 qboolean v_flipped_state = false;
32 r_viewport_t gl_viewport;
33 matrix4x4_t gl_modelmatrix;
34 matrix4x4_t gl_viewmatrix;
35 matrix4x4_t gl_modelviewmatrix;
36 matrix4x4_t gl_projectionmatrix;
37 matrix4x4_t gl_modelviewprojectionmatrix;
38 float gl_modelview16f[16];
39 float gl_modelviewprojection16f[16];
40 qboolean gl_modelmatrixchanged;
42 int gl_maxdrawrangeelementsvertices;
43 int gl_maxdrawrangeelementsindices;
48 void GL_PrintError(int errornumber, const char *filename, int linenumber)
52 #ifdef GL_INVALID_ENUM
54 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
57 #ifdef GL_INVALID_VALUE
58 case GL_INVALID_VALUE:
59 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
62 #ifdef GL_INVALID_OPERATION
63 case GL_INVALID_OPERATION:
64 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
67 #ifdef GL_STACK_OVERFLOW
68 case GL_STACK_OVERFLOW:
69 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
72 #ifdef GL_STACK_UNDERFLOW
73 case GL_STACK_UNDERFLOW:
74 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
77 #ifdef GL_OUT_OF_MEMORY
78 case GL_OUT_OF_MEMORY:
79 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
82 #ifdef GL_TABLE_TOO_LARGE
83 case GL_TABLE_TOO_LARGE:
84 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
87 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
88 case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
89 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
93 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
99 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
101 void SCR_ScreenShot_f (void);
103 typedef struct gltextureunit_s
105 int pointer_texcoord_components;
106 int pointer_texcoord_gltype;
107 size_t pointer_texcoord_stride;
108 const void *pointer_texcoord_pointer;
109 const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
110 size_t pointer_texcoord_offset;
113 int t2d, t3d, tcubemap;
115 int rgbscale, alphascale;
117 int combinergb, combinealpha;
118 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
119 int texmatrixenabled;
124 typedef struct gl_state_s
132 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
136 float polygonoffset[2];
139 float alphafuncvalue;
142 unsigned int clientunit;
143 gltextureunit_t units[MAX_TEXTUREUNITS];
147 int vertexbufferobject;
148 int elementbufferobject;
149 int framebufferobject;
150 int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
151 qboolean pointer_color_enabled;
153 int pointer_vertex_components;
154 int pointer_vertex_gltype;
155 size_t pointer_vertex_stride;
156 const void *pointer_vertex_pointer;
157 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
158 size_t pointer_vertex_offset;
160 int pointer_color_components;
161 int pointer_color_gltype;
162 size_t pointer_color_stride;
163 const void *pointer_color_pointer;
164 const r_meshbuffer_t *pointer_color_vertexbuffer;
165 size_t pointer_color_offset;
167 void *preparevertices_tempdata;
168 size_t preparevertices_tempdatamaxsize;
169 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
170 r_vertexgeneric_t *preparevertices_vertexgeneric;
171 r_vertexmesh_t *preparevertices_vertexmesh;
172 int preparevertices_numvertices;
174 r_meshbuffer_t *draw_dynamicindexbuffer;
176 qboolean usevbo_staticvertex;
177 qboolean usevbo_staticindex;
178 qboolean usevbo_dynamicvertex;
179 qboolean usevbo_dynamicindex;
181 memexpandablearray_t meshbufferarray;
186 // rtexture_t *d3drt_depthtexture;
187 // rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
188 IDirect3DSurface9 *d3drt_depthsurface;
189 IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
190 IDirect3DSurface9 *d3drt_backbufferdepthsurface;
191 IDirect3DSurface9 *d3drt_backbuffercolorsurface;
192 void *d3dvertexbuffer;
194 size_t d3dvertexsize;
199 static gl_state_t gl_state;
203 note: here's strip order for a terrain row:
210 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
212 *elements++ = i + row;
214 *elements++ = i + row + 1;
217 *elements++ = i + row + 1;
220 for (y = 0;y < rows - 1;y++)
222 for (x = 0;x < columns - 1;x++)
225 *elements++ = i + columns;
227 *elements++ = i + columns + 1;
230 *elements++ = i + columns + 1;
241 for (y = 0;y < rows - 1;y++)
243 for (x = 0;x < columns - 1;x++)
247 *elements++ = i + columns;
248 *elements++ = i + columns + 1;
249 *elements++ = i + columns;
250 *elements++ = i + columns + 1;
256 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
257 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
258 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
259 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
261 void GL_VBOStats_f(void)
263 GL_Mesh_ListVBOs(true);
266 static void GL_Backend_ResetState(void);
268 static void R_Mesh_InitVertexDeclarations(void);
269 static void R_Mesh_DestroyVertexDeclarations(void);
271 static void R_Mesh_SetUseVBO(void)
273 switch(vid.renderpath)
275 case RENDERPATH_GL11:
276 case RENDERPATH_GL13:
277 case RENDERPATH_GL20:
278 case RENDERPATH_GLES1:
279 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
280 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
281 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
282 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
284 case RENDERPATH_D3D9:
285 gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
286 gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo;
288 case RENDERPATH_D3D10:
289 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
291 case RENDERPATH_D3D11:
292 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
294 case RENDERPATH_SOFT:
295 gl_state.usevbo_staticvertex = false;
296 gl_state.usevbo_staticindex = false;
297 gl_state.usevbo_dynamicvertex = false;
298 gl_state.usevbo_dynamicindex = false;
300 case RENDERPATH_GLES2:
301 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
302 gl_state.usevbo_staticindex = false;
303 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
304 gl_state.usevbo_dynamicindex = false;
309 static void gl_backend_start(void)
311 memset(&gl_state, 0, sizeof(gl_state));
313 R_Mesh_InitVertexDeclarations();
316 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
318 Con_DPrintf("OpenGL backend started.\n");
322 GL_Backend_ResetState();
324 switch(vid.renderpath)
326 case RENDERPATH_GL11:
327 case RENDERPATH_GL13:
328 case RENDERPATH_GL20:
329 case RENDERPATH_GLES1:
330 case RENDERPATH_GLES2:
331 // fetch current fbo here (default fbo is not 0 on some GLES devices)
332 if (vid.support.ext_framebuffer_object)
333 qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
335 case RENDERPATH_D3D9:
337 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
338 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
341 case RENDERPATH_D3D10:
342 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
344 case RENDERPATH_D3D11:
345 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
347 case RENDERPATH_SOFT:
352 static void gl_backend_shutdown(void)
354 Con_DPrint("OpenGL Backend shutting down\n");
356 switch(vid.renderpath)
358 case RENDERPATH_GL11:
359 case RENDERPATH_GL13:
360 case RENDERPATH_GL20:
361 case RENDERPATH_SOFT:
362 case RENDERPATH_GLES1:
363 case RENDERPATH_GLES2:
365 case RENDERPATH_D3D9:
367 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
368 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
371 case RENDERPATH_D3D10:
372 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
374 case RENDERPATH_D3D11:
375 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
379 if (gl_state.preparevertices_tempdata)
380 Mem_Free(gl_state.preparevertices_tempdata);
381 if (gl_state.preparevertices_dynamicvertexbuffer)
382 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
384 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
386 R_Mesh_DestroyVertexDeclarations();
388 memset(&gl_state, 0, sizeof(gl_state));
391 static void gl_backend_newmap(void)
395 static void gl_backend_devicelost(void)
398 r_meshbuffer_t *buffer;
400 gl_state.d3dvertexbuffer = NULL;
402 switch(vid.renderpath)
404 case RENDERPATH_GL11:
405 case RENDERPATH_GL13:
406 case RENDERPATH_GL20:
407 case RENDERPATH_SOFT:
408 case RENDERPATH_GLES1:
409 case RENDERPATH_GLES2:
411 case RENDERPATH_D3D9:
413 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
414 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
417 case RENDERPATH_D3D10:
418 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
420 case RENDERPATH_D3D11:
421 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
424 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
425 for (i = 0;i < endindex;i++)
427 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
428 if (!buffer || !buffer->isdynamic)
430 switch(vid.renderpath)
432 case RENDERPATH_GL11:
433 case RENDERPATH_GL13:
434 case RENDERPATH_GL20:
435 case RENDERPATH_SOFT:
436 case RENDERPATH_GLES1:
437 case RENDERPATH_GLES2:
439 case RENDERPATH_D3D9:
441 if (buffer->devicebuffer)
443 if (buffer->isindexbuffer)
444 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
446 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
447 buffer->devicebuffer = NULL;
451 case RENDERPATH_D3D10:
452 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
454 case RENDERPATH_D3D11:
455 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
461 static void gl_backend_devicerestored(void)
463 switch(vid.renderpath)
465 case RENDERPATH_GL11:
466 case RENDERPATH_GL13:
467 case RENDERPATH_GL20:
468 case RENDERPATH_SOFT:
469 case RENDERPATH_GLES1:
470 case RENDERPATH_GLES2:
472 case RENDERPATH_D3D9:
474 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
475 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
478 case RENDERPATH_D3D10:
479 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
481 case RENDERPATH_D3D11:
482 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
487 void gl_backend_init(void)
491 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
493 polygonelement3s[i * 3 + 0] = 0;
494 polygonelement3s[i * 3 + 1] = i + 1;
495 polygonelement3s[i * 3 + 2] = i + 2;
497 // elements for rendering a series of quads as triangles
498 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
500 quadelement3s[i * 6 + 0] = i * 4;
501 quadelement3s[i * 6 + 1] = i * 4 + 1;
502 quadelement3s[i * 6 + 2] = i * 4 + 2;
503 quadelement3s[i * 6 + 3] = i * 4;
504 quadelement3s[i * 6 + 4] = i * 4 + 2;
505 quadelement3s[i * 6 + 5] = i * 4 + 3;
508 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
509 polygonelement3i[i] = polygonelement3s[i];
510 for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
511 quadelement3i[i] = quadelement3s[i];
513 Cvar_RegisterVariable(&r_render);
514 Cvar_RegisterVariable(&r_renderview);
515 Cvar_RegisterVariable(&r_waterwarp);
516 Cvar_RegisterVariable(&gl_polyblend);
517 Cvar_RegisterVariable(&v_flipped);
518 Cvar_RegisterVariable(&gl_dither);
519 Cvar_RegisterVariable(&gl_vbo);
520 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
521 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
522 Cvar_RegisterVariable(&gl_paranoid);
523 Cvar_RegisterVariable(&gl_printcheckerror);
525 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
526 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
527 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
529 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");
531 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
534 void GL_SetMirrorState(qboolean state);
536 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
540 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
541 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
543 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
545 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
546 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
547 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
549 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
554 switch(vid.renderpath)
556 case RENDERPATH_GL11:
557 case RENDERPATH_GL13:
558 case RENDERPATH_GL20:
559 case RENDERPATH_GLES1:
560 case RENDERPATH_GLES2:
563 case RENDERPATH_D3D9:
564 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
566 case RENDERPATH_D3D10:
567 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
569 case RENDERPATH_D3D11:
570 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
572 case RENDERPATH_SOFT:
578 static int bboxedges[12][2] =
597 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
599 int i, ix1, iy1, ix2, iy2;
600 float x1, y1, x2, y2;
611 scissor[0] = r_refdef.view.viewport.x;
612 scissor[1] = r_refdef.view.viewport.y;
613 scissor[2] = r_refdef.view.viewport.width;
614 scissor[3] = r_refdef.view.viewport.height;
616 // if view is inside the box, just say yes it's visible
617 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
620 x1 = y1 = x2 = y2 = 0;
622 // transform all corners that are infront of the nearclip plane
623 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
624 plane4f[3] = r_refdef.view.frustum[4].dist;
626 for (i = 0;i < 8;i++)
628 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
629 dist[i] = DotProduct4(corner[i], plane4f);
630 sign[i] = dist[i] > 0;
633 VectorCopy(corner[i], vertex[numvertices]);
637 // if some points are behind the nearclip, add clipped edge points to make
638 // sure that the scissor boundary is complete
639 if (numvertices > 0 && numvertices < 8)
641 // add clipped edge points
642 for (i = 0;i < 12;i++)
646 if (sign[j] != sign[k])
648 f = dist[j] / (dist[j] - dist[k]);
649 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
655 // if we have no points to check, it is behind the view plane
659 // if we have some points to transform, check what screen area is covered
660 x1 = y1 = x2 = y2 = 0;
662 //Con_Printf("%i vertices to transform...\n", numvertices);
663 for (i = 0;i < numvertices;i++)
665 VectorCopy(vertex[i], v);
666 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
667 //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]);
670 if (x1 > v2[0]) x1 = v2[0];
671 if (x2 < v2[0]) x2 = v2[0];
672 if (y1 > v2[1]) y1 = v2[1];
673 if (y2 < v2[1]) y2 = v2[1];
682 // now convert the scissor rectangle to integer screen coordinates
683 ix1 = (int)(x1 - 1.0f);
684 //iy1 = vid.height - (int)(y2 - 1.0f);
685 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
686 iy1 = (int)(y1 - 1.0f);
687 ix2 = (int)(x2 + 1.0f);
688 //iy2 = vid.height - (int)(y1 + 1.0f);
689 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
690 iy2 = (int)(y2 + 1.0f);
691 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
693 // clamp it to the screen
694 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
695 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
696 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
697 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
699 // if it is inside out, it's not visible
700 if (ix2 <= ix1 || iy2 <= iy1)
703 // the light area is visible, set up the scissor rectangle
706 scissor[2] = ix2 - ix1;
707 scissor[3] = iy2 - iy1;
709 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
710 switch(vid.renderpath)
712 case RENDERPATH_D3D9:
713 case RENDERPATH_D3D10:
714 case RENDERPATH_D3D11:
715 scissor[1] = vid.height - scissor[1] - scissor[3];
717 case RENDERPATH_GL11:
718 case RENDERPATH_GL13:
719 case RENDERPATH_GL20:
720 case RENDERPATH_SOFT:
721 case RENDERPATH_GLES1:
722 case RENDERPATH_GLES2:
730 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
734 float clipPlane[4], v3[3], v4[3];
737 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
739 VectorSet(normal, normalx, normaly, normalz);
740 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
741 VectorScale(normal, -dist, v3);
742 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
743 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
744 clipPlane[3] = -DotProduct(v4, clipPlane);
748 // testing code for comparing results
750 VectorCopy4(clipPlane, clipPlane2);
751 R_EntityMatrix(&identitymatrix);
752 VectorSet(q, normal[0], normal[1], normal[2], -dist);
753 qglClipPlane(GL_CLIP_PLANE0, q);
754 qglGetClipPlane(GL_CLIP_PLANE0, q);
755 VectorCopy4(q, clipPlane);
759 // Calculate the clip-space corner point opposite the clipping plane
760 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
761 // transform it into camera space by multiplying it
762 // by the inverse of the projection matrix
763 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
764 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
766 q[3] = (1.0f + m[10]) / m[14];
768 // Calculate the scaled plane vector
769 d = 2.0f / DotProduct4(clipPlane, q);
771 // Replace the third row of the projection matrix
772 m[2] = clipPlane[0] * d;
773 m[6] = clipPlane[1] * d;
774 m[10] = clipPlane[2] * d + 1.0f;
775 m[14] = clipPlane[3] * d;
778 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)
780 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
782 memset(v, 0, sizeof(*v));
783 v->type = R_VIEWPORTTYPE_ORTHO;
784 v->cameramatrix = *cameramatrix;
791 memset(m, 0, sizeof(m));
792 m[0] = 2/(right - left);
793 m[5] = 2/(top - bottom);
794 m[10] = -2/(zFar - zNear);
795 m[12] = - (right + left)/(right - left);
796 m[13] = - (top + bottom)/(top - bottom);
797 m[14] = - (zFar + zNear)/(zFar - zNear);
799 switch(vid.renderpath)
801 case RENDERPATH_GL11:
802 case RENDERPATH_GL13:
803 case RENDERPATH_GL20:
804 case RENDERPATH_SOFT:
805 case RENDERPATH_GLES1:
806 case RENDERPATH_GLES2:
808 case RENDERPATH_D3D9:
809 case RENDERPATH_D3D10:
810 case RENDERPATH_D3D11:
811 m[10] = -1/(zFar - zNear);
812 m[14] = -zNear/(zFar-zNear);
815 v->screentodepth[0] = -farclip / (farclip - nearclip);
816 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
818 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
821 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
823 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
829 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
830 R_Viewport_TransformToScreen(v, test1, test2);
831 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
836 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)
838 matrix4x4_t tempmatrix, basematrix;
840 memset(v, 0, sizeof(*v));
842 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
843 v->cameramatrix = *cameramatrix;
850 memset(m, 0, sizeof(m));
851 m[0] = 1.0 / frustumx;
852 m[5] = 1.0 / frustumy;
853 m[10] = -(farclip + nearclip) / (farclip - nearclip);
855 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
856 v->screentodepth[0] = -farclip / (farclip - nearclip);
857 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
859 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
860 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
861 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
862 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
865 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
867 if(v_flipped.integer)
875 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
878 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)
880 matrix4x4_t tempmatrix, basematrix;
881 const float nudge = 1.0 - 1.0 / (1<<23);
883 memset(v, 0, sizeof(*v));
885 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
886 v->cameramatrix = *cameramatrix;
893 memset(m, 0, sizeof(m));
894 m[ 0] = 1.0 / frustumx;
895 m[ 5] = 1.0 / frustumy;
898 m[14] = -2 * nearclip * nudge;
899 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
900 v->screentodepth[1] = m[14] * -0.5;
902 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
903 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
904 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
905 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
908 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
910 if(v_flipped.integer)
918 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
921 float cubeviewmatrix[6][16] =
923 // standard cubemap projections
961 float rectviewmatrix[6][16] =
963 // sign-preserving cubemap projections
1002 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
1004 matrix4x4_t tempmatrix, basematrix;
1006 memset(v, 0, sizeof(*v));
1007 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1008 v->cameramatrix = *cameramatrix;
1012 memset(m, 0, sizeof(m));
1014 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1016 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1018 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
1019 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1020 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1023 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1025 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1028 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)
1030 matrix4x4_t tempmatrix, basematrix;
1032 memset(v, 0, sizeof(*v));
1033 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1034 v->cameramatrix = *cameramatrix;
1035 v->x = (side & 1) * size;
1036 v->y = (side >> 1) * size;
1040 memset(m, 0, sizeof(m));
1041 m[0] = m[5] = 1.0f * ((float)size - border) / size;
1042 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1044 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1046 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1047 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1048 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1050 switch(vid.renderpath)
1052 case RENDERPATH_GL20:
1053 case RENDERPATH_GL13:
1054 case RENDERPATH_GL11:
1055 case RENDERPATH_SOFT:
1056 case RENDERPATH_GLES1:
1057 case RENDERPATH_GLES2:
1059 case RENDERPATH_D3D9:
1062 case RENDERPATH_D3D10:
1063 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1065 case RENDERPATH_D3D11:
1066 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1071 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1073 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1076 void R_SetViewport(const r_viewport_t *v)
1081 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1082 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1084 // copy over the matrices to our state
1085 gl_viewmatrix = v->viewmatrix;
1086 gl_projectionmatrix = v->projectmatrix;
1088 switch(vid.renderpath)
1090 case RENDERPATH_GL13:
1091 case RENDERPATH_GL11:
1092 case RENDERPATH_GLES1:
1094 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1095 // Load the projection matrix into OpenGL
1096 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1097 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1098 qglLoadMatrixf(m);CHECKGLERROR
1099 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1101 case RENDERPATH_D3D9:
1104 D3DVIEWPORT9 d3dviewport;
1105 d3dviewport.X = gl_viewport.x;
1106 d3dviewport.Y = gl_viewport.y;
1107 d3dviewport.Width = gl_viewport.width;
1108 d3dviewport.Height = gl_viewport.height;
1109 d3dviewport.MinZ = gl_state.depthrange[0];
1110 d3dviewport.MaxZ = gl_state.depthrange[1];
1111 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1115 case RENDERPATH_D3D10:
1116 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1118 case RENDERPATH_D3D11:
1119 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1121 case RENDERPATH_SOFT:
1122 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1124 case RENDERPATH_GL20:
1125 case RENDERPATH_GLES2:
1127 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1131 // force an update of the derived matrices
1132 gl_modelmatrixchanged = true;
1133 R_EntityMatrix(&gl_modelmatrix);
1136 void R_GetViewport(r_viewport_t *v)
1141 static void GL_BindVBO(int bufferobject)
1143 if (gl_state.vertexbufferobject != bufferobject)
1145 gl_state.vertexbufferobject = bufferobject;
1147 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1151 static void GL_BindEBO(int bufferobject)
1153 if (gl_state.elementbufferobject != bufferobject)
1155 gl_state.elementbufferobject = bufferobject;
1157 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1161 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1164 switch(vid.renderpath)
1166 case RENDERPATH_GL11:
1167 case RENDERPATH_GL13:
1168 case RENDERPATH_GL20:
1169 case RENDERPATH_GLES1:
1170 case RENDERPATH_GLES2:
1171 if (!vid.support.ext_framebuffer_object)
1173 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1174 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1175 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1176 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1177 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1178 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1179 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1181 case RENDERPATH_D3D9:
1182 case RENDERPATH_D3D10:
1183 case RENDERPATH_D3D11:
1185 case RENDERPATH_SOFT:
1191 void R_Mesh_DestroyFramebufferObject(int fbo)
1193 switch(vid.renderpath)
1195 case RENDERPATH_GL11:
1196 case RENDERPATH_GL13:
1197 case RENDERPATH_GL20:
1198 case RENDERPATH_GLES1:
1199 case RENDERPATH_GLES2:
1201 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1203 case RENDERPATH_D3D9:
1204 case RENDERPATH_D3D10:
1205 case RENDERPATH_D3D11:
1207 case RENDERPATH_SOFT:
1213 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1215 // 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)
1216 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)
1219 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1220 if (gl_state.d3drt_depthsurface != depthsurface)
1222 gl_state.d3drt_depthsurface = depthsurface;
1223 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1225 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1227 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1228 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1230 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1232 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1233 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1235 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1237 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1238 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1240 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1242 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1243 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1248 void R_Mesh_ResetRenderTargets(void)
1250 switch(vid.renderpath)
1252 case RENDERPATH_GL11:
1253 case RENDERPATH_GL13:
1254 case RENDERPATH_GL20:
1255 case RENDERPATH_GLES1:
1256 case RENDERPATH_GLES2:
1257 if (gl_state.framebufferobject)
1259 gl_state.framebufferobject = 0;
1260 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1263 case RENDERPATH_D3D9:
1265 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1268 case RENDERPATH_D3D10:
1269 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1271 case RENDERPATH_D3D11:
1272 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1274 case RENDERPATH_SOFT:
1275 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1280 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1284 rtexture_t *textures[5];
1285 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1286 textures[4] = depthtexture;
1287 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1288 for (j = 0;j < 5;j++)
1290 for (i = 0;i < vid.teximageunits;i++)
1291 if (gl_state.units[i].texture == textures[j])
1292 R_Mesh_TexBind(i, NULL);
1293 // set up framebuffer object or render targets for the active rendering API
1294 switch(vid.renderpath)
1296 case RENDERPATH_GL11:
1297 case RENDERPATH_GL13:
1298 case RENDERPATH_GL20:
1299 case RENDERPATH_GLES1:
1300 case RENDERPATH_GLES2:
1301 if (gl_state.framebufferobject != fbo)
1303 gl_state.framebufferobject = fbo;
1304 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1307 case RENDERPATH_D3D9:
1309 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1310 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1313 IDirect3DSurface9 *colorsurfaces[4];
1314 for (i = 0;i < 4;i++)
1316 colorsurfaces[i] = NULL;
1318 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1320 // set the render targets for real
1321 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1322 // release the texture surface levels (they won't be lost while bound...)
1323 for (i = 0;i < 4;i++)
1325 IDirect3DSurface9_Release(colorsurfaces[i]);
1328 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1331 case RENDERPATH_D3D10:
1332 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1334 case RENDERPATH_D3D11:
1335 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1337 case RENDERPATH_SOFT:
1341 unsigned int *pointers[5];
1342 memset(pointers, 0, sizeof(pointers));
1343 for (i = 0;i < 5;i++)
1344 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1345 width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1346 height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1347 DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1350 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1356 static int d3dcmpforglfunc(int f)
1360 case GL_NEVER: return D3DCMP_NEVER;
1361 case GL_LESS: return D3DCMP_LESS;
1362 case GL_EQUAL: return D3DCMP_EQUAL;
1363 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1364 case GL_GREATER: return D3DCMP_GREATER;
1365 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1366 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1367 case GL_ALWAYS: return D3DCMP_ALWAYS;
1368 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1372 static int d3dstencilopforglfunc(int f)
1376 case GL_KEEP: return D3DSTENCILOP_KEEP;
1377 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1378 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1379 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1384 extern cvar_t r_transparent_alphatocoverage;
1386 static void GL_Backend_ResetState(void)
1389 gl_state.active = true;
1390 gl_state.depthtest = true;
1391 gl_state.alphatest = false;
1392 gl_state.alphafunc = GL_GEQUAL;
1393 gl_state.alphafuncvalue = 0.5f;
1394 gl_state.blendfunc1 = GL_ONE;
1395 gl_state.blendfunc2 = GL_ZERO;
1396 gl_state.blend = false;
1397 gl_state.depthmask = GL_TRUE;
1398 gl_state.colormask = 15;
1399 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1400 gl_state.lockrange_first = 0;
1401 gl_state.lockrange_count = 0;
1402 gl_state.cullface = GL_FRONT;
1403 gl_state.cullfaceenable = false;
1404 gl_state.polygonoffset[0] = 0;
1405 gl_state.polygonoffset[1] = 0;
1406 gl_state.framebufferobject = 0;
1407 gl_state.depthfunc = GL_LEQUAL;
1409 switch(vid.renderpath)
1411 case RENDERPATH_D3D9:
1414 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1415 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1416 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1417 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1418 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1419 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1420 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1421 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1422 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1423 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1427 case RENDERPATH_D3D10:
1428 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1430 case RENDERPATH_D3D11:
1431 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1433 case RENDERPATH_GL11:
1434 case RENDERPATH_GL13:
1435 case RENDERPATH_GLES1:
1438 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1439 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1440 qglDisable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
1441 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1442 qglDisable(GL_BLEND);CHECKGLERROR
1443 qglCullFace(gl_state.cullface);CHECKGLERROR
1444 qglDisable(GL_CULL_FACE);CHECKGLERROR
1445 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1446 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1447 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1448 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1450 if (vid.support.arb_vertex_buffer_object)
1452 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1453 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1456 if (vid.support.ext_framebuffer_object)
1458 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1459 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1462 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1463 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1465 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1466 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1467 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1469 if (vid.support.ext_framebuffer_object)
1470 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1472 gl_state.unit = MAX_TEXTUREUNITS;
1473 gl_state.clientunit = MAX_TEXTUREUNITS;
1474 for (i = 0;i < vid.texunits;i++)
1476 GL_ActiveTexture(i);
1477 GL_ClientActiveTexture(i);
1478 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1479 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1480 if (vid.support.ext_texture_3d)
1482 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1483 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1485 if (vid.support.arb_texture_cube_map)
1487 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1488 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1491 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1492 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1493 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1494 qglLoadIdentity();CHECKGLERROR
1495 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1496 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1500 case RENDERPATH_SOFT:
1501 DPSOFTRAST_ColorMask(1,1,1,1);
1502 DPSOFTRAST_AlphaTest(gl_state.alphatest);
1503 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1504 DPSOFTRAST_CullFace(gl_state.cullface);
1505 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1506 DPSOFTRAST_DepthMask(gl_state.depthmask);
1507 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1508 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1509 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1511 case RENDERPATH_GL20:
1512 case RENDERPATH_GLES2:
1514 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1515 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1516 qglDisable(GL_BLEND);CHECKGLERROR
1517 qglCullFace(gl_state.cullface);CHECKGLERROR
1518 qglDisable(GL_CULL_FACE);CHECKGLERROR
1519 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1520 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1521 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1522 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1523 // if (vid.renderpath == RENDERPATH_GL20)
1525 // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1526 // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1528 if (vid.support.arb_vertex_buffer_object)
1530 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1531 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1533 if (vid.support.ext_framebuffer_object)
1534 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1535 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1536 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1537 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1538 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1539 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1540 gl_state.unit = MAX_TEXTUREUNITS;
1541 gl_state.clientunit = MAX_TEXTUREUNITS;
1542 for (i = 0;i < vid.teximageunits;i++)
1544 GL_ActiveTexture(i);
1545 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1546 if (vid.support.ext_texture_3d)
1548 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1550 if (vid.support.arb_texture_cube_map)
1552 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1555 for (i = 0;i < vid.texarrayunits;i++)
1558 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1559 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1566 void GL_ActiveTexture(unsigned int num)
1568 if (gl_state.unit != num)
1570 gl_state.unit = num;
1571 switch(vid.renderpath)
1573 case RENDERPATH_GL11:
1574 case RENDERPATH_GL13:
1575 case RENDERPATH_GL20:
1576 case RENDERPATH_GLES1:
1577 case RENDERPATH_GLES2:
1578 if (qglActiveTexture)
1581 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1585 case RENDERPATH_D3D9:
1586 case RENDERPATH_D3D10:
1587 case RENDERPATH_D3D11:
1589 case RENDERPATH_SOFT:
1595 void GL_ClientActiveTexture(unsigned int num)
1597 if (gl_state.clientunit != num)
1599 gl_state.clientunit = num;
1600 switch(vid.renderpath)
1602 case RENDERPATH_GL11:
1603 case RENDERPATH_GL13:
1604 case RENDERPATH_GLES1:
1605 if (qglActiveTexture)
1608 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1612 case RENDERPATH_D3D9:
1613 case RENDERPATH_D3D10:
1614 case RENDERPATH_D3D11:
1616 case RENDERPATH_SOFT:
1618 case RENDERPATH_GL20:
1619 case RENDERPATH_GLES2:
1625 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1627 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1629 qboolean blendenable;
1630 gl_state.blendfunc1 = blendfunc1;
1631 gl_state.blendfunc2 = blendfunc2;
1632 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1633 switch(vid.renderpath)
1635 case RENDERPATH_GL11:
1636 case RENDERPATH_GL13:
1637 case RENDERPATH_GL20:
1638 case RENDERPATH_GLES1:
1639 case RENDERPATH_GLES2:
1641 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1642 if (gl_state.blend != blendenable)
1644 gl_state.blend = blendenable;
1645 if (!gl_state.blend)
1647 qglDisable(GL_BLEND);CHECKGLERROR
1651 qglEnable(GL_BLEND);CHECKGLERROR
1655 case RENDERPATH_D3D9:
1660 D3DBLEND d3dblendfunc[2];
1661 glblendfunc[0] = gl_state.blendfunc1;
1662 glblendfunc[1] = gl_state.blendfunc2;
1663 for (i = 0;i < 2;i++)
1665 switch(glblendfunc[i])
1667 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1668 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1669 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1670 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1671 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1672 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1673 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1674 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1675 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1676 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1679 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1680 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1681 if (gl_state.blend != blendenable)
1683 gl_state.blend = blendenable;
1684 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1689 case RENDERPATH_D3D10:
1690 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1692 case RENDERPATH_D3D11:
1693 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1695 case RENDERPATH_SOFT:
1696 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1702 void GL_DepthMask(int state)
1704 if (gl_state.depthmask != state)
1706 gl_state.depthmask = state;
1707 switch(vid.renderpath)
1709 case RENDERPATH_GL11:
1710 case RENDERPATH_GL13:
1711 case RENDERPATH_GL20:
1712 case RENDERPATH_GLES1:
1713 case RENDERPATH_GLES2:
1715 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1717 case RENDERPATH_D3D9:
1719 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1722 case RENDERPATH_D3D10:
1723 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1725 case RENDERPATH_D3D11:
1726 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1728 case RENDERPATH_SOFT:
1729 DPSOFTRAST_DepthMask(gl_state.depthmask);
1735 void GL_DepthTest(int state)
1737 if (gl_state.depthtest != state)
1739 gl_state.depthtest = state;
1740 switch(vid.renderpath)
1742 case RENDERPATH_GL11:
1743 case RENDERPATH_GL13:
1744 case RENDERPATH_GL20:
1745 case RENDERPATH_GLES1:
1746 case RENDERPATH_GLES2:
1748 if (gl_state.depthtest)
1750 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1754 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1757 case RENDERPATH_D3D9:
1759 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1762 case RENDERPATH_D3D10:
1763 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1765 case RENDERPATH_D3D11:
1766 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1768 case RENDERPATH_SOFT:
1769 DPSOFTRAST_DepthTest(gl_state.depthtest);
1775 void GL_DepthFunc(int state)
1777 if (gl_state.depthfunc != state)
1779 gl_state.depthfunc = state;
1780 switch(vid.renderpath)
1782 case RENDERPATH_GL11:
1783 case RENDERPATH_GL13:
1784 case RENDERPATH_GL20:
1785 case RENDERPATH_GLES1:
1786 case RENDERPATH_GLES2:
1788 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1790 case RENDERPATH_D3D9:
1792 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1795 case RENDERPATH_D3D10:
1796 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1798 case RENDERPATH_D3D11:
1799 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1801 case RENDERPATH_SOFT:
1802 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1808 void GL_DepthRange(float nearfrac, float farfrac)
1810 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1812 gl_state.depthrange[0] = nearfrac;
1813 gl_state.depthrange[1] = farfrac;
1814 switch(vid.renderpath)
1816 case RENDERPATH_GL11:
1817 case RENDERPATH_GL13:
1818 case RENDERPATH_GL20:
1819 case RENDERPATH_GLES1:
1820 case RENDERPATH_GLES2:
1821 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1823 case RENDERPATH_D3D9:
1826 D3DVIEWPORT9 d3dviewport;
1827 d3dviewport.X = gl_viewport.x;
1828 d3dviewport.Y = gl_viewport.y;
1829 d3dviewport.Width = gl_viewport.width;
1830 d3dviewport.Height = gl_viewport.height;
1831 d3dviewport.MinZ = gl_state.depthrange[0];
1832 d3dviewport.MaxZ = gl_state.depthrange[1];
1833 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1837 case RENDERPATH_D3D10:
1838 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840 case RENDERPATH_D3D11:
1841 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1843 case RENDERPATH_SOFT:
1844 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1850 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)
1852 switch (vid.renderpath)
1854 case RENDERPATH_GL11:
1855 case RENDERPATH_GL13:
1856 case RENDERPATH_GL20:
1857 case RENDERPATH_GLES1:
1858 case RENDERPATH_GLES2:
1862 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1866 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1868 if (vid.support.ati_separate_stencil)
1870 qglStencilMask(writemask);CHECKGLERROR
1871 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1872 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1873 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1875 else if (vid.support.ext_stencil_two_side)
1877 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1878 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1879 qglStencilMask(writemask);CHECKGLERROR
1880 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1881 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1882 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1883 qglStencilMask(writemask);CHECKGLERROR
1884 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1885 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1888 case RENDERPATH_D3D9:
1890 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1891 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1892 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1893 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1894 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1895 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1896 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1897 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1898 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1899 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1900 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1901 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1902 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1905 case RENDERPATH_D3D10:
1906 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1908 case RENDERPATH_D3D11:
1909 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1911 case RENDERPATH_SOFT:
1912 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1919 switch (vid.renderpath)
1921 case RENDERPATH_GL11:
1922 case RENDERPATH_GL13:
1923 case RENDERPATH_GL20:
1924 case RENDERPATH_GLES1:
1925 case RENDERPATH_GLES2:
1929 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1933 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1935 if (vid.support.ext_stencil_two_side)
1937 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1939 qglStencilMask(writemask);CHECKGLERROR
1940 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1941 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1944 case RENDERPATH_D3D9:
1946 if (vid.support.ati_separate_stencil)
1947 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1948 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1949 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1950 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1951 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1952 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1953 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1954 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1955 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1958 case RENDERPATH_D3D10:
1959 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_D3D11:
1962 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964 case RENDERPATH_SOFT:
1965 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1970 void GL_PolygonOffset(float planeoffset, float depthoffset)
1972 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1974 gl_state.polygonoffset[0] = planeoffset;
1975 gl_state.polygonoffset[1] = depthoffset;
1976 switch(vid.renderpath)
1978 case RENDERPATH_GL11:
1979 case RENDERPATH_GL13:
1980 case RENDERPATH_GL20:
1981 case RENDERPATH_GLES1:
1982 case RENDERPATH_GLES2:
1983 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1985 case RENDERPATH_D3D9:
1987 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1988 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1991 case RENDERPATH_D3D10:
1992 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994 case RENDERPATH_D3D11:
1995 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1997 case RENDERPATH_SOFT:
1998 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2004 void GL_SetMirrorState(qboolean state)
2006 if (v_flipped_state != state)
2008 v_flipped_state = state;
2009 if (gl_state.cullface == GL_BACK)
2010 gl_state.cullface = GL_FRONT;
2011 else if (gl_state.cullface == GL_FRONT)
2012 gl_state.cullface = GL_BACK;
2015 switch(vid.renderpath)
2017 case RENDERPATH_GL11:
2018 case RENDERPATH_GL13:
2019 case RENDERPATH_GL20:
2020 case RENDERPATH_GLES1:
2021 case RENDERPATH_GLES2:
2022 qglCullFace(gl_state.cullface);CHECKGLERROR
2024 case RENDERPATH_D3D9:
2026 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2029 case RENDERPATH_D3D10:
2030 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2032 case RENDERPATH_D3D11:
2033 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2035 case RENDERPATH_SOFT:
2036 DPSOFTRAST_CullFace(gl_state.cullface);
2042 void GL_CullFace(int state)
2046 if(state == GL_FRONT)
2048 else if(state == GL_BACK)
2052 switch(vid.renderpath)
2054 case RENDERPATH_GL11:
2055 case RENDERPATH_GL13:
2056 case RENDERPATH_GL20:
2057 case RENDERPATH_GLES1:
2058 case RENDERPATH_GLES2:
2061 if (state != GL_NONE)
2063 if (!gl_state.cullfaceenable)
2065 gl_state.cullfaceenable = true;
2066 qglEnable(GL_CULL_FACE);CHECKGLERROR
2068 if (gl_state.cullface != state)
2070 gl_state.cullface = state;
2071 qglCullFace(gl_state.cullface);CHECKGLERROR
2076 if (gl_state.cullfaceenable)
2078 gl_state.cullfaceenable = false;
2079 qglDisable(GL_CULL_FACE);CHECKGLERROR
2083 case RENDERPATH_D3D9:
2085 if (gl_state.cullface != state)
2087 gl_state.cullface = state;
2088 switch(gl_state.cullface)
2091 gl_state.cullfaceenable = false;
2092 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2095 gl_state.cullfaceenable = true;
2096 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2099 gl_state.cullfaceenable = true;
2100 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2106 case RENDERPATH_D3D10:
2107 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2109 case RENDERPATH_D3D11:
2110 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2112 case RENDERPATH_SOFT:
2113 if (gl_state.cullface != state)
2115 gl_state.cullface = state;
2116 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2117 DPSOFTRAST_CullFace(gl_state.cullface);
2123 void GL_AlphaTest(int state)
2125 if (gl_state.alphatest != state)
2127 gl_state.alphatest = state;
2128 switch(vid.renderpath)
2130 case RENDERPATH_GL11:
2131 case RENDERPATH_GL13:
2132 case RENDERPATH_GLES1:
2133 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2135 if (gl_state.alphatest)
2137 qglEnable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
2141 qglDisable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
2144 case RENDERPATH_D3D9:
2146 // IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2149 case RENDERPATH_D3D10:
2151 case RENDERPATH_D3D11:
2153 case RENDERPATH_SOFT:
2154 // DPSOFTRAST_AlphaTest(gl_state.alphatest);
2156 case RENDERPATH_GL20:
2157 case RENDERPATH_GLES2:
2163 void GL_ColorMask(int r, int g, int b, int a)
2165 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2166 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2167 if (gl_state.colormask != state)
2169 gl_state.colormask = state;
2170 switch(vid.renderpath)
2172 case RENDERPATH_GL11:
2173 case RENDERPATH_GL13:
2174 case RENDERPATH_GL20:
2175 case RENDERPATH_GLES1:
2176 case RENDERPATH_GLES2:
2178 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2180 case RENDERPATH_D3D9:
2182 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2185 case RENDERPATH_D3D10:
2186 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2188 case RENDERPATH_D3D11:
2189 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2191 case RENDERPATH_SOFT:
2192 DPSOFTRAST_ColorMask(r, g, b, a);
2198 void GL_Color(float cr, float cg, float cb, float ca)
2200 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)
2202 gl_state.color4f[0] = cr;
2203 gl_state.color4f[1] = cg;
2204 gl_state.color4f[2] = cb;
2205 gl_state.color4f[3] = ca;
2206 switch(vid.renderpath)
2208 case RENDERPATH_GL11:
2209 case RENDERPATH_GL13:
2210 case RENDERPATH_GLES1:
2212 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2215 case RENDERPATH_D3D9:
2216 case RENDERPATH_D3D10:
2217 case RENDERPATH_D3D11:
2218 // no equivalent in D3D
2220 case RENDERPATH_SOFT:
2221 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2223 case RENDERPATH_GL20:
2224 case RENDERPATH_GLES2:
2225 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2231 void GL_Scissor (int x, int y, int width, int height)
2233 switch(vid.renderpath)
2235 case RENDERPATH_GL11:
2236 case RENDERPATH_GL13:
2237 case RENDERPATH_GL20:
2238 case RENDERPATH_GLES1:
2239 case RENDERPATH_GLES2:
2241 qglScissor(x, y,width,height);
2244 case RENDERPATH_D3D9:
2250 d3drect.right = x + width;
2251 d3drect.bottom = y + height;
2252 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2256 case RENDERPATH_D3D10:
2257 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2259 case RENDERPATH_D3D11:
2260 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2262 case RENDERPATH_SOFT:
2263 DPSOFTRAST_Scissor(x, y, width, height);
2268 void GL_ScissorTest(int state)
2270 if (gl_state.scissortest != state)
2272 gl_state.scissortest = state;
2273 switch(vid.renderpath)
2275 case RENDERPATH_GL11:
2276 case RENDERPATH_GL13:
2277 case RENDERPATH_GL20:
2278 case RENDERPATH_GLES1:
2279 case RENDERPATH_GLES2:
2281 if(gl_state.scissortest)
2282 qglEnable(GL_SCISSOR_TEST);
2284 qglDisable(GL_SCISSOR_TEST);
2287 case RENDERPATH_D3D9:
2289 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2292 case RENDERPATH_D3D10:
2293 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2295 case RENDERPATH_D3D11:
2296 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2298 case RENDERPATH_SOFT:
2299 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2305 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2307 static const float blackcolor[4] = {0, 0, 0, 0};
2308 // prevent warnings when trying to clear a buffer that does not exist
2310 colorvalue = blackcolor;
2313 mask &= ~GL_STENCIL_BUFFER_BIT;
2316 switch(vid.renderpath)
2318 case RENDERPATH_GL11:
2319 case RENDERPATH_GL13:
2320 case RENDERPATH_GL20:
2321 case RENDERPATH_GLES1:
2322 case RENDERPATH_GLES2:
2324 if (mask & GL_COLOR_BUFFER_BIT)
2326 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2328 if (mask & GL_DEPTH_BUFFER_BIT)
2330 qglClearDepth(depthvalue);CHECKGLERROR
2332 if (mask & GL_STENCIL_BUFFER_BIT)
2334 qglClearStencil(stencilvalue);CHECKGLERROR
2336 qglClear(mask);CHECKGLERROR
2338 case RENDERPATH_D3D9:
2340 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);
2343 case RENDERPATH_D3D10:
2344 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2346 case RENDERPATH_D3D11:
2347 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2349 case RENDERPATH_SOFT:
2350 if (mask & GL_COLOR_BUFFER_BIT)
2351 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2352 if (mask & GL_DEPTH_BUFFER_BIT)
2353 DPSOFTRAST_ClearDepth(depthvalue);
2358 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2360 switch(vid.renderpath)
2362 case RENDERPATH_GL11:
2363 case RENDERPATH_GL13:
2364 case RENDERPATH_GL20:
2365 case RENDERPATH_GLES1:
2366 case RENDERPATH_GLES2:
2368 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2370 case RENDERPATH_D3D9:
2373 // LordHavoc: we can't directly download the backbuffer because it may be
2374 // multisampled, and it may not be lockable, so we blit it to a lockable
2375 // surface of the same dimensions (but without multisample) to resolve the
2376 // multisample buffer to a normal image, and then lock that...
2377 IDirect3DSurface9 *stretchsurface = NULL;
2378 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2380 D3DLOCKED_RECT lockedrect;
2381 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2383 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2386 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2387 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2388 memcpy(outpixels + line * width * 4, row, width * 4);
2389 IDirect3DSurface9_UnlockRect(stretchsurface);
2392 IDirect3DSurface9_Release(stretchsurface);
2395 //IDirect3DSurface9 *syssurface = NULL;
2396 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2397 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2398 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2399 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2400 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2401 //IDirect3DSurface9_UnlockRect(syssurface);
2402 //IDirect3DSurface9_Release(syssurface);
2406 case RENDERPATH_D3D10:
2407 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2409 case RENDERPATH_D3D11:
2410 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2412 case RENDERPATH_SOFT:
2413 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2418 // called at beginning of frame
2419 void R_Mesh_Start(void)
2422 R_Mesh_ResetRenderTargets();
2424 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2426 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2427 Cvar_SetValueQuick(&gl_paranoid, 1);
2431 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2435 char compilelog[MAX_INPUTLINE];
2436 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2439 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2440 qglCompileShader(shaderobject);CHECKGLERROR
2441 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2442 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2443 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2445 int i, j, pretextlines = 0;
2446 for (i = 0;i < numstrings - 1;i++)
2447 for (j = 0;strings[i][j];j++)
2448 if (strings[i][j] == '\n')
2450 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2452 if (!shadercompiled)
2454 qglDeleteShader(shaderobject);CHECKGLERROR
2457 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2458 qglDeleteShader(shaderobject);CHECKGLERROR
2462 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)
2464 GLint programlinked;
2465 GLuint programobject = 0;
2466 char linklog[MAX_INPUTLINE];
2469 programobject = qglCreateProgram();CHECKGLERROR
2473 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2474 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2475 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2476 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2477 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2478 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2479 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2480 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2481 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2482 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2483 if(vid.support.gl20shaders130)
2484 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2486 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2489 #ifdef GL_GEOMETRY_SHADER
2490 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2494 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2497 qglLinkProgram(programobject);CHECKGLERROR
2498 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2499 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2502 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2503 Con_DPrintf("program link log:\n%s\n", linklog);
2504 // software vertex shader is ok but software fragment shader is WAY
2505 // too slow, fail program if so.
2506 // NOTE: this string might be ATI specific, but that's ok because the
2507 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2508 // software fragment shader due to low instruction and dependent
2510 if (strstr(linklog, "fragment shader will run in software"))
2511 programlinked = false;
2515 return programobject;
2517 qglDeleteProgram(programobject);CHECKGLERROR
2521 void GL_Backend_FreeProgram(unsigned int prog)
2524 qglDeleteProgram(prog);
2528 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2533 for (i = 0;i < count;i++)
2534 *out++ = *in++ + offset;
2537 memcpy(out, in, sizeof(*out) * count);
2540 // renders triangles using vertices from the active arrays
2541 int paranoidblah = 0;
2542 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)
2544 unsigned int numelements = numtriangles * 3;
2546 size_t bufferoffset3i;
2548 size_t bufferoffset3s;
2549 if (numvertices < 3 || numtriangles < 1)
2551 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2552 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);
2555 if (!gl_mesh_prefer_short_elements.integer)
2559 if (element3i_indexbuffer)
2560 element3i_indexbuffer = NULL;
2562 // adjust the pointers for firsttriangle
2564 element3i += firsttriangle * 3;
2565 if (element3i_indexbuffer)
2566 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2568 element3s += firsttriangle * 3;
2569 if (element3s_indexbuffer)
2570 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2571 switch(vid.renderpath)
2573 case RENDERPATH_GL11:
2574 case RENDERPATH_GL13:
2575 case RENDERPATH_GL20:
2576 case RENDERPATH_GLES1:
2577 case RENDERPATH_GLES2:
2578 // check if the user specified to ignore static index buffers
2579 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2581 element3i_indexbuffer = NULL;
2582 element3s_indexbuffer = NULL;
2585 case RENDERPATH_D3D9:
2586 case RENDERPATH_D3D10:
2587 case RENDERPATH_D3D11:
2589 case RENDERPATH_SOFT:
2592 // upload a dynamic index buffer if needed
2595 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2597 if (gl_state.draw_dynamicindexbuffer)
2598 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2600 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2601 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2602 element3s_bufferoffset = 0;
2607 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2609 if (gl_state.draw_dynamicindexbuffer)
2610 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2612 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2613 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2614 element3i_bufferoffset = 0;
2617 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2618 bufferoffset3i = element3i_bufferoffset;
2619 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2620 bufferoffset3s = element3s_bufferoffset;
2621 r_refdef.stats.draws++;
2622 r_refdef.stats.draws_vertices += numvertices;
2623 r_refdef.stats.draws_elements += numelements;
2624 if (gl_paranoid.integer)
2627 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2629 unsigned int j, size;
2631 // note: there's no validation done here on buffer objects because it
2632 // is somewhat difficult to get at the data, and gl_paranoid can be
2633 // used without buffer objects if the need arises
2634 // (the data could be gotten using glMapBuffer but it would be very
2635 // slow due to uncachable video memory reads)
2636 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2637 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2639 if (gl_state.pointer_vertex_pointer)
2640 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2642 if (gl_state.pointer_color_enabled)
2644 if (!qglIsEnabled(GL_COLOR_ARRAY))
2645 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2647 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2648 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2651 for (i = 0;i < vid.texarrayunits;i++)
2653 if (gl_state.units[i].arrayenabled)
2655 GL_ClientActiveTexture(i);
2656 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2657 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2659 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2660 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++)
2667 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2669 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2671 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2678 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2680 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2682 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2688 if (r_render.integer || r_refdef.draw2dstage)
2690 switch(vid.renderpath)
2692 case RENDERPATH_GL11:
2693 case RENDERPATH_GL13:
2694 case RENDERPATH_GL20:
2696 if (gl_mesh_testmanualfeeding.integer)
2698 unsigned int i, j, element;
2700 qglBegin(GL_TRIANGLES);
2701 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2704 element = element3i[i];
2706 element = element3s[i];
2708 element = firstvertex + i;
2709 for (j = 0;j < vid.texarrayunits;j++)
2711 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2713 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2715 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2716 if (vid.texarrayunits > 1)
2718 if (gl_state.units[j].pointer_texcoord_components == 4)
2719 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2720 else if (gl_state.units[j].pointer_texcoord_components == 3)
2721 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2722 else if (gl_state.units[j].pointer_texcoord_components == 2)
2723 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2725 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2729 if (gl_state.units[j].pointer_texcoord_components == 4)
2730 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2731 else if (gl_state.units[j].pointer_texcoord_components == 3)
2732 qglTexCoord3f(p[0], p[1], p[2]);
2733 else if (gl_state.units[j].pointer_texcoord_components == 2)
2734 qglTexCoord2f(p[0], p[1]);
2736 qglTexCoord1f(p[0]);
2739 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2741 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2742 if (vid.texarrayunits > 1)
2744 if (gl_state.units[j].pointer_texcoord_components == 4)
2745 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2746 else if (gl_state.units[j].pointer_texcoord_components == 3)
2747 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2748 else if (gl_state.units[j].pointer_texcoord_components == 2)
2749 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2750 else if (gl_state.units[j].pointer_texcoord_components == 1)
2751 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2755 if (gl_state.units[j].pointer_texcoord_components == 4)
2756 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2757 else if (gl_state.units[j].pointer_texcoord_components == 3)
2758 qglTexCoord3f(s[0], s[1], s[2]);
2759 else if (gl_state.units[j].pointer_texcoord_components == 2)
2760 qglTexCoord2f(s[0], s[1]);
2761 else if (gl_state.units[j].pointer_texcoord_components == 1)
2762 qglTexCoord1f(s[0]);
2765 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2767 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2768 if (vid.texarrayunits > 1)
2770 if (gl_state.units[j].pointer_texcoord_components == 4)
2771 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2772 else if (gl_state.units[j].pointer_texcoord_components == 3)
2773 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2774 else if (gl_state.units[j].pointer_texcoord_components == 2)
2775 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2776 else if (gl_state.units[j].pointer_texcoord_components == 1)
2777 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2781 if (gl_state.units[j].pointer_texcoord_components == 4)
2782 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2783 else if (gl_state.units[j].pointer_texcoord_components == 3)
2784 qglTexCoord3f(sb[0], sb[1], sb[2]);
2785 else if (gl_state.units[j].pointer_texcoord_components == 2)
2786 qglTexCoord2f(sb[0], sb[1]);
2787 else if (gl_state.units[j].pointer_texcoord_components == 1)
2788 qglTexCoord1f(sb[0]);
2793 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2795 if (gl_state.pointer_color_gltype == GL_FLOAT)
2797 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2798 qglColor4f(p[0], p[1], p[2], p[3]);
2800 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2802 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2803 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2806 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2808 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2809 if (gl_state.pointer_vertex_components == 4)
2810 qglVertex4f(p[0], p[1], p[2], p[3]);
2811 else if (gl_state.pointer_vertex_components == 3)
2812 qglVertex3f(p[0], p[1], p[2]);
2814 qglVertex2f(p[0], p[1]);
2820 else if (bufferobject3s)
2822 GL_BindEBO(bufferobject3s);
2823 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2825 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2830 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2834 else if (bufferobject3i)
2836 GL_BindEBO(bufferobject3i);
2837 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2839 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2844 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2851 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2853 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2858 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2865 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2867 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2872 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2878 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2882 case RENDERPATH_D3D9:
2884 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2886 if (element3s_indexbuffer)
2888 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2889 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2891 else if (element3i_indexbuffer)
2893 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2894 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2897 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2902 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2904 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2906 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2910 case RENDERPATH_D3D10:
2911 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2913 case RENDERPATH_D3D11:
2914 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2916 case RENDERPATH_SOFT:
2917 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2919 case RENDERPATH_GLES1:
2920 case RENDERPATH_GLES2:
2921 // GLES does not have glDrawRangeElements, and generally
2922 // underperforms with index buffers, so this code path is
2923 // relatively straightforward...
2925 if (gl_paranoid.integer)
2927 int r, prog, enabled, i;
2928 GLsizei attriblength;
2931 GLchar attribname[1024];
2932 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2933 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2934 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2935 #ifndef GL_CURRENT_PROGRAM
2936 #define GL_CURRENT_PROGRAM 0x8B8D
2938 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2939 if (r < 0 || r > 10000)
2940 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2942 for (i = 0;i < 8;i++)
2944 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2947 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2948 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);
2954 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2959 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2964 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2972 // restores backend state, used when done with 3D rendering
2973 void R_Mesh_Finish(void)
2975 R_Mesh_ResetRenderTargets();
2978 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2980 r_meshbuffer_t *buffer;
2981 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2983 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2984 memset(buffer, 0, sizeof(*buffer));
2985 buffer->bufferobject = 0;
2986 buffer->devicebuffer = NULL;
2988 buffer->isindexbuffer = isindexbuffer;
2989 buffer->isdynamic = isdynamic;
2990 buffer->isindex16 = isindex16;
2991 strlcpy(buffer->name, name, sizeof(buffer->name));
2992 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2996 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
3000 if (buffer->isindexbuffer)
3002 r_refdef.stats.indexbufferuploadcount++;
3003 r_refdef.stats.indexbufferuploadsize += size;
3007 r_refdef.stats.vertexbufferuploadcount++;
3008 r_refdef.stats.vertexbufferuploadsize += size;
3010 switch(vid.renderpath)
3012 case RENDERPATH_GL11:
3013 case RENDERPATH_GL13:
3014 case RENDERPATH_GL20:
3015 case RENDERPATH_GLES1:
3016 case RENDERPATH_GLES2:
3017 if (!buffer->bufferobject)
3018 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3019 if (buffer->isindexbuffer)
3020 GL_BindEBO(buffer->bufferobject);
3022 GL_BindVBO(buffer->bufferobject);
3023 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
3025 case RENDERPATH_D3D9:
3029 void *datapointer = NULL;
3030 if (buffer->isindexbuffer)
3032 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3033 if (size > buffer->size || !buffer->devicebuffer)
3035 if (buffer->devicebuffer)
3036 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3037 buffer->devicebuffer = NULL;
3038 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)))
3039 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);
3040 buffer->devicebuffer = (void *)d3d9indexbuffer;
3041 buffer->size = size;
3043 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3046 memcpy(datapointer, data, size);
3048 memset(datapointer, 0, size);
3049 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3054 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3055 if (size > buffer->size || !buffer->devicebuffer)
3057 if (buffer->devicebuffer)
3058 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3059 buffer->devicebuffer = NULL;
3060 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3061 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);
3062 buffer->devicebuffer = (void *)d3d9vertexbuffer;
3063 buffer->size = size;
3065 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3068 memcpy(datapointer, data, size);
3070 memset(datapointer, 0, size);
3071 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3077 case RENDERPATH_D3D10:
3078 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3080 case RENDERPATH_D3D11:
3081 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3083 case RENDERPATH_SOFT:
3088 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3092 switch(vid.renderpath)
3094 case RENDERPATH_GL11:
3095 case RENDERPATH_GL13:
3096 case RENDERPATH_GL20:
3097 case RENDERPATH_GLES1:
3098 case RENDERPATH_GLES2:
3099 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3101 case RENDERPATH_D3D9:
3103 if (gl_state.d3dvertexbuffer == (void *)buffer)
3104 gl_state.d3dvertexbuffer = NULL;
3105 if (buffer->devicebuffer)
3107 if (buffer->isindexbuffer)
3108 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3110 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3111 buffer->devicebuffer = NULL;
3115 case RENDERPATH_D3D10:
3116 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3118 case RENDERPATH_D3D11:
3119 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3121 case RENDERPATH_SOFT:
3124 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3127 void GL_Mesh_ListVBOs(qboolean printeach)
3130 size_t ebocount = 0, ebomemory = 0;
3131 size_t vbocount = 0, vbomemory = 0;
3132 r_meshbuffer_t *buffer;
3133 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3134 for (i = 0;i < endindex;i++)
3136 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3139 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)");}
3140 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)");}
3142 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);
3147 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3149 switch(vid.renderpath)
3151 case RENDERPATH_GL11:
3152 case RENDERPATH_GL13:
3153 case RENDERPATH_GLES1:
3154 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)
3156 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3157 gl_state.pointer_vertex_components = components;
3158 gl_state.pointer_vertex_gltype = gltype;
3159 gl_state.pointer_vertex_stride = stride;
3160 gl_state.pointer_vertex_pointer = pointer;
3161 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3162 gl_state.pointer_vertex_offset = bufferoffset;
3164 GL_BindVBO(bufferobject);
3165 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3168 case RENDERPATH_GL20:
3169 case RENDERPATH_GLES2:
3170 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)
3172 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3173 gl_state.pointer_vertex_components = components;
3174 gl_state.pointer_vertex_gltype = gltype;
3175 gl_state.pointer_vertex_stride = stride;
3176 gl_state.pointer_vertex_pointer = pointer;
3177 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3178 gl_state.pointer_vertex_offset = bufferoffset;
3180 GL_BindVBO(bufferobject);
3181 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3184 case RENDERPATH_D3D9:
3185 case RENDERPATH_D3D10:
3186 case RENDERPATH_D3D11:
3187 case RENDERPATH_SOFT:
3192 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3194 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3195 // the pointer only.
3196 switch(vid.renderpath)
3198 case RENDERPATH_GL11:
3199 case RENDERPATH_GL13:
3200 case RENDERPATH_GLES1:
3204 // caller wants color array enabled
3205 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3206 if (!gl_state.pointer_color_enabled)
3208 gl_state.pointer_color_enabled = true;
3210 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3212 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)
3214 gl_state.pointer_color_components = components;
3215 gl_state.pointer_color_gltype = gltype;
3216 gl_state.pointer_color_stride = stride;
3217 gl_state.pointer_color_pointer = pointer;
3218 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3219 gl_state.pointer_color_offset = bufferoffset;
3221 GL_BindVBO(bufferobject);
3222 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3227 // caller wants color array disabled
3228 if (gl_state.pointer_color_enabled)
3230 gl_state.pointer_color_enabled = false;
3232 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3233 // when color array is on the glColor gets trashed, set it again
3234 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3238 case RENDERPATH_GL20:
3239 case RENDERPATH_GLES2:
3243 // caller wants color array enabled
3244 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3245 if (!gl_state.pointer_color_enabled)
3247 gl_state.pointer_color_enabled = true;
3249 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3251 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)
3253 gl_state.pointer_color_components = components;
3254 gl_state.pointer_color_gltype = gltype;
3255 gl_state.pointer_color_stride = stride;
3256 gl_state.pointer_color_pointer = pointer;
3257 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3258 gl_state.pointer_color_offset = bufferoffset;
3260 GL_BindVBO(bufferobject);
3261 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3266 // caller wants color array disabled
3267 if (gl_state.pointer_color_enabled)
3269 gl_state.pointer_color_enabled = false;
3271 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3272 // when color array is on the glColor gets trashed, set it again
3273 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3277 case RENDERPATH_D3D9:
3278 case RENDERPATH_D3D10:
3279 case RENDERPATH_D3D11:
3280 case RENDERPATH_SOFT:
3285 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)
3287 gltextureunit_t *unit = gl_state.units + unitnum;
3288 // update array settings
3289 // note: there is no need to check bufferobject here because all cases
3290 // that involve a valid bufferobject also supply a texcoord array
3291 switch(vid.renderpath)
3293 case RENDERPATH_GL11:
3294 case RENDERPATH_GL13:
3295 case RENDERPATH_GLES1:
3299 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3300 // texture array unit is enabled, enable the array
3301 if (!unit->arrayenabled)
3303 unit->arrayenabled = true;
3304 GL_ClientActiveTexture(unitnum);
3305 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3308 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)
3310 unit->pointer_texcoord_components = components;
3311 unit->pointer_texcoord_gltype = gltype;
3312 unit->pointer_texcoord_stride = stride;
3313 unit->pointer_texcoord_pointer = pointer;
3314 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3315 unit->pointer_texcoord_offset = bufferoffset;
3316 GL_ClientActiveTexture(unitnum);
3317 GL_BindVBO(bufferobject);
3318 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3323 // texture array unit is disabled, disable the array
3324 if (unit->arrayenabled)
3326 unit->arrayenabled = false;
3327 GL_ClientActiveTexture(unitnum);
3328 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3332 case RENDERPATH_GL20:
3333 case RENDERPATH_GLES2:
3337 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3338 // texture array unit is enabled, enable the array
3339 if (!unit->arrayenabled)
3341 unit->arrayenabled = true;
3342 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3345 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)
3347 unit->pointer_texcoord_components = components;
3348 unit->pointer_texcoord_gltype = gltype;
3349 unit->pointer_texcoord_stride = stride;
3350 unit->pointer_texcoord_pointer = pointer;
3351 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3352 unit->pointer_texcoord_offset = bufferoffset;
3353 GL_BindVBO(bufferobject);
3354 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3359 // texture array unit is disabled, disable the array
3360 if (unit->arrayenabled)
3362 unit->arrayenabled = false;
3363 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3367 case RENDERPATH_D3D9:
3368 case RENDERPATH_D3D10:
3369 case RENDERPATH_D3D11:
3370 case RENDERPATH_SOFT:
3375 int R_Mesh_TexBound(unsigned int unitnum, int id)
3377 gltextureunit_t *unit = gl_state.units + unitnum;
3378 if (unitnum >= vid.teximageunits)
3380 if (id == GL_TEXTURE_2D)
3382 if (id == GL_TEXTURE_3D)
3384 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3385 return unit->tcubemap;
3389 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3391 switch(vid.renderpath)
3393 case RENDERPATH_GL11:
3394 case RENDERPATH_GL13:
3395 case RENDERPATH_GL20:
3396 case RENDERPATH_GLES1:
3397 case RENDERPATH_GLES2:
3398 R_Mesh_TexBind(0, tex);
3399 GL_ActiveTexture(0);CHECKGLERROR
3400 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3402 case RENDERPATH_D3D9:
3405 IDirect3DSurface9 *currentsurface = NULL;
3406 IDirect3DSurface9 *texturesurface = NULL;
3409 sourcerect.left = sx;
3410 sourcerect.top = sy;
3411 sourcerect.right = sx + width;
3412 sourcerect.bottom = sy + height;
3415 destrect.right = tx + width;
3416 destrect.bottom = ty + height;
3417 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3419 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3421 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3422 IDirect3DSurface9_Release(currentsurface);
3424 IDirect3DSurface9_Release(texturesurface);
3429 case RENDERPATH_D3D10:
3430 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3432 case RENDERPATH_D3D11:
3433 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3435 case RENDERPATH_SOFT:
3436 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3442 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};
3445 void R_Mesh_ClearBindingsForTexture(int texnum)
3447 gltextureunit_t *unit;
3448 unsigned int unitnum;
3449 // 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)
3450 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3452 unit = gl_state.units + unitnum;
3453 if (unit->t2d == texnum)
3455 if (unit->t3d == texnum)
3457 if (unit->tcubemap == texnum)
3458 unit->tcubemap = -1;
3462 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3464 gltextureunit_t *unit = gl_state.units + unitnum;
3465 int tex2d, tex3d, texcubemap, texnum;
3466 if (unitnum >= vid.teximageunits)
3468 // if (unit->texture == tex)
3470 switch(vid.renderpath)
3472 case RENDERPATH_GL20:
3473 case RENDERPATH_GLES2:
3476 tex = r_texture_white;
3477 // not initialized enough yet...
3481 unit->texture = tex;
3482 texnum = R_GetTexture(tex);
3483 switch(tex->gltexturetypeenum)
3485 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3486 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3487 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;
3490 case RENDERPATH_GL11:
3491 case RENDERPATH_GL13:
3492 case RENDERPATH_GLES1:
3493 unit->texture = tex;
3499 texnum = R_GetTexture(tex);
3500 switch(tex->gltexturetypeenum)
3508 case GL_TEXTURE_CUBE_MAP_ARB:
3509 texcubemap = texnum;
3513 // update 2d texture binding
3514 if (unit->t2d != tex2d)
3516 GL_ActiveTexture(unitnum);
3521 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3528 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3532 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3534 // update 3d texture binding
3535 if (unit->t3d != tex3d)
3537 GL_ActiveTexture(unitnum);
3542 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3549 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3553 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3555 // update cubemap texture binding
3556 if (unit->tcubemap != texcubemap)
3558 GL_ActiveTexture(unitnum);
3561 if (unit->tcubemap == 0)
3563 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3570 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3573 unit->tcubemap = texcubemap;
3574 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3577 case RENDERPATH_D3D9:
3580 extern cvar_t gl_texture_anisotropy;
3583 tex = r_texture_white;
3584 // not initialized enough yet...
3588 // upload texture if needed
3590 if (unit->texture == tex)
3592 unit->texture = tex;
3593 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3594 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3595 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3596 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3597 if (tex->d3daddressw)
3598 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3599 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3600 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3601 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3602 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3603 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3604 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3608 case RENDERPATH_D3D10:
3609 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3611 case RENDERPATH_D3D11:
3612 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3614 case RENDERPATH_SOFT:
3617 tex = r_texture_white;
3618 // not initialized enough yet...
3622 texnum = R_GetTexture(tex);
3623 if (unit->texture == tex)
3625 unit->texture = tex;
3626 DPSOFTRAST_SetTexture(unitnum, texnum);
3631 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3633 gltextureunit_t *unit = gl_state.units + unitnum;
3634 switch(vid.renderpath)
3636 case RENDERPATH_GL11:
3637 case RENDERPATH_GL13:
3638 case RENDERPATH_GL20:
3639 case RENDERPATH_GLES1:
3640 case RENDERPATH_GLES2:
3641 if (matrix && matrix->m[3][3])
3643 // texmatrix specified, check if it is different
3644 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3647 unit->texmatrixenabled = true;
3648 unit->matrix = *matrix;
3650 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3651 GL_ActiveTexture(unitnum);
3652 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3653 qglLoadMatrixf(glmatrix);CHECKGLERROR
3654 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3659 // no texmatrix specified, revert to identity
3660 if (unit->texmatrixenabled)
3662 unit->texmatrixenabled = false;
3663 unit->matrix = identitymatrix;
3665 GL_ActiveTexture(unitnum);
3666 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3667 qglLoadIdentity();CHECKGLERROR
3668 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3672 case RENDERPATH_D3D9:
3673 case RENDERPATH_D3D10:
3674 case RENDERPATH_D3D11:
3676 case RENDERPATH_SOFT:
3681 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3683 gltextureunit_t *unit = gl_state.units + unitnum;
3685 switch(vid.renderpath)
3687 case RENDERPATH_GL20:
3688 case RENDERPATH_GLES2:
3691 case RENDERPATH_GL13:
3692 case RENDERPATH_GLES1:
3693 // GL_ARB_texture_env_combine
3695 combinergb = GL_MODULATE;
3697 combinealpha = GL_MODULATE;
3702 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3704 if (combinergb == GL_DECAL)
3705 combinergb = GL_INTERPOLATE_ARB;
3706 if (unit->combine != GL_COMBINE_ARB)
3708 unit->combine = GL_COMBINE_ARB;
3709 GL_ActiveTexture(unitnum);
3710 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3711 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3713 if (unit->combinergb != combinergb)
3715 unit->combinergb = combinergb;
3716 GL_ActiveTexture(unitnum);
3717 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3719 if (unit->combinealpha != combinealpha)
3721 unit->combinealpha = combinealpha;
3722 GL_ActiveTexture(unitnum);
3723 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3725 if (unit->rgbscale != rgbscale)
3727 unit->rgbscale = rgbscale;
3728 GL_ActiveTexture(unitnum);
3729 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3731 if (unit->alphascale != alphascale)
3733 unit->alphascale = alphascale;
3734 GL_ActiveTexture(unitnum);
3735 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3740 if (unit->combine != combinergb)
3742 unit->combine = combinergb;
3743 GL_ActiveTexture(unitnum);
3744 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3748 case RENDERPATH_GL11:
3751 combinergb = GL_MODULATE;
3752 if (unit->combine != combinergb)
3754 unit->combine = combinergb;
3755 GL_ActiveTexture(unitnum);
3756 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3759 case RENDERPATH_D3D9:
3760 case RENDERPATH_D3D10:
3761 case RENDERPATH_D3D11:
3763 case RENDERPATH_SOFT:
3768 void R_Mesh_ResetTextureState(void)
3770 unsigned int unitnum;
3774 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3775 R_Mesh_TexBind(unitnum, NULL);
3776 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3777 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3778 switch(vid.renderpath)
3780 case RENDERPATH_GL20:
3781 case RENDERPATH_GLES2:
3782 case RENDERPATH_D3D9:
3783 case RENDERPATH_D3D10:
3784 case RENDERPATH_D3D11:
3785 case RENDERPATH_SOFT:
3787 case RENDERPATH_GL11:
3788 case RENDERPATH_GL13:
3789 case RENDERPATH_GLES1:
3790 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3792 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3793 R_Mesh_TexMatrix(unitnum, NULL);
3802 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3803 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3804 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3806 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3808 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3812 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3814 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3815 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3816 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3820 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3822 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3823 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3824 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3825 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3826 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3827 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3828 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3832 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3833 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3834 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3837 static void R_Mesh_InitVertexDeclarations(void)
3840 r_vertex3f_d3d9decl = NULL;
3841 r_vertexgeneric_d3d9decl = NULL;
3842 r_vertexmesh_d3d9decl = NULL;
3843 switch(vid.renderpath)
3845 case RENDERPATH_GL20:
3846 case RENDERPATH_GL13:
3847 case RENDERPATH_GL11:
3848 case RENDERPATH_GLES1:
3849 case RENDERPATH_GLES2:
3851 case RENDERPATH_D3D9:
3852 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3853 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3854 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3856 case RENDERPATH_D3D10:
3857 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3859 case RENDERPATH_D3D11:
3860 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3862 case RENDERPATH_SOFT:
3868 static void R_Mesh_DestroyVertexDeclarations(void)
3871 if (r_vertex3f_d3d9decl)
3872 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3873 r_vertex3f_d3d9decl = NULL;
3874 if (r_vertexgeneric_d3d9decl)
3875 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3876 r_vertexgeneric_d3d9decl = NULL;
3877 if (r_vertexmesh_d3d9decl)
3878 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3879 r_vertexmesh_d3d9decl = NULL;
3883 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3885 // upload temporary vertexbuffer for this rendering
3886 if (!gl_state.usevbo_staticvertex)
3887 vertexbuffer = NULL;
3888 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3890 if (gl_state.preparevertices_dynamicvertexbuffer)
3891 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3893 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3894 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3896 switch(vid.renderpath)
3898 case RENDERPATH_GL20:
3899 case RENDERPATH_GLES2:
3902 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3903 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3904 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3905 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3906 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3907 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3908 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3912 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3913 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3914 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3915 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3916 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3917 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3918 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3921 case RENDERPATH_GL13:
3922 case RENDERPATH_GLES1:
3925 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3926 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3927 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3928 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3932 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3933 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3934 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3935 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3938 case RENDERPATH_GL11:
3941 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3942 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3943 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3947 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3948 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3949 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3952 case RENDERPATH_D3D9:
3954 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3956 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3958 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3959 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3960 gl_state.d3dvertexdata = (void *)vertex3f;
3961 gl_state.d3dvertexsize = sizeof(float[3]);
3964 case RENDERPATH_D3D10:
3965 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3967 case RENDERPATH_D3D11:
3968 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3970 case RENDERPATH_SOFT:
3971 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3972 DPSOFTRAST_SetColorPointer(NULL, 0);
3973 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3974 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3975 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3976 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3977 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3984 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3987 size = sizeof(r_vertexgeneric_t) * numvertices;
3988 if (gl_state.preparevertices_tempdatamaxsize < size)
3990 gl_state.preparevertices_tempdatamaxsize = size;
3991 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3993 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3994 gl_state.preparevertices_numvertices = numvertices;
3995 return gl_state.preparevertices_vertexgeneric;
3998 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
4000 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4001 gl_state.preparevertices_vertexgeneric = NULL;
4002 gl_state.preparevertices_numvertices = 0;
4006 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4009 r_vertexgeneric_t *vertex;
4010 switch(vid.renderpath)
4012 case RENDERPATH_GL20:
4013 case RENDERPATH_GLES2:
4014 if (!vid.useinterleavedarrays)
4016 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4017 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4018 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4019 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4020 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4021 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4022 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4026 case RENDERPATH_GL11:
4027 case RENDERPATH_GL13:
4028 case RENDERPATH_GLES1:
4029 if (!vid.useinterleavedarrays)
4031 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4032 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4033 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4034 if (vid.texunits >= 2)
4035 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4036 if (vid.texunits >= 3)
4037 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4041 case RENDERPATH_D3D9:
4042 case RENDERPATH_D3D10:
4043 case RENDERPATH_D3D11:
4045 case RENDERPATH_SOFT:
4046 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4047 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4048 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4049 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4050 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4051 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4052 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4056 // no quick path for this case, convert to vertex structs
4057 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4058 for (i = 0;i < numvertices;i++)
4059 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4062 for (i = 0;i < numvertices;i++)
4063 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4067 for (i = 0;i < numvertices;i++)
4068 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4071 for (i = 0;i < numvertices;i++)
4072 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4073 R_Mesh_PrepareVertices_Generic_Unlock();
4074 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4077 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4079 // upload temporary vertexbuffer for this rendering
4080 if (!gl_state.usevbo_staticvertex)
4081 vertexbuffer = NULL;
4082 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4084 if (gl_state.preparevertices_dynamicvertexbuffer)
4085 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4087 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4088 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4090 switch(vid.renderpath)
4092 case RENDERPATH_GL20:
4093 case RENDERPATH_GLES2:
4096 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4097 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4098 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4099 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4100 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4101 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4102 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4106 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4107 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4108 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4109 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4110 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4111 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4112 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4115 case RENDERPATH_GL13:
4116 case RENDERPATH_GLES1:
4119 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4120 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4121 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4122 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4126 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4127 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4128 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4129 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4132 case RENDERPATH_GL11:
4135 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4136 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4137 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4141 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4142 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4143 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4146 case RENDERPATH_D3D9:
4148 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4150 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4152 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4153 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4154 gl_state.d3dvertexdata = (void *)vertex;
4155 gl_state.d3dvertexsize = sizeof(*vertex);
4158 case RENDERPATH_D3D10:
4159 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4161 case RENDERPATH_D3D11:
4162 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4164 case RENDERPATH_SOFT:
4165 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4166 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4167 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4168 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4169 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4170 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4171 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4178 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4181 size = sizeof(r_vertexmesh_t) * numvertices;
4182 if (gl_state.preparevertices_tempdatamaxsize < size)
4184 gl_state.preparevertices_tempdatamaxsize = size;
4185 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4187 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4188 gl_state.preparevertices_numvertices = numvertices;
4189 return gl_state.preparevertices_vertexmesh;
4192 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4194 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4195 gl_state.preparevertices_vertexmesh = NULL;
4196 gl_state.preparevertices_numvertices = 0;
4200 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)
4203 r_vertexmesh_t *vertex;
4204 switch(vid.renderpath)
4206 case RENDERPATH_GL20:
4207 case RENDERPATH_GLES2:
4208 if (!vid.useinterleavedarrays)
4210 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4211 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4212 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4213 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4214 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4215 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4216 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4220 case RENDERPATH_GL11:
4221 case RENDERPATH_GL13:
4222 case RENDERPATH_GLES1:
4223 if (!vid.useinterleavedarrays)
4225 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4226 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4227 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4228 if (vid.texunits >= 2)
4229 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4230 if (vid.texunits >= 3)
4231 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4235 case RENDERPATH_D3D9:
4236 case RENDERPATH_D3D10:
4237 case RENDERPATH_D3D11:
4239 case RENDERPATH_SOFT:
4240 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4241 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4242 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4243 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4244 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4245 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4246 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4250 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4251 for (i = 0;i < numvertices;i++)
4252 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4254 for (i = 0;i < numvertices;i++)
4255 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4257 for (i = 0;i < numvertices;i++)
4258 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4260 for (i = 0;i < numvertices;i++)
4261 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4264 for (i = 0;i < numvertices;i++)
4265 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4269 for (i = 0;i < numvertices;i++)
4270 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4272 if (texcoordtexture2f)
4273 for (i = 0;i < numvertices;i++)
4274 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4275 if (texcoordlightmap2f)
4276 for (i = 0;i < numvertices;i++)
4277 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4278 R_Mesh_PrepareVertices_Mesh_Unlock();
4279 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4282 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4284 // upload temporary vertexbuffer for this rendering
4285 if (!gl_state.usevbo_staticvertex)
4286 vertexbuffer = NULL;
4287 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4289 if (gl_state.preparevertices_dynamicvertexbuffer)
4290 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4292 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4293 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4295 switch(vid.renderpath)
4297 case RENDERPATH_GL20:
4298 case RENDERPATH_GLES2:
4301 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4302 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4303 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4304 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4305 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4306 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4307 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4311 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4312 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4313 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4314 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4315 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4316 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4317 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4320 case RENDERPATH_GL13:
4321 case RENDERPATH_GLES1:
4324 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4325 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4326 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4327 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4331 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4332 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4333 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4334 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4337 case RENDERPATH_GL11:
4340 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4341 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4342 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4346 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4347 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4348 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4351 case RENDERPATH_D3D9:
4353 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4355 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4357 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4358 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4359 gl_state.d3dvertexdata = (void *)vertex;
4360 gl_state.d3dvertexsize = sizeof(*vertex);
4363 case RENDERPATH_D3D10:
4364 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4366 case RENDERPATH_D3D11:
4367 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4369 case RENDERPATH_SOFT:
4370 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4371 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4372 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4373 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4374 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4375 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4376 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);