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((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((r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR
2141 qglDisable((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:
2158 if (vid_multisampling.integer)
2160 if (gl_state.alphatest && r_transparent_alphatocoverage.integer)
2161 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
2163 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
2171 void GL_ColorMask(int r, int g, int b, int a)
2173 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2174 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2175 if (gl_state.colormask != state)
2177 gl_state.colormask = state;
2178 switch(vid.renderpath)
2180 case RENDERPATH_GL11:
2181 case RENDERPATH_GL13:
2182 case RENDERPATH_GL20:
2183 case RENDERPATH_GLES1:
2184 case RENDERPATH_GLES2:
2186 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2188 case RENDERPATH_D3D9:
2190 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2193 case RENDERPATH_D3D10:
2194 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2196 case RENDERPATH_D3D11:
2197 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2199 case RENDERPATH_SOFT:
2200 DPSOFTRAST_ColorMask(r, g, b, a);
2206 void GL_Color(float cr, float cg, float cb, float ca)
2208 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)
2210 gl_state.color4f[0] = cr;
2211 gl_state.color4f[1] = cg;
2212 gl_state.color4f[2] = cb;
2213 gl_state.color4f[3] = ca;
2214 switch(vid.renderpath)
2216 case RENDERPATH_GL11:
2217 case RENDERPATH_GL13:
2218 case RENDERPATH_GLES1:
2220 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2223 case RENDERPATH_D3D9:
2224 case RENDERPATH_D3D10:
2225 case RENDERPATH_D3D11:
2226 // no equivalent in D3D
2228 case RENDERPATH_SOFT:
2229 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2231 case RENDERPATH_GL20:
2232 case RENDERPATH_GLES2:
2233 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2239 void GL_Scissor (int x, int y, int width, int height)
2241 switch(vid.renderpath)
2243 case RENDERPATH_GL11:
2244 case RENDERPATH_GL13:
2245 case RENDERPATH_GL20:
2246 case RENDERPATH_GLES1:
2247 case RENDERPATH_GLES2:
2249 qglScissor(x, y,width,height);
2252 case RENDERPATH_D3D9:
2258 d3drect.right = x + width;
2259 d3drect.bottom = y + height;
2260 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2264 case RENDERPATH_D3D10:
2265 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2267 case RENDERPATH_D3D11:
2268 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2270 case RENDERPATH_SOFT:
2271 DPSOFTRAST_Scissor(x, y, width, height);
2276 void GL_ScissorTest(int state)
2278 if (gl_state.scissortest != state)
2280 gl_state.scissortest = state;
2281 switch(vid.renderpath)
2283 case RENDERPATH_GL11:
2284 case RENDERPATH_GL13:
2285 case RENDERPATH_GL20:
2286 case RENDERPATH_GLES1:
2287 case RENDERPATH_GLES2:
2289 if(gl_state.scissortest)
2290 qglEnable(GL_SCISSOR_TEST);
2292 qglDisable(GL_SCISSOR_TEST);
2295 case RENDERPATH_D3D9:
2297 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2300 case RENDERPATH_D3D10:
2301 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2303 case RENDERPATH_D3D11:
2304 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2306 case RENDERPATH_SOFT:
2307 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2313 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2315 static const float blackcolor[4] = {0, 0, 0, 0};
2316 // prevent warnings when trying to clear a buffer that does not exist
2318 colorvalue = blackcolor;
2321 mask &= ~GL_STENCIL_BUFFER_BIT;
2324 switch(vid.renderpath)
2326 case RENDERPATH_GL11:
2327 case RENDERPATH_GL13:
2328 case RENDERPATH_GL20:
2329 case RENDERPATH_GLES1:
2330 case RENDERPATH_GLES2:
2332 if (mask & GL_COLOR_BUFFER_BIT)
2334 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2336 if (mask & GL_DEPTH_BUFFER_BIT)
2338 qglClearDepth(depthvalue);CHECKGLERROR
2340 if (mask & GL_STENCIL_BUFFER_BIT)
2342 qglClearStencil(stencilvalue);CHECKGLERROR
2344 qglClear(mask);CHECKGLERROR
2346 case RENDERPATH_D3D9:
2348 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);
2351 case RENDERPATH_D3D10:
2352 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2354 case RENDERPATH_D3D11:
2355 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2357 case RENDERPATH_SOFT:
2358 if (mask & GL_COLOR_BUFFER_BIT)
2359 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2360 if (mask & GL_DEPTH_BUFFER_BIT)
2361 DPSOFTRAST_ClearDepth(depthvalue);
2366 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2368 switch(vid.renderpath)
2370 case RENDERPATH_GL11:
2371 case RENDERPATH_GL13:
2372 case RENDERPATH_GL20:
2373 case RENDERPATH_GLES1:
2374 case RENDERPATH_GLES2:
2376 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2378 case RENDERPATH_D3D9:
2381 // LordHavoc: we can't directly download the backbuffer because it may be
2382 // multisampled, and it may not be lockable, so we blit it to a lockable
2383 // surface of the same dimensions (but without multisample) to resolve the
2384 // multisample buffer to a normal image, and then lock that...
2385 IDirect3DSurface9 *stretchsurface = NULL;
2386 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2388 D3DLOCKED_RECT lockedrect;
2389 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2391 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2394 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2395 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2396 memcpy(outpixels + line * width * 4, row, width * 4);
2397 IDirect3DSurface9_UnlockRect(stretchsurface);
2400 IDirect3DSurface9_Release(stretchsurface);
2403 //IDirect3DSurface9 *syssurface = NULL;
2404 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2405 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2406 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2407 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2408 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2409 //IDirect3DSurface9_UnlockRect(syssurface);
2410 //IDirect3DSurface9_Release(syssurface);
2414 case RENDERPATH_D3D10:
2415 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2417 case RENDERPATH_D3D11:
2418 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2420 case RENDERPATH_SOFT:
2421 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2426 // called at beginning of frame
2427 void R_Mesh_Start(void)
2430 R_Mesh_ResetRenderTargets();
2432 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2434 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2435 Cvar_SetValueQuick(&gl_paranoid, 1);
2439 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2443 char compilelog[MAX_INPUTLINE];
2444 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2447 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2448 qglCompileShader(shaderobject);CHECKGLERROR
2449 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2450 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2451 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2453 int i, j, pretextlines = 0;
2454 for (i = 0;i < numstrings - 1;i++)
2455 for (j = 0;strings[i][j];j++)
2456 if (strings[i][j] == '\n')
2458 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2460 if (!shadercompiled)
2462 qglDeleteShader(shaderobject);CHECKGLERROR
2465 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2466 qglDeleteShader(shaderobject);CHECKGLERROR
2470 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)
2472 GLint programlinked;
2473 GLuint programobject = 0;
2474 char linklog[MAX_INPUTLINE];
2477 programobject = qglCreateProgram();CHECKGLERROR
2481 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2482 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2483 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2484 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2485 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2486 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2487 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2488 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2489 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2490 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2491 if(vid.support.gl20shaders130)
2492 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2494 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2497 #ifdef GL_GEOMETRY_SHADER
2498 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2502 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2505 qglLinkProgram(programobject);CHECKGLERROR
2506 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2507 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2510 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2511 Con_DPrintf("program link log:\n%s\n", linklog);
2512 // software vertex shader is ok but software fragment shader is WAY
2513 // too slow, fail program if so.
2514 // NOTE: this string might be ATI specific, but that's ok because the
2515 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2516 // software fragment shader due to low instruction and dependent
2518 if (strstr(linklog, "fragment shader will run in software"))
2519 programlinked = false;
2523 return programobject;
2525 qglDeleteProgram(programobject);CHECKGLERROR
2529 void GL_Backend_FreeProgram(unsigned int prog)
2532 qglDeleteProgram(prog);
2536 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2541 for (i = 0;i < count;i++)
2542 *out++ = *in++ + offset;
2545 memcpy(out, in, sizeof(*out) * count);
2548 // renders triangles using vertices from the active arrays
2549 int paranoidblah = 0;
2550 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)
2552 unsigned int numelements = numtriangles * 3;
2554 size_t bufferoffset3i;
2556 size_t bufferoffset3s;
2557 if (numvertices < 3 || numtriangles < 1)
2559 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2560 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);
2563 if (!gl_mesh_prefer_short_elements.integer)
2567 if (element3i_indexbuffer)
2568 element3i_indexbuffer = NULL;
2570 // adjust the pointers for firsttriangle
2572 element3i += firsttriangle * 3;
2573 if (element3i_indexbuffer)
2574 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2576 element3s += firsttriangle * 3;
2577 if (element3s_indexbuffer)
2578 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2579 switch(vid.renderpath)
2581 case RENDERPATH_GL11:
2582 case RENDERPATH_GL13:
2583 case RENDERPATH_GL20:
2584 case RENDERPATH_GLES1:
2585 case RENDERPATH_GLES2:
2586 // check if the user specified to ignore static index buffers
2587 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2589 element3i_indexbuffer = NULL;
2590 element3s_indexbuffer = NULL;
2593 case RENDERPATH_D3D9:
2594 case RENDERPATH_D3D10:
2595 case RENDERPATH_D3D11:
2597 case RENDERPATH_SOFT:
2600 // upload a dynamic index buffer if needed
2603 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2605 if (gl_state.draw_dynamicindexbuffer)
2606 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2608 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2609 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2610 element3s_bufferoffset = 0;
2615 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2617 if (gl_state.draw_dynamicindexbuffer)
2618 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2620 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2621 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2622 element3i_bufferoffset = 0;
2625 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2626 bufferoffset3i = element3i_bufferoffset;
2627 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2628 bufferoffset3s = element3s_bufferoffset;
2629 r_refdef.stats.draws++;
2630 r_refdef.stats.draws_vertices += numvertices;
2631 r_refdef.stats.draws_elements += numelements;
2632 if (gl_paranoid.integer)
2635 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2637 unsigned int j, size;
2639 // note: there's no validation done here on buffer objects because it
2640 // is somewhat difficult to get at the data, and gl_paranoid can be
2641 // used without buffer objects if the need arises
2642 // (the data could be gotten using glMapBuffer but it would be very
2643 // slow due to uncachable video memory reads)
2644 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2645 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2647 if (gl_state.pointer_vertex_pointer)
2648 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2650 if (gl_state.pointer_color_enabled)
2652 if (!qglIsEnabled(GL_COLOR_ARRAY))
2653 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2655 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2656 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2659 for (i = 0;i < vid.texarrayunits;i++)
2661 if (gl_state.units[i].arrayenabled)
2663 GL_ClientActiveTexture(i);
2664 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2665 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2667 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2668 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++)
2675 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2677 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2679 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2686 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2688 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2690 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2696 if (r_render.integer || r_refdef.draw2dstage)
2698 switch(vid.renderpath)
2700 case RENDERPATH_GL11:
2701 case RENDERPATH_GL13:
2702 case RENDERPATH_GL20:
2704 if (gl_mesh_testmanualfeeding.integer)
2706 unsigned int i, j, element;
2708 qglBegin(GL_TRIANGLES);
2709 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2712 element = element3i[i];
2714 element = element3s[i];
2716 element = firstvertex + i;
2717 for (j = 0;j < vid.texarrayunits;j++)
2719 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2721 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2723 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2724 if (vid.texarrayunits > 1)
2726 if (gl_state.units[j].pointer_texcoord_components == 4)
2727 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2728 else if (gl_state.units[j].pointer_texcoord_components == 3)
2729 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2730 else if (gl_state.units[j].pointer_texcoord_components == 2)
2731 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2733 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2737 if (gl_state.units[j].pointer_texcoord_components == 4)
2738 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2739 else if (gl_state.units[j].pointer_texcoord_components == 3)
2740 qglTexCoord3f(p[0], p[1], p[2]);
2741 else if (gl_state.units[j].pointer_texcoord_components == 2)
2742 qglTexCoord2f(p[0], p[1]);
2744 qglTexCoord1f(p[0]);
2747 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2749 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2750 if (vid.texarrayunits > 1)
2752 if (gl_state.units[j].pointer_texcoord_components == 4)
2753 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2754 else if (gl_state.units[j].pointer_texcoord_components == 3)
2755 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2756 else if (gl_state.units[j].pointer_texcoord_components == 2)
2757 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2758 else if (gl_state.units[j].pointer_texcoord_components == 1)
2759 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2763 if (gl_state.units[j].pointer_texcoord_components == 4)
2764 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2765 else if (gl_state.units[j].pointer_texcoord_components == 3)
2766 qglTexCoord3f(s[0], s[1], s[2]);
2767 else if (gl_state.units[j].pointer_texcoord_components == 2)
2768 qglTexCoord2f(s[0], s[1]);
2769 else if (gl_state.units[j].pointer_texcoord_components == 1)
2770 qglTexCoord1f(s[0]);
2773 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2775 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2776 if (vid.texarrayunits > 1)
2778 if (gl_state.units[j].pointer_texcoord_components == 4)
2779 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2780 else if (gl_state.units[j].pointer_texcoord_components == 3)
2781 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2782 else if (gl_state.units[j].pointer_texcoord_components == 2)
2783 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2784 else if (gl_state.units[j].pointer_texcoord_components == 1)
2785 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2789 if (gl_state.units[j].pointer_texcoord_components == 4)
2790 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2791 else if (gl_state.units[j].pointer_texcoord_components == 3)
2792 qglTexCoord3f(sb[0], sb[1], sb[2]);
2793 else if (gl_state.units[j].pointer_texcoord_components == 2)
2794 qglTexCoord2f(sb[0], sb[1]);
2795 else if (gl_state.units[j].pointer_texcoord_components == 1)
2796 qglTexCoord1f(sb[0]);
2801 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2803 if (gl_state.pointer_color_gltype == GL_FLOAT)
2805 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2806 qglColor4f(p[0], p[1], p[2], p[3]);
2808 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2810 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2811 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2814 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2816 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2817 if (gl_state.pointer_vertex_components == 4)
2818 qglVertex4f(p[0], p[1], p[2], p[3]);
2819 else if (gl_state.pointer_vertex_components == 3)
2820 qglVertex3f(p[0], p[1], p[2]);
2822 qglVertex2f(p[0], p[1]);
2828 else if (bufferobject3s)
2830 GL_BindEBO(bufferobject3s);
2831 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2833 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2838 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2842 else if (bufferobject3i)
2844 GL_BindEBO(bufferobject3i);
2845 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2847 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2852 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2859 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2861 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2866 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2873 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2875 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2880 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2886 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2890 case RENDERPATH_D3D9:
2892 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2894 if (element3s_indexbuffer)
2896 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2897 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2899 else if (element3i_indexbuffer)
2901 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2902 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2905 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2910 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2912 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2914 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2918 case RENDERPATH_D3D10:
2919 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2921 case RENDERPATH_D3D11:
2922 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2924 case RENDERPATH_SOFT:
2925 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2927 case RENDERPATH_GLES1:
2928 case RENDERPATH_GLES2:
2929 // GLES does not have glDrawRangeElements, and generally
2930 // underperforms with index buffers, so this code path is
2931 // relatively straightforward...
2933 if (gl_paranoid.integer)
2935 int r, prog, enabled, i;
2936 GLsizei attriblength;
2939 GLchar attribname[1024];
2940 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2941 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2942 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2943 #ifndef GL_CURRENT_PROGRAM
2944 #define GL_CURRENT_PROGRAM 0x8B8D
2946 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2947 if (r < 0 || r > 10000)
2948 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2950 for (i = 0;i < 8;i++)
2952 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2955 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2956 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);
2962 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2967 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2972 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2980 // restores backend state, used when done with 3D rendering
2981 void R_Mesh_Finish(void)
2983 R_Mesh_ResetRenderTargets();
2986 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2988 r_meshbuffer_t *buffer;
2989 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2991 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2992 memset(buffer, 0, sizeof(*buffer));
2993 buffer->bufferobject = 0;
2994 buffer->devicebuffer = NULL;
2996 buffer->isindexbuffer = isindexbuffer;
2997 buffer->isdynamic = isdynamic;
2998 buffer->isindex16 = isindex16;
2999 strlcpy(buffer->name, name, sizeof(buffer->name));
3000 R_Mesh_UpdateMeshBuffer(buffer, data, size);
3004 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
3008 if (buffer->isindexbuffer)
3010 r_refdef.stats.indexbufferuploadcount++;
3011 r_refdef.stats.indexbufferuploadsize += size;
3015 r_refdef.stats.vertexbufferuploadcount++;
3016 r_refdef.stats.vertexbufferuploadsize += size;
3018 switch(vid.renderpath)
3020 case RENDERPATH_GL11:
3021 case RENDERPATH_GL13:
3022 case RENDERPATH_GL20:
3023 case RENDERPATH_GLES1:
3024 case RENDERPATH_GLES2:
3025 if (!buffer->bufferobject)
3026 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3027 if (buffer->isindexbuffer)
3028 GL_BindEBO(buffer->bufferobject);
3030 GL_BindVBO(buffer->bufferobject);
3031 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
3033 case RENDERPATH_D3D9:
3037 void *datapointer = NULL;
3038 if (buffer->isindexbuffer)
3040 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3041 if (size > buffer->size || !buffer->devicebuffer)
3043 if (buffer->devicebuffer)
3044 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3045 buffer->devicebuffer = NULL;
3046 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)))
3047 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);
3048 buffer->devicebuffer = (void *)d3d9indexbuffer;
3049 buffer->size = size;
3051 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3054 memcpy(datapointer, data, size);
3056 memset(datapointer, 0, size);
3057 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3062 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3063 if (size > buffer->size || !buffer->devicebuffer)
3065 if (buffer->devicebuffer)
3066 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3067 buffer->devicebuffer = NULL;
3068 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3069 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);
3070 buffer->devicebuffer = (void *)d3d9vertexbuffer;
3071 buffer->size = size;
3073 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3076 memcpy(datapointer, data, size);
3078 memset(datapointer, 0, size);
3079 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3085 case RENDERPATH_D3D10:
3086 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3088 case RENDERPATH_D3D11:
3089 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3091 case RENDERPATH_SOFT:
3096 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3100 switch(vid.renderpath)
3102 case RENDERPATH_GL11:
3103 case RENDERPATH_GL13:
3104 case RENDERPATH_GL20:
3105 case RENDERPATH_GLES1:
3106 case RENDERPATH_GLES2:
3107 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3109 case RENDERPATH_D3D9:
3111 if (gl_state.d3dvertexbuffer == (void *)buffer)
3112 gl_state.d3dvertexbuffer = NULL;
3113 if (buffer->devicebuffer)
3115 if (buffer->isindexbuffer)
3116 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3118 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3119 buffer->devicebuffer = NULL;
3123 case RENDERPATH_D3D10:
3124 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3126 case RENDERPATH_D3D11:
3127 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3129 case RENDERPATH_SOFT:
3132 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3135 void GL_Mesh_ListVBOs(qboolean printeach)
3138 size_t ebocount = 0, ebomemory = 0;
3139 size_t vbocount = 0, vbomemory = 0;
3140 r_meshbuffer_t *buffer;
3141 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3142 for (i = 0;i < endindex;i++)
3144 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3147 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)");}
3148 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)");}
3150 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);
3155 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3157 switch(vid.renderpath)
3159 case RENDERPATH_GL11:
3160 case RENDERPATH_GL13:
3161 case RENDERPATH_GLES1:
3162 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)
3164 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3165 gl_state.pointer_vertex_components = components;
3166 gl_state.pointer_vertex_gltype = gltype;
3167 gl_state.pointer_vertex_stride = stride;
3168 gl_state.pointer_vertex_pointer = pointer;
3169 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3170 gl_state.pointer_vertex_offset = bufferoffset;
3172 GL_BindVBO(bufferobject);
3173 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3176 case RENDERPATH_GL20:
3177 case RENDERPATH_GLES2:
3178 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)
3180 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3181 gl_state.pointer_vertex_components = components;
3182 gl_state.pointer_vertex_gltype = gltype;
3183 gl_state.pointer_vertex_stride = stride;
3184 gl_state.pointer_vertex_pointer = pointer;
3185 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3186 gl_state.pointer_vertex_offset = bufferoffset;
3188 GL_BindVBO(bufferobject);
3189 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3192 case RENDERPATH_D3D9:
3193 case RENDERPATH_D3D10:
3194 case RENDERPATH_D3D11:
3195 case RENDERPATH_SOFT:
3200 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3202 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3203 // the pointer only.
3204 switch(vid.renderpath)
3206 case RENDERPATH_GL11:
3207 case RENDERPATH_GL13:
3208 case RENDERPATH_GLES1:
3212 // caller wants color array enabled
3213 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3214 if (!gl_state.pointer_color_enabled)
3216 gl_state.pointer_color_enabled = true;
3218 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3220 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)
3222 gl_state.pointer_color_components = components;
3223 gl_state.pointer_color_gltype = gltype;
3224 gl_state.pointer_color_stride = stride;
3225 gl_state.pointer_color_pointer = pointer;
3226 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3227 gl_state.pointer_color_offset = bufferoffset;
3229 GL_BindVBO(bufferobject);
3230 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3235 // caller wants color array disabled
3236 if (gl_state.pointer_color_enabled)
3238 gl_state.pointer_color_enabled = false;
3240 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3241 // when color array is on the glColor gets trashed, set it again
3242 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3246 case RENDERPATH_GL20:
3247 case RENDERPATH_GLES2:
3251 // caller wants color array enabled
3252 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3253 if (!gl_state.pointer_color_enabled)
3255 gl_state.pointer_color_enabled = true;
3257 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3259 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)
3261 gl_state.pointer_color_components = components;
3262 gl_state.pointer_color_gltype = gltype;
3263 gl_state.pointer_color_stride = stride;
3264 gl_state.pointer_color_pointer = pointer;
3265 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3266 gl_state.pointer_color_offset = bufferoffset;
3268 GL_BindVBO(bufferobject);
3269 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3274 // caller wants color array disabled
3275 if (gl_state.pointer_color_enabled)
3277 gl_state.pointer_color_enabled = false;
3279 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3280 // when color array is on the glColor gets trashed, set it again
3281 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3285 case RENDERPATH_D3D9:
3286 case RENDERPATH_D3D10:
3287 case RENDERPATH_D3D11:
3288 case RENDERPATH_SOFT:
3293 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)
3295 gltextureunit_t *unit = gl_state.units + unitnum;
3296 // update array settings
3297 // note: there is no need to check bufferobject here because all cases
3298 // that involve a valid bufferobject also supply a texcoord array
3299 switch(vid.renderpath)
3301 case RENDERPATH_GL11:
3302 case RENDERPATH_GL13:
3303 case RENDERPATH_GLES1:
3307 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3308 // texture array unit is enabled, enable the array
3309 if (!unit->arrayenabled)
3311 unit->arrayenabled = true;
3312 GL_ClientActiveTexture(unitnum);
3313 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3316 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)
3318 unit->pointer_texcoord_components = components;
3319 unit->pointer_texcoord_gltype = gltype;
3320 unit->pointer_texcoord_stride = stride;
3321 unit->pointer_texcoord_pointer = pointer;
3322 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3323 unit->pointer_texcoord_offset = bufferoffset;
3324 GL_ClientActiveTexture(unitnum);
3325 GL_BindVBO(bufferobject);
3326 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3331 // texture array unit is disabled, disable the array
3332 if (unit->arrayenabled)
3334 unit->arrayenabled = false;
3335 GL_ClientActiveTexture(unitnum);
3336 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3340 case RENDERPATH_GL20:
3341 case RENDERPATH_GLES2:
3345 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3346 // texture array unit is enabled, enable the array
3347 if (!unit->arrayenabled)
3349 unit->arrayenabled = true;
3350 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3353 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)
3355 unit->pointer_texcoord_components = components;
3356 unit->pointer_texcoord_gltype = gltype;
3357 unit->pointer_texcoord_stride = stride;
3358 unit->pointer_texcoord_pointer = pointer;
3359 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3360 unit->pointer_texcoord_offset = bufferoffset;
3361 GL_BindVBO(bufferobject);
3362 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3367 // texture array unit is disabled, disable the array
3368 if (unit->arrayenabled)
3370 unit->arrayenabled = false;
3371 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3375 case RENDERPATH_D3D9:
3376 case RENDERPATH_D3D10:
3377 case RENDERPATH_D3D11:
3378 case RENDERPATH_SOFT:
3383 int R_Mesh_TexBound(unsigned int unitnum, int id)
3385 gltextureunit_t *unit = gl_state.units + unitnum;
3386 if (unitnum >= vid.teximageunits)
3388 if (id == GL_TEXTURE_2D)
3390 if (id == GL_TEXTURE_3D)
3392 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3393 return unit->tcubemap;
3397 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3399 switch(vid.renderpath)
3401 case RENDERPATH_GL11:
3402 case RENDERPATH_GL13:
3403 case RENDERPATH_GL20:
3404 case RENDERPATH_GLES1:
3405 case RENDERPATH_GLES2:
3406 R_Mesh_TexBind(0, tex);
3407 GL_ActiveTexture(0);CHECKGLERROR
3408 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3410 case RENDERPATH_D3D9:
3413 IDirect3DSurface9 *currentsurface = NULL;
3414 IDirect3DSurface9 *texturesurface = NULL;
3417 sourcerect.left = sx;
3418 sourcerect.top = sy;
3419 sourcerect.right = sx + width;
3420 sourcerect.bottom = sy + height;
3423 destrect.right = tx + width;
3424 destrect.bottom = ty + height;
3425 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3427 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3429 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3430 IDirect3DSurface9_Release(currentsurface);
3432 IDirect3DSurface9_Release(texturesurface);
3437 case RENDERPATH_D3D10:
3438 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3440 case RENDERPATH_D3D11:
3441 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3443 case RENDERPATH_SOFT:
3444 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3450 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};
3453 void R_Mesh_ClearBindingsForTexture(int texnum)
3455 gltextureunit_t *unit;
3456 unsigned int unitnum;
3457 // 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)
3458 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3460 unit = gl_state.units + unitnum;
3461 if (unit->t2d == texnum)
3463 if (unit->t3d == texnum)
3465 if (unit->tcubemap == texnum)
3466 unit->tcubemap = -1;
3470 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3472 gltextureunit_t *unit = gl_state.units + unitnum;
3473 int tex2d, tex3d, texcubemap, texnum;
3474 if (unitnum >= vid.teximageunits)
3476 // if (unit->texture == tex)
3478 switch(vid.renderpath)
3480 case RENDERPATH_GL20:
3481 case RENDERPATH_GLES2:
3484 tex = r_texture_white;
3485 // not initialized enough yet...
3489 unit->texture = tex;
3490 texnum = R_GetTexture(tex);
3491 switch(tex->gltexturetypeenum)
3493 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3494 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3495 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;
3498 case RENDERPATH_GL11:
3499 case RENDERPATH_GL13:
3500 case RENDERPATH_GLES1:
3501 unit->texture = tex;
3507 texnum = R_GetTexture(tex);
3508 switch(tex->gltexturetypeenum)
3516 case GL_TEXTURE_CUBE_MAP_ARB:
3517 texcubemap = texnum;
3521 // update 2d texture binding
3522 if (unit->t2d != tex2d)
3524 GL_ActiveTexture(unitnum);
3529 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3536 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3540 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3542 // update 3d texture binding
3543 if (unit->t3d != tex3d)
3545 GL_ActiveTexture(unitnum);
3550 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3557 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3561 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3563 // update cubemap texture binding
3564 if (unit->tcubemap != texcubemap)
3566 GL_ActiveTexture(unitnum);
3569 if (unit->tcubemap == 0)
3571 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3578 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3581 unit->tcubemap = texcubemap;
3582 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3585 case RENDERPATH_D3D9:
3588 extern cvar_t gl_texture_anisotropy;
3591 tex = r_texture_white;
3592 // not initialized enough yet...
3596 // upload texture if needed
3598 if (unit->texture == tex)
3600 unit->texture = tex;
3601 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3602 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3603 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3604 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3605 if (tex->d3daddressw)
3606 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3607 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3608 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3609 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3610 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3611 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3612 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3616 case RENDERPATH_D3D10:
3617 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3619 case RENDERPATH_D3D11:
3620 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3622 case RENDERPATH_SOFT:
3625 tex = r_texture_white;
3626 // not initialized enough yet...
3630 texnum = R_GetTexture(tex);
3631 if (unit->texture == tex)
3633 unit->texture = tex;
3634 DPSOFTRAST_SetTexture(unitnum, texnum);
3639 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3641 gltextureunit_t *unit = gl_state.units + unitnum;
3642 switch(vid.renderpath)
3644 case RENDERPATH_GL11:
3645 case RENDERPATH_GL13:
3646 case RENDERPATH_GL20:
3647 case RENDERPATH_GLES1:
3648 case RENDERPATH_GLES2:
3649 if (matrix && matrix->m[3][3])
3651 // texmatrix specified, check if it is different
3652 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3655 unit->texmatrixenabled = true;
3656 unit->matrix = *matrix;
3658 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3659 GL_ActiveTexture(unitnum);
3660 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3661 qglLoadMatrixf(glmatrix);CHECKGLERROR
3662 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3667 // no texmatrix specified, revert to identity
3668 if (unit->texmatrixenabled)
3670 unit->texmatrixenabled = false;
3671 unit->matrix = identitymatrix;
3673 GL_ActiveTexture(unitnum);
3674 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3675 qglLoadIdentity();CHECKGLERROR
3676 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3680 case RENDERPATH_D3D9:
3681 case RENDERPATH_D3D10:
3682 case RENDERPATH_D3D11:
3684 case RENDERPATH_SOFT:
3689 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3691 gltextureunit_t *unit = gl_state.units + unitnum;
3693 switch(vid.renderpath)
3695 case RENDERPATH_GL20:
3696 case RENDERPATH_GLES2:
3699 case RENDERPATH_GL13:
3700 case RENDERPATH_GLES1:
3701 // GL_ARB_texture_env_combine
3703 combinergb = GL_MODULATE;
3705 combinealpha = GL_MODULATE;
3710 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3712 if (combinergb == GL_DECAL)
3713 combinergb = GL_INTERPOLATE_ARB;
3714 if (unit->combine != GL_COMBINE_ARB)
3716 unit->combine = GL_COMBINE_ARB;
3717 GL_ActiveTexture(unitnum);
3718 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3719 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3721 if (unit->combinergb != combinergb)
3723 unit->combinergb = combinergb;
3724 GL_ActiveTexture(unitnum);
3725 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3727 if (unit->combinealpha != combinealpha)
3729 unit->combinealpha = combinealpha;
3730 GL_ActiveTexture(unitnum);
3731 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3733 if (unit->rgbscale != rgbscale)
3735 unit->rgbscale = rgbscale;
3736 GL_ActiveTexture(unitnum);
3737 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3739 if (unit->alphascale != alphascale)
3741 unit->alphascale = alphascale;
3742 GL_ActiveTexture(unitnum);
3743 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3748 if (unit->combine != combinergb)
3750 unit->combine = combinergb;
3751 GL_ActiveTexture(unitnum);
3752 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3756 case RENDERPATH_GL11:
3759 combinergb = GL_MODULATE;
3760 if (unit->combine != combinergb)
3762 unit->combine = combinergb;
3763 GL_ActiveTexture(unitnum);
3764 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3767 case RENDERPATH_D3D9:
3768 case RENDERPATH_D3D10:
3769 case RENDERPATH_D3D11:
3771 case RENDERPATH_SOFT:
3776 void R_Mesh_ResetTextureState(void)
3778 unsigned int unitnum;
3782 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3783 R_Mesh_TexBind(unitnum, NULL);
3784 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3785 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3786 switch(vid.renderpath)
3788 case RENDERPATH_GL20:
3789 case RENDERPATH_GLES2:
3790 case RENDERPATH_D3D9:
3791 case RENDERPATH_D3D10:
3792 case RENDERPATH_D3D11:
3793 case RENDERPATH_SOFT:
3795 case RENDERPATH_GL11:
3796 case RENDERPATH_GL13:
3797 case RENDERPATH_GLES1:
3798 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3800 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3801 R_Mesh_TexMatrix(unitnum, NULL);
3810 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3811 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3812 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3814 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3816 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3820 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3822 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3823 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3824 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3828 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3830 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3831 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3832 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3833 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3834 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3835 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3836 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3840 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3841 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3842 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3845 static void R_Mesh_InitVertexDeclarations(void)
3848 r_vertex3f_d3d9decl = NULL;
3849 r_vertexgeneric_d3d9decl = NULL;
3850 r_vertexmesh_d3d9decl = NULL;
3851 switch(vid.renderpath)
3853 case RENDERPATH_GL20:
3854 case RENDERPATH_GL13:
3855 case RENDERPATH_GL11:
3856 case RENDERPATH_GLES1:
3857 case RENDERPATH_GLES2:
3859 case RENDERPATH_D3D9:
3860 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3861 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3862 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3864 case RENDERPATH_D3D10:
3865 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3867 case RENDERPATH_D3D11:
3868 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3870 case RENDERPATH_SOFT:
3876 static void R_Mesh_DestroyVertexDeclarations(void)
3879 if (r_vertex3f_d3d9decl)
3880 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3881 r_vertex3f_d3d9decl = NULL;
3882 if (r_vertexgeneric_d3d9decl)
3883 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3884 r_vertexgeneric_d3d9decl = NULL;
3885 if (r_vertexmesh_d3d9decl)
3886 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3887 r_vertexmesh_d3d9decl = NULL;
3891 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3893 // upload temporary vertexbuffer for this rendering
3894 if (!gl_state.usevbo_staticvertex)
3895 vertexbuffer = NULL;
3896 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3898 if (gl_state.preparevertices_dynamicvertexbuffer)
3899 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3901 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3902 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3904 switch(vid.renderpath)
3906 case RENDERPATH_GL20:
3907 case RENDERPATH_GLES2:
3910 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3911 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3912 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3913 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3914 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3915 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3916 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3920 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3921 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3922 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3923 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3924 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3925 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3926 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3929 case RENDERPATH_GL13:
3930 case RENDERPATH_GLES1:
3933 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3934 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3935 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3936 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3940 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3941 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3942 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3943 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3946 case RENDERPATH_GL11:
3949 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3950 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3951 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3955 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3956 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3957 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3960 case RENDERPATH_D3D9:
3962 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3964 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3966 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3967 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3968 gl_state.d3dvertexdata = (void *)vertex3f;
3969 gl_state.d3dvertexsize = sizeof(float[3]);
3972 case RENDERPATH_D3D10:
3973 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3975 case RENDERPATH_D3D11:
3976 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3978 case RENDERPATH_SOFT:
3979 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3980 DPSOFTRAST_SetColorPointer(NULL, 0);
3981 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3982 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3983 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3984 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3985 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3992 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3995 size = sizeof(r_vertexgeneric_t) * numvertices;
3996 if (gl_state.preparevertices_tempdatamaxsize < size)
3998 gl_state.preparevertices_tempdatamaxsize = size;
3999 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4001 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
4002 gl_state.preparevertices_numvertices = numvertices;
4003 return gl_state.preparevertices_vertexgeneric;
4006 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
4008 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4009 gl_state.preparevertices_vertexgeneric = NULL;
4010 gl_state.preparevertices_numvertices = 0;
4014 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4017 r_vertexgeneric_t *vertex;
4018 switch(vid.renderpath)
4020 case RENDERPATH_GL20:
4021 case RENDERPATH_GLES2:
4022 if (!vid.useinterleavedarrays)
4024 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4025 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4026 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4027 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4028 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4029 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4030 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4034 case RENDERPATH_GL11:
4035 case RENDERPATH_GL13:
4036 case RENDERPATH_GLES1:
4037 if (!vid.useinterleavedarrays)
4039 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4040 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4041 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4042 if (vid.texunits >= 2)
4043 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4044 if (vid.texunits >= 3)
4045 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4049 case RENDERPATH_D3D9:
4050 case RENDERPATH_D3D10:
4051 case RENDERPATH_D3D11:
4053 case RENDERPATH_SOFT:
4054 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4055 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4056 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4057 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4058 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4059 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4060 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4064 // no quick path for this case, convert to vertex structs
4065 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4066 for (i = 0;i < numvertices;i++)
4067 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4070 for (i = 0;i < numvertices;i++)
4071 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4075 for (i = 0;i < numvertices;i++)
4076 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4079 for (i = 0;i < numvertices;i++)
4080 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4081 R_Mesh_PrepareVertices_Generic_Unlock();
4082 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4085 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4087 // upload temporary vertexbuffer for this rendering
4088 if (!gl_state.usevbo_staticvertex)
4089 vertexbuffer = NULL;
4090 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4092 if (gl_state.preparevertices_dynamicvertexbuffer)
4093 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4095 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4096 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4098 switch(vid.renderpath)
4100 case RENDERPATH_GL20:
4101 case RENDERPATH_GLES2:
4104 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4105 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4106 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4107 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4108 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4109 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4110 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4114 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4115 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4116 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4117 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4118 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4119 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4120 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4123 case RENDERPATH_GL13:
4124 case RENDERPATH_GLES1:
4127 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4128 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4129 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4130 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4134 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4135 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4136 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4137 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4140 case RENDERPATH_GL11:
4143 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4144 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4145 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4149 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4150 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4151 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4154 case RENDERPATH_D3D9:
4156 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4158 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4160 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4161 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4162 gl_state.d3dvertexdata = (void *)vertex;
4163 gl_state.d3dvertexsize = sizeof(*vertex);
4166 case RENDERPATH_D3D10:
4167 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4169 case RENDERPATH_D3D11:
4170 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4172 case RENDERPATH_SOFT:
4173 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4174 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4175 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4176 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4177 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4178 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4179 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4186 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4189 size = sizeof(r_vertexmesh_t) * numvertices;
4190 if (gl_state.preparevertices_tempdatamaxsize < size)
4192 gl_state.preparevertices_tempdatamaxsize = size;
4193 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4195 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4196 gl_state.preparevertices_numvertices = numvertices;
4197 return gl_state.preparevertices_vertexmesh;
4200 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4202 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4203 gl_state.preparevertices_vertexmesh = NULL;
4204 gl_state.preparevertices_numvertices = 0;
4208 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)
4211 r_vertexmesh_t *vertex;
4212 switch(vid.renderpath)
4214 case RENDERPATH_GL20:
4215 case RENDERPATH_GLES2:
4216 if (!vid.useinterleavedarrays)
4218 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4219 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4220 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4221 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4222 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4223 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4224 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4228 case RENDERPATH_GL11:
4229 case RENDERPATH_GL13:
4230 case RENDERPATH_GLES1:
4231 if (!vid.useinterleavedarrays)
4233 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4234 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4235 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4236 if (vid.texunits >= 2)
4237 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4238 if (vid.texunits >= 3)
4239 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4243 case RENDERPATH_D3D9:
4244 case RENDERPATH_D3D10:
4245 case RENDERPATH_D3D11:
4247 case RENDERPATH_SOFT:
4248 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4249 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4250 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4251 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4252 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4253 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4254 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4258 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4259 for (i = 0;i < numvertices;i++)
4260 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4262 for (i = 0;i < numvertices;i++)
4263 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4265 for (i = 0;i < numvertices;i++)
4266 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4268 for (i = 0;i < numvertices;i++)
4269 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4272 for (i = 0;i < numvertices;i++)
4273 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4277 for (i = 0;i < numvertices;i++)
4278 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4280 if (texcoordtexture2f)
4281 for (i = 0;i < numvertices;i++)
4282 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4283 if (texcoordlightmap2f)
4284 for (i = 0;i < numvertices;i++)
4285 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4286 R_Mesh_PrepareVertices_Mesh_Unlock();
4287 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4290 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4292 // upload temporary vertexbuffer for this rendering
4293 if (!gl_state.usevbo_staticvertex)
4294 vertexbuffer = NULL;
4295 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4297 if (gl_state.preparevertices_dynamicvertexbuffer)
4298 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4300 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4301 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4303 switch(vid.renderpath)
4305 case RENDERPATH_GL20:
4306 case RENDERPATH_GLES2:
4309 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4310 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4311 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4312 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4313 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4314 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4315 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4319 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4320 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4321 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4322 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4323 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4324 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4325 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4328 case RENDERPATH_GL13:
4329 case RENDERPATH_GLES1:
4332 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4333 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4334 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4335 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4339 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4340 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4341 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4342 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4345 case RENDERPATH_GL11:
4348 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4349 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4350 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4354 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4355 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4356 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4359 case RENDERPATH_D3D9:
4361 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4363 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4365 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4366 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4367 gl_state.d3dvertexdata = (void *)vertex;
4368 gl_state.d3dvertexsize = sizeof(*vertex);
4371 case RENDERPATH_D3D10:
4372 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4374 case RENDERPATH_D3D11:
4375 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4377 case RENDERPATH_SOFT:
4378 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4379 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4380 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4381 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4382 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4383 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4384 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);