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;
1385 static void GL_Backend_ResetState(void)
1388 gl_state.active = true;
1389 gl_state.depthtest = true;
1390 gl_state.alphatest = false;
1391 gl_state.alphafunc = GL_GEQUAL;
1392 gl_state.alphafuncvalue = 0.5f;
1393 gl_state.blendfunc1 = GL_ONE;
1394 gl_state.blendfunc2 = GL_ZERO;
1395 gl_state.blend = false;
1396 gl_state.depthmask = GL_TRUE;
1397 gl_state.colormask = 15;
1398 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1399 gl_state.lockrange_first = 0;
1400 gl_state.lockrange_count = 0;
1401 gl_state.cullface = GL_FRONT;
1402 gl_state.cullfaceenable = false;
1403 gl_state.polygonoffset[0] = 0;
1404 gl_state.polygonoffset[1] = 0;
1405 gl_state.framebufferobject = 0;
1406 gl_state.depthfunc = GL_LEQUAL;
1408 switch(vid.renderpath)
1410 case RENDERPATH_D3D9:
1413 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1414 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1415 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1416 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1417 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1418 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1419 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1420 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1421 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1422 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1426 case RENDERPATH_D3D10:
1427 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1429 case RENDERPATH_D3D11:
1430 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1432 case RENDERPATH_GL11:
1433 case RENDERPATH_GL13:
1434 case RENDERPATH_GLES1:
1437 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1438 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1439 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1440 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1441 qglDisable(GL_BLEND);CHECKGLERROR
1442 qglCullFace(gl_state.cullface);CHECKGLERROR
1443 qglDisable(GL_CULL_FACE);CHECKGLERROR
1444 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1445 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1446 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1447 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1449 if (vid.support.arb_vertex_buffer_object)
1451 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1452 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1455 if (vid.support.ext_framebuffer_object)
1457 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1458 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1461 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1462 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1464 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1465 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1466 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1468 if (vid.support.ext_framebuffer_object)
1469 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1471 gl_state.unit = MAX_TEXTUREUNITS;
1472 gl_state.clientunit = MAX_TEXTUREUNITS;
1473 for (i = 0;i < vid.texunits;i++)
1475 GL_ActiveTexture(i);
1476 GL_ClientActiveTexture(i);
1477 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1478 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1479 if (vid.support.ext_texture_3d)
1481 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1482 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1484 if (vid.support.arb_texture_cube_map)
1486 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1487 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1490 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1491 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1492 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1493 qglLoadIdentity();CHECKGLERROR
1494 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1495 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1499 case RENDERPATH_SOFT:
1500 DPSOFTRAST_ColorMask(1,1,1,1);
1501 DPSOFTRAST_AlphaTest(gl_state.alphatest);
1502 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1503 DPSOFTRAST_CullFace(gl_state.cullface);
1504 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1505 DPSOFTRAST_DepthMask(gl_state.depthmask);
1506 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1507 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1508 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1510 case RENDERPATH_GL20:
1511 case RENDERPATH_GLES2:
1513 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1514 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1515 qglDisable(GL_BLEND);CHECKGLERROR
1516 qglCullFace(gl_state.cullface);CHECKGLERROR
1517 qglDisable(GL_CULL_FACE);CHECKGLERROR
1518 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1519 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1520 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1521 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1522 // if (vid.renderpath == RENDERPATH_GL20)
1524 // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1525 // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1527 if (vid.support.arb_vertex_buffer_object)
1529 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1530 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1532 if (vid.support.ext_framebuffer_object)
1533 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1534 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1535 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1536 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1537 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1538 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1539 gl_state.unit = MAX_TEXTUREUNITS;
1540 gl_state.clientunit = MAX_TEXTUREUNITS;
1541 for (i = 0;i < vid.teximageunits;i++)
1543 GL_ActiveTexture(i);
1544 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1545 if (vid.support.ext_texture_3d)
1547 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1549 if (vid.support.arb_texture_cube_map)
1551 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1554 for (i = 0;i < vid.texarrayunits;i++)
1557 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1558 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1565 void GL_ActiveTexture(unsigned int num)
1567 if (gl_state.unit != num)
1569 gl_state.unit = num;
1570 switch(vid.renderpath)
1572 case RENDERPATH_GL11:
1573 case RENDERPATH_GL13:
1574 case RENDERPATH_GL20:
1575 case RENDERPATH_GLES1:
1576 case RENDERPATH_GLES2:
1577 if (qglActiveTexture)
1580 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1584 case RENDERPATH_D3D9:
1585 case RENDERPATH_D3D10:
1586 case RENDERPATH_D3D11:
1588 case RENDERPATH_SOFT:
1594 void GL_ClientActiveTexture(unsigned int num)
1596 if (gl_state.clientunit != num)
1598 gl_state.clientunit = num;
1599 switch(vid.renderpath)
1601 case RENDERPATH_GL11:
1602 case RENDERPATH_GL13:
1603 case RENDERPATH_GLES1:
1604 if (qglActiveTexture)
1607 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1611 case RENDERPATH_D3D9:
1612 case RENDERPATH_D3D10:
1613 case RENDERPATH_D3D11:
1615 case RENDERPATH_SOFT:
1617 case RENDERPATH_GL20:
1618 case RENDERPATH_GLES2:
1624 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1626 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1628 qboolean blendenable;
1629 gl_state.blendfunc1 = blendfunc1;
1630 gl_state.blendfunc2 = blendfunc2;
1631 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1632 switch(vid.renderpath)
1634 case RENDERPATH_GL11:
1635 case RENDERPATH_GL13:
1636 case RENDERPATH_GL20:
1637 case RENDERPATH_GLES1:
1638 case RENDERPATH_GLES2:
1640 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1641 if (gl_state.blend != blendenable)
1643 gl_state.blend = blendenable;
1644 if (!gl_state.blend)
1646 qglDisable(GL_BLEND);CHECKGLERROR
1650 qglEnable(GL_BLEND);CHECKGLERROR
1654 case RENDERPATH_D3D9:
1659 D3DBLEND d3dblendfunc[2];
1660 glblendfunc[0] = gl_state.blendfunc1;
1661 glblendfunc[1] = gl_state.blendfunc2;
1662 for (i = 0;i < 2;i++)
1664 switch(glblendfunc[i])
1666 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1667 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1668 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1669 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1670 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1671 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1672 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1673 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1674 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1675 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1678 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1679 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1680 if (gl_state.blend != blendenable)
1682 gl_state.blend = blendenable;
1683 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1688 case RENDERPATH_D3D10:
1689 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1691 case RENDERPATH_D3D11:
1692 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1694 case RENDERPATH_SOFT:
1695 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1701 void GL_DepthMask(int state)
1703 if (gl_state.depthmask != state)
1705 gl_state.depthmask = state;
1706 switch(vid.renderpath)
1708 case RENDERPATH_GL11:
1709 case RENDERPATH_GL13:
1710 case RENDERPATH_GL20:
1711 case RENDERPATH_GLES1:
1712 case RENDERPATH_GLES2:
1714 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1716 case RENDERPATH_D3D9:
1718 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1721 case RENDERPATH_D3D10:
1722 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1724 case RENDERPATH_D3D11:
1725 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1727 case RENDERPATH_SOFT:
1728 DPSOFTRAST_DepthMask(gl_state.depthmask);
1734 void GL_DepthTest(int state)
1736 if (gl_state.depthtest != state)
1738 gl_state.depthtest = state;
1739 switch(vid.renderpath)
1741 case RENDERPATH_GL11:
1742 case RENDERPATH_GL13:
1743 case RENDERPATH_GL20:
1744 case RENDERPATH_GLES1:
1745 case RENDERPATH_GLES2:
1747 if (gl_state.depthtest)
1749 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1753 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1756 case RENDERPATH_D3D9:
1758 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1761 case RENDERPATH_D3D10:
1762 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1764 case RENDERPATH_D3D11:
1765 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1767 case RENDERPATH_SOFT:
1768 DPSOFTRAST_DepthTest(gl_state.depthtest);
1774 void GL_DepthFunc(int state)
1776 if (gl_state.depthfunc != state)
1778 gl_state.depthfunc = state;
1779 switch(vid.renderpath)
1781 case RENDERPATH_GL11:
1782 case RENDERPATH_GL13:
1783 case RENDERPATH_GL20:
1784 case RENDERPATH_GLES1:
1785 case RENDERPATH_GLES2:
1787 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1789 case RENDERPATH_D3D9:
1791 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1794 case RENDERPATH_D3D10:
1795 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1797 case RENDERPATH_D3D11:
1798 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1800 case RENDERPATH_SOFT:
1801 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1807 void GL_DepthRange(float nearfrac, float farfrac)
1809 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1811 gl_state.depthrange[0] = nearfrac;
1812 gl_state.depthrange[1] = farfrac;
1813 switch(vid.renderpath)
1815 case RENDERPATH_GL11:
1816 case RENDERPATH_GL13:
1817 case RENDERPATH_GL20:
1818 case RENDERPATH_GLES1:
1819 case RENDERPATH_GLES2:
1820 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1822 case RENDERPATH_D3D9:
1825 D3DVIEWPORT9 d3dviewport;
1826 d3dviewport.X = gl_viewport.x;
1827 d3dviewport.Y = gl_viewport.y;
1828 d3dviewport.Width = gl_viewport.width;
1829 d3dviewport.Height = gl_viewport.height;
1830 d3dviewport.MinZ = gl_state.depthrange[0];
1831 d3dviewport.MaxZ = gl_state.depthrange[1];
1832 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1836 case RENDERPATH_D3D10:
1837 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1839 case RENDERPATH_D3D11:
1840 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1842 case RENDERPATH_SOFT:
1843 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1849 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)
1851 switch (vid.renderpath)
1853 case RENDERPATH_GL11:
1854 case RENDERPATH_GL13:
1855 case RENDERPATH_GL20:
1856 case RENDERPATH_GLES1:
1857 case RENDERPATH_GLES2:
1861 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1865 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1867 if (vid.support.ati_separate_stencil)
1869 qglStencilMask(writemask);CHECKGLERROR
1870 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1871 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1872 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1874 else if (vid.support.ext_stencil_two_side)
1876 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1877 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1878 qglStencilMask(writemask);CHECKGLERROR
1879 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1880 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1881 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1882 qglStencilMask(writemask);CHECKGLERROR
1883 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1884 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1887 case RENDERPATH_D3D9:
1889 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1890 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1891 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1892 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1893 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1894 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1895 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1896 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1897 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1898 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1899 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1900 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1901 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1904 case RENDERPATH_D3D10:
1905 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1907 case RENDERPATH_D3D11:
1908 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1910 case RENDERPATH_SOFT:
1911 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1916 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1918 switch (vid.renderpath)
1920 case RENDERPATH_GL11:
1921 case RENDERPATH_GL13:
1922 case RENDERPATH_GL20:
1923 case RENDERPATH_GLES1:
1924 case RENDERPATH_GLES2:
1928 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1932 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1934 if (vid.support.ext_stencil_two_side)
1936 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1938 qglStencilMask(writemask);CHECKGLERROR
1939 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1940 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1943 case RENDERPATH_D3D9:
1945 if (vid.support.ati_separate_stencil)
1946 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1947 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1948 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1949 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1950 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1951 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1952 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1953 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1954 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1957 case RENDERPATH_D3D10:
1958 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960 case RENDERPATH_D3D11:
1961 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1963 case RENDERPATH_SOFT:
1964 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1969 void GL_PolygonOffset(float planeoffset, float depthoffset)
1971 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1973 gl_state.polygonoffset[0] = planeoffset;
1974 gl_state.polygonoffset[1] = depthoffset;
1975 switch(vid.renderpath)
1977 case RENDERPATH_GL11:
1978 case RENDERPATH_GL13:
1979 case RENDERPATH_GL20:
1980 case RENDERPATH_GLES1:
1981 case RENDERPATH_GLES2:
1982 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1984 case RENDERPATH_D3D9:
1986 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1987 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1990 case RENDERPATH_D3D10:
1991 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993 case RENDERPATH_D3D11:
1994 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1996 case RENDERPATH_SOFT:
1997 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2003 void GL_SetMirrorState(qboolean state)
2005 if (v_flipped_state != state)
2007 v_flipped_state = state;
2008 if (gl_state.cullface == GL_BACK)
2009 gl_state.cullface = GL_FRONT;
2010 else if (gl_state.cullface == GL_FRONT)
2011 gl_state.cullface = GL_BACK;
2014 switch(vid.renderpath)
2016 case RENDERPATH_GL11:
2017 case RENDERPATH_GL13:
2018 case RENDERPATH_GL20:
2019 case RENDERPATH_GLES1:
2020 case RENDERPATH_GLES2:
2021 qglCullFace(gl_state.cullface);CHECKGLERROR
2023 case RENDERPATH_D3D9:
2025 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2028 case RENDERPATH_D3D10:
2029 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2031 case RENDERPATH_D3D11:
2032 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2034 case RENDERPATH_SOFT:
2035 DPSOFTRAST_CullFace(gl_state.cullface);
2041 void GL_CullFace(int state)
2045 if(state == GL_FRONT)
2047 else if(state == GL_BACK)
2051 switch(vid.renderpath)
2053 case RENDERPATH_GL11:
2054 case RENDERPATH_GL13:
2055 case RENDERPATH_GL20:
2056 case RENDERPATH_GLES1:
2057 case RENDERPATH_GLES2:
2060 if (state != GL_NONE)
2062 if (!gl_state.cullfaceenable)
2064 gl_state.cullfaceenable = true;
2065 qglEnable(GL_CULL_FACE);CHECKGLERROR
2067 if (gl_state.cullface != state)
2069 gl_state.cullface = state;
2070 qglCullFace(gl_state.cullface);CHECKGLERROR
2075 if (gl_state.cullfaceenable)
2077 gl_state.cullfaceenable = false;
2078 qglDisable(GL_CULL_FACE);CHECKGLERROR
2082 case RENDERPATH_D3D9:
2084 if (gl_state.cullface != state)
2086 gl_state.cullface = state;
2087 switch(gl_state.cullface)
2090 gl_state.cullfaceenable = false;
2091 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2094 gl_state.cullfaceenable = true;
2095 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2098 gl_state.cullfaceenable = true;
2099 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2105 case RENDERPATH_D3D10:
2106 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2108 case RENDERPATH_D3D11:
2109 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2111 case RENDERPATH_SOFT:
2112 if (gl_state.cullface != state)
2114 gl_state.cullface = state;
2115 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2116 DPSOFTRAST_CullFace(gl_state.cullface);
2122 void GL_AlphaTest(int state)
2124 if (gl_state.alphatest != state)
2126 gl_state.alphatest = state;
2127 switch(vid.renderpath)
2129 case RENDERPATH_GL11:
2130 case RENDERPATH_GL13:
2131 case RENDERPATH_GLES1:
2132 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2134 if (gl_state.alphatest)
2136 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2140 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2143 case RENDERPATH_D3D9:
2145 // IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2148 case RENDERPATH_D3D10:
2150 case RENDERPATH_D3D11:
2152 case RENDERPATH_SOFT:
2153 // DPSOFTRAST_AlphaTest(gl_state.alphatest);
2155 case RENDERPATH_GL20:
2156 case RENDERPATH_GLES2:
2162 void GL_ColorMask(int r, int g, int b, int a)
2164 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2165 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2166 if (gl_state.colormask != state)
2168 gl_state.colormask = state;
2169 switch(vid.renderpath)
2171 case RENDERPATH_GL11:
2172 case RENDERPATH_GL13:
2173 case RENDERPATH_GL20:
2174 case RENDERPATH_GLES1:
2175 case RENDERPATH_GLES2:
2177 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2179 case RENDERPATH_D3D9:
2181 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2184 case RENDERPATH_D3D10:
2185 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2187 case RENDERPATH_D3D11:
2188 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2190 case RENDERPATH_SOFT:
2191 DPSOFTRAST_ColorMask(r, g, b, a);
2197 void GL_Color(float cr, float cg, float cb, float ca)
2199 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)
2201 gl_state.color4f[0] = cr;
2202 gl_state.color4f[1] = cg;
2203 gl_state.color4f[2] = cb;
2204 gl_state.color4f[3] = ca;
2205 switch(vid.renderpath)
2207 case RENDERPATH_GL11:
2208 case RENDERPATH_GL13:
2209 case RENDERPATH_GLES1:
2211 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2214 case RENDERPATH_D3D9:
2215 case RENDERPATH_D3D10:
2216 case RENDERPATH_D3D11:
2217 // no equivalent in D3D
2219 case RENDERPATH_SOFT:
2220 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2222 case RENDERPATH_GL20:
2223 case RENDERPATH_GLES2:
2224 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2230 void GL_Scissor (int x, int y, int width, int height)
2232 switch(vid.renderpath)
2234 case RENDERPATH_GL11:
2235 case RENDERPATH_GL13:
2236 case RENDERPATH_GL20:
2237 case RENDERPATH_GLES1:
2238 case RENDERPATH_GLES2:
2240 qglScissor(x, y,width,height);
2243 case RENDERPATH_D3D9:
2249 d3drect.right = x + width;
2250 d3drect.bottom = y + height;
2251 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2255 case RENDERPATH_D3D10:
2256 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2258 case RENDERPATH_D3D11:
2259 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2261 case RENDERPATH_SOFT:
2262 DPSOFTRAST_Scissor(x, y, width, height);
2267 void GL_ScissorTest(int state)
2269 if (gl_state.scissortest != state)
2271 gl_state.scissortest = state;
2272 switch(vid.renderpath)
2274 case RENDERPATH_GL11:
2275 case RENDERPATH_GL13:
2276 case RENDERPATH_GL20:
2277 case RENDERPATH_GLES1:
2278 case RENDERPATH_GLES2:
2280 if(gl_state.scissortest)
2281 qglEnable(GL_SCISSOR_TEST);
2283 qglDisable(GL_SCISSOR_TEST);
2286 case RENDERPATH_D3D9:
2288 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2291 case RENDERPATH_D3D10:
2292 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2294 case RENDERPATH_D3D11:
2295 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2297 case RENDERPATH_SOFT:
2298 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2304 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2306 static const float blackcolor[4] = {0, 0, 0, 0};
2307 // prevent warnings when trying to clear a buffer that does not exist
2309 colorvalue = blackcolor;
2312 mask &= ~GL_STENCIL_BUFFER_BIT;
2315 switch(vid.renderpath)
2317 case RENDERPATH_GL11:
2318 case RENDERPATH_GL13:
2319 case RENDERPATH_GL20:
2320 case RENDERPATH_GLES1:
2321 case RENDERPATH_GLES2:
2323 if (mask & GL_COLOR_BUFFER_BIT)
2325 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2327 if (mask & GL_DEPTH_BUFFER_BIT)
2329 qglClearDepth(depthvalue);CHECKGLERROR
2331 if (mask & GL_STENCIL_BUFFER_BIT)
2333 qglClearStencil(stencilvalue);CHECKGLERROR
2335 qglClear(mask);CHECKGLERROR
2337 case RENDERPATH_D3D9:
2339 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);
2342 case RENDERPATH_D3D10:
2343 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2345 case RENDERPATH_D3D11:
2346 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2348 case RENDERPATH_SOFT:
2349 if (mask & GL_COLOR_BUFFER_BIT)
2350 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2351 if (mask & GL_DEPTH_BUFFER_BIT)
2352 DPSOFTRAST_ClearDepth(depthvalue);
2357 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2359 switch(vid.renderpath)
2361 case RENDERPATH_GL11:
2362 case RENDERPATH_GL13:
2363 case RENDERPATH_GL20:
2364 case RENDERPATH_GLES1:
2365 case RENDERPATH_GLES2:
2367 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2369 case RENDERPATH_D3D9:
2372 // LordHavoc: we can't directly download the backbuffer because it may be
2373 // multisampled, and it may not be lockable, so we blit it to a lockable
2374 // surface of the same dimensions (but without multisample) to resolve the
2375 // multisample buffer to a normal image, and then lock that...
2376 IDirect3DSurface9 *stretchsurface = NULL;
2377 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2379 D3DLOCKED_RECT lockedrect;
2380 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2382 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2385 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2386 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2387 memcpy(outpixels + line * width * 4, row, width * 4);
2388 IDirect3DSurface9_UnlockRect(stretchsurface);
2391 IDirect3DSurface9_Release(stretchsurface);
2394 //IDirect3DSurface9 *syssurface = NULL;
2395 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2396 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2397 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2398 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2399 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2400 //IDirect3DSurface9_UnlockRect(syssurface);
2401 //IDirect3DSurface9_Release(syssurface);
2405 case RENDERPATH_D3D10:
2406 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2408 case RENDERPATH_D3D11:
2409 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2411 case RENDERPATH_SOFT:
2412 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2417 // called at beginning of frame
2418 void R_Mesh_Start(void)
2421 R_Mesh_ResetRenderTargets();
2423 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2425 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2426 Cvar_SetValueQuick(&gl_paranoid, 1);
2430 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2434 char compilelog[MAX_INPUTLINE];
2435 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2438 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2439 qglCompileShader(shaderobject);CHECKGLERROR
2440 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2441 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2442 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2444 int i, j, pretextlines = 0;
2445 for (i = 0;i < numstrings - 1;i++)
2446 for (j = 0;strings[i][j];j++)
2447 if (strings[i][j] == '\n')
2449 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2451 if (!shadercompiled)
2453 qglDeleteShader(shaderobject);CHECKGLERROR
2456 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2457 qglDeleteShader(shaderobject);CHECKGLERROR
2461 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)
2463 GLint programlinked;
2464 GLuint programobject = 0;
2465 char linklog[MAX_INPUTLINE];
2468 programobject = qglCreateProgram();CHECKGLERROR
2472 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2473 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2474 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2475 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2476 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2477 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2478 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2479 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2480 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2481 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2482 if(vid.support.gl20shaders130)
2483 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
2485 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2488 #ifdef GL_GEOMETRY_SHADER
2489 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2493 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2496 qglLinkProgram(programobject);CHECKGLERROR
2497 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2498 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2501 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2502 Con_DPrintf("program link log:\n%s\n", linklog);
2503 // software vertex shader is ok but software fragment shader is WAY
2504 // too slow, fail program if so.
2505 // NOTE: this string might be ATI specific, but that's ok because the
2506 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2507 // software fragment shader due to low instruction and dependent
2509 if (strstr(linklog, "fragment shader will run in software"))
2510 programlinked = false;
2514 return programobject;
2516 qglDeleteProgram(programobject);CHECKGLERROR
2520 void GL_Backend_FreeProgram(unsigned int prog)
2523 qglDeleteProgram(prog);
2527 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2532 for (i = 0;i < count;i++)
2533 *out++ = *in++ + offset;
2536 memcpy(out, in, sizeof(*out) * count);
2539 // renders triangles using vertices from the active arrays
2540 int paranoidblah = 0;
2541 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)
2543 unsigned int numelements = numtriangles * 3;
2545 size_t bufferoffset3i;
2547 size_t bufferoffset3s;
2548 if (numvertices < 3 || numtriangles < 1)
2550 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2551 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);
2554 if (!gl_mesh_prefer_short_elements.integer)
2558 if (element3i_indexbuffer)
2559 element3i_indexbuffer = NULL;
2561 // adjust the pointers for firsttriangle
2563 element3i += firsttriangle * 3;
2564 if (element3i_indexbuffer)
2565 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2567 element3s += firsttriangle * 3;
2568 if (element3s_indexbuffer)
2569 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2570 switch(vid.renderpath)
2572 case RENDERPATH_GL11:
2573 case RENDERPATH_GL13:
2574 case RENDERPATH_GL20:
2575 case RENDERPATH_GLES1:
2576 case RENDERPATH_GLES2:
2577 // check if the user specified to ignore static index buffers
2578 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2580 element3i_indexbuffer = NULL;
2581 element3s_indexbuffer = NULL;
2584 case RENDERPATH_D3D9:
2585 case RENDERPATH_D3D10:
2586 case RENDERPATH_D3D11:
2588 case RENDERPATH_SOFT:
2591 // upload a dynamic index buffer if needed
2594 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2596 if (gl_state.draw_dynamicindexbuffer)
2597 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2599 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2600 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2601 element3s_bufferoffset = 0;
2606 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2608 if (gl_state.draw_dynamicindexbuffer)
2609 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2611 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2612 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2613 element3i_bufferoffset = 0;
2616 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2617 bufferoffset3i = element3i_bufferoffset;
2618 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2619 bufferoffset3s = element3s_bufferoffset;
2620 r_refdef.stats.draws++;
2621 r_refdef.stats.draws_vertices += numvertices;
2622 r_refdef.stats.draws_elements += numelements;
2623 if (gl_paranoid.integer)
2626 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2628 unsigned int j, size;
2630 // note: there's no validation done here on buffer objects because it
2631 // is somewhat difficult to get at the data, and gl_paranoid can be
2632 // used without buffer objects if the need arises
2633 // (the data could be gotten using glMapBuffer but it would be very
2634 // slow due to uncachable video memory reads)
2635 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2636 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2638 if (gl_state.pointer_vertex_pointer)
2639 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2641 if (gl_state.pointer_color_enabled)
2643 if (!qglIsEnabled(GL_COLOR_ARRAY))
2644 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2646 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2647 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2650 for (i = 0;i < vid.texarrayunits;i++)
2652 if (gl_state.units[i].arrayenabled)
2654 GL_ClientActiveTexture(i);
2655 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2656 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2658 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2659 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++)
2666 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2668 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2670 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2677 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2679 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2681 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2687 if (r_render.integer || r_refdef.draw2dstage)
2689 switch(vid.renderpath)
2691 case RENDERPATH_GL11:
2692 case RENDERPATH_GL13:
2693 case RENDERPATH_GL20:
2695 if (gl_mesh_testmanualfeeding.integer)
2697 unsigned int i, j, element;
2699 qglBegin(GL_TRIANGLES);
2700 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2703 element = element3i[i];
2705 element = element3s[i];
2707 element = firstvertex + i;
2708 for (j = 0;j < vid.texarrayunits;j++)
2710 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2712 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2714 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2715 if (vid.texarrayunits > 1)
2717 if (gl_state.units[j].pointer_texcoord_components == 4)
2718 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2719 else if (gl_state.units[j].pointer_texcoord_components == 3)
2720 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2721 else if (gl_state.units[j].pointer_texcoord_components == 2)
2722 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2724 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2728 if (gl_state.units[j].pointer_texcoord_components == 4)
2729 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2730 else if (gl_state.units[j].pointer_texcoord_components == 3)
2731 qglTexCoord3f(p[0], p[1], p[2]);
2732 else if (gl_state.units[j].pointer_texcoord_components == 2)
2733 qglTexCoord2f(p[0], p[1]);
2735 qglTexCoord1f(p[0]);
2738 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2740 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2741 if (vid.texarrayunits > 1)
2743 if (gl_state.units[j].pointer_texcoord_components == 4)
2744 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2745 else if (gl_state.units[j].pointer_texcoord_components == 3)
2746 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2747 else if (gl_state.units[j].pointer_texcoord_components == 2)
2748 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2749 else if (gl_state.units[j].pointer_texcoord_components == 1)
2750 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2754 if (gl_state.units[j].pointer_texcoord_components == 4)
2755 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2756 else if (gl_state.units[j].pointer_texcoord_components == 3)
2757 qglTexCoord3f(s[0], s[1], s[2]);
2758 else if (gl_state.units[j].pointer_texcoord_components == 2)
2759 qglTexCoord2f(s[0], s[1]);
2760 else if (gl_state.units[j].pointer_texcoord_components == 1)
2761 qglTexCoord1f(s[0]);
2764 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2766 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2767 if (vid.texarrayunits > 1)
2769 if (gl_state.units[j].pointer_texcoord_components == 4)
2770 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2771 else if (gl_state.units[j].pointer_texcoord_components == 3)
2772 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2773 else if (gl_state.units[j].pointer_texcoord_components == 2)
2774 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2775 else if (gl_state.units[j].pointer_texcoord_components == 1)
2776 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2780 if (gl_state.units[j].pointer_texcoord_components == 4)
2781 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2782 else if (gl_state.units[j].pointer_texcoord_components == 3)
2783 qglTexCoord3f(sb[0], sb[1], sb[2]);
2784 else if (gl_state.units[j].pointer_texcoord_components == 2)
2785 qglTexCoord2f(sb[0], sb[1]);
2786 else if (gl_state.units[j].pointer_texcoord_components == 1)
2787 qglTexCoord1f(sb[0]);
2792 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2794 if (gl_state.pointer_color_gltype == GL_FLOAT)
2796 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2797 qglColor4f(p[0], p[1], p[2], p[3]);
2799 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2801 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2802 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2805 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2807 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2808 if (gl_state.pointer_vertex_components == 4)
2809 qglVertex4f(p[0], p[1], p[2], p[3]);
2810 else if (gl_state.pointer_vertex_components == 3)
2811 qglVertex3f(p[0], p[1], p[2]);
2813 qglVertex2f(p[0], p[1]);
2819 else if (bufferobject3s)
2821 GL_BindEBO(bufferobject3s);
2822 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2824 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2829 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2833 else if (bufferobject3i)
2835 GL_BindEBO(bufferobject3i);
2836 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2838 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2843 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2850 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2852 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2857 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2864 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2866 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2871 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2877 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2881 case RENDERPATH_D3D9:
2883 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2885 if (element3s_indexbuffer)
2887 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2888 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2890 else if (element3i_indexbuffer)
2892 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2893 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2896 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2901 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2903 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2905 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2909 case RENDERPATH_D3D10:
2910 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2912 case RENDERPATH_D3D11:
2913 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2915 case RENDERPATH_SOFT:
2916 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2918 case RENDERPATH_GLES1:
2919 case RENDERPATH_GLES2:
2920 // GLES does not have glDrawRangeElements, and generally
2921 // underperforms with index buffers, so this code path is
2922 // relatively straightforward...
2924 if (gl_paranoid.integer)
2926 int r, prog, enabled, i;
2927 GLsizei attriblength;
2930 GLchar attribname[1024];
2931 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2932 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2933 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2934 #ifndef GL_CURRENT_PROGRAM
2935 #define GL_CURRENT_PROGRAM 0x8B8D
2937 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2938 if (r < 0 || r > 10000)
2939 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2941 for (i = 0;i < 8;i++)
2943 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2946 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2947 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);
2953 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2958 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2963 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2971 // restores backend state, used when done with 3D rendering
2972 void R_Mesh_Finish(void)
2974 R_Mesh_ResetRenderTargets();
2977 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2979 r_meshbuffer_t *buffer;
2980 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2982 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2983 memset(buffer, 0, sizeof(*buffer));
2984 buffer->bufferobject = 0;
2985 buffer->devicebuffer = NULL;
2987 buffer->isindexbuffer = isindexbuffer;
2988 buffer->isdynamic = isdynamic;
2989 buffer->isindex16 = isindex16;
2990 strlcpy(buffer->name, name, sizeof(buffer->name));
2991 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2995 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
2999 if (buffer->isindexbuffer)
3001 r_refdef.stats.indexbufferuploadcount++;
3002 r_refdef.stats.indexbufferuploadsize += size;
3006 r_refdef.stats.vertexbufferuploadcount++;
3007 r_refdef.stats.vertexbufferuploadsize += size;
3009 switch(vid.renderpath)
3011 case RENDERPATH_GL11:
3012 case RENDERPATH_GL13:
3013 case RENDERPATH_GL20:
3014 case RENDERPATH_GLES1:
3015 case RENDERPATH_GLES2:
3016 if (!buffer->bufferobject)
3017 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3018 if (buffer->isindexbuffer)
3019 GL_BindEBO(buffer->bufferobject);
3021 GL_BindVBO(buffer->bufferobject);
3022 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
3024 case RENDERPATH_D3D9:
3028 void *datapointer = NULL;
3029 if (buffer->isindexbuffer)
3031 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3032 if (size > buffer->size || !buffer->devicebuffer)
3034 if (buffer->devicebuffer)
3035 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3036 buffer->devicebuffer = NULL;
3037 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)))
3038 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);
3039 buffer->devicebuffer = (void *)d3d9indexbuffer;
3040 buffer->size = size;
3042 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3045 memcpy(datapointer, data, size);
3047 memset(datapointer, 0, size);
3048 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3053 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3054 if (size > buffer->size || !buffer->devicebuffer)
3056 if (buffer->devicebuffer)
3057 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3058 buffer->devicebuffer = NULL;
3059 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3060 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);
3061 buffer->devicebuffer = (void *)d3d9vertexbuffer;
3062 buffer->size = size;
3064 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3067 memcpy(datapointer, data, size);
3069 memset(datapointer, 0, size);
3070 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3076 case RENDERPATH_D3D10:
3077 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3079 case RENDERPATH_D3D11:
3080 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3082 case RENDERPATH_SOFT:
3087 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3091 switch(vid.renderpath)
3093 case RENDERPATH_GL11:
3094 case RENDERPATH_GL13:
3095 case RENDERPATH_GL20:
3096 case RENDERPATH_GLES1:
3097 case RENDERPATH_GLES2:
3098 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3100 case RENDERPATH_D3D9:
3102 if (gl_state.d3dvertexbuffer == (void *)buffer)
3103 gl_state.d3dvertexbuffer = NULL;
3104 if (buffer->devicebuffer)
3106 if (buffer->isindexbuffer)
3107 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3109 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3110 buffer->devicebuffer = NULL;
3114 case RENDERPATH_D3D10:
3115 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3117 case RENDERPATH_D3D11:
3118 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3120 case RENDERPATH_SOFT:
3123 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3126 void GL_Mesh_ListVBOs(qboolean printeach)
3129 size_t ebocount = 0, ebomemory = 0;
3130 size_t vbocount = 0, vbomemory = 0;
3131 r_meshbuffer_t *buffer;
3132 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3133 for (i = 0;i < endindex;i++)
3135 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3138 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)");}
3139 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)");}
3141 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);
3146 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3148 switch(vid.renderpath)
3150 case RENDERPATH_GL11:
3151 case RENDERPATH_GL13:
3152 case RENDERPATH_GLES1:
3153 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)
3155 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3156 gl_state.pointer_vertex_components = components;
3157 gl_state.pointer_vertex_gltype = gltype;
3158 gl_state.pointer_vertex_stride = stride;
3159 gl_state.pointer_vertex_pointer = pointer;
3160 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3161 gl_state.pointer_vertex_offset = bufferoffset;
3163 GL_BindVBO(bufferobject);
3164 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3167 case RENDERPATH_GL20:
3168 case RENDERPATH_GLES2:
3169 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)
3171 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3172 gl_state.pointer_vertex_components = components;
3173 gl_state.pointer_vertex_gltype = gltype;
3174 gl_state.pointer_vertex_stride = stride;
3175 gl_state.pointer_vertex_pointer = pointer;
3176 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3177 gl_state.pointer_vertex_offset = bufferoffset;
3179 GL_BindVBO(bufferobject);
3180 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3183 case RENDERPATH_D3D9:
3184 case RENDERPATH_D3D10:
3185 case RENDERPATH_D3D11:
3186 case RENDERPATH_SOFT:
3191 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3193 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3194 // the pointer only.
3195 switch(vid.renderpath)
3197 case RENDERPATH_GL11:
3198 case RENDERPATH_GL13:
3199 case RENDERPATH_GLES1:
3203 // caller wants color array enabled
3204 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3205 if (!gl_state.pointer_color_enabled)
3207 gl_state.pointer_color_enabled = true;
3209 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3211 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)
3213 gl_state.pointer_color_components = components;
3214 gl_state.pointer_color_gltype = gltype;
3215 gl_state.pointer_color_stride = stride;
3216 gl_state.pointer_color_pointer = pointer;
3217 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3218 gl_state.pointer_color_offset = bufferoffset;
3220 GL_BindVBO(bufferobject);
3221 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3226 // caller wants color array disabled
3227 if (gl_state.pointer_color_enabled)
3229 gl_state.pointer_color_enabled = false;
3231 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3232 // when color array is on the glColor gets trashed, set it again
3233 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3237 case RENDERPATH_GL20:
3238 case RENDERPATH_GLES2:
3242 // caller wants color array enabled
3243 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3244 if (!gl_state.pointer_color_enabled)
3246 gl_state.pointer_color_enabled = true;
3248 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3250 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)
3252 gl_state.pointer_color_components = components;
3253 gl_state.pointer_color_gltype = gltype;
3254 gl_state.pointer_color_stride = stride;
3255 gl_state.pointer_color_pointer = pointer;
3256 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3257 gl_state.pointer_color_offset = bufferoffset;
3259 GL_BindVBO(bufferobject);
3260 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3265 // caller wants color array disabled
3266 if (gl_state.pointer_color_enabled)
3268 gl_state.pointer_color_enabled = false;
3270 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3271 // when color array is on the glColor gets trashed, set it again
3272 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3276 case RENDERPATH_D3D9:
3277 case RENDERPATH_D3D10:
3278 case RENDERPATH_D3D11:
3279 case RENDERPATH_SOFT:
3284 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)
3286 gltextureunit_t *unit = gl_state.units + unitnum;
3287 // update array settings
3288 // note: there is no need to check bufferobject here because all cases
3289 // that involve a valid bufferobject also supply a texcoord array
3290 switch(vid.renderpath)
3292 case RENDERPATH_GL11:
3293 case RENDERPATH_GL13:
3294 case RENDERPATH_GLES1:
3298 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3299 // texture array unit is enabled, enable the array
3300 if (!unit->arrayenabled)
3302 unit->arrayenabled = true;
3303 GL_ClientActiveTexture(unitnum);
3304 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3307 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)
3309 unit->pointer_texcoord_components = components;
3310 unit->pointer_texcoord_gltype = gltype;
3311 unit->pointer_texcoord_stride = stride;
3312 unit->pointer_texcoord_pointer = pointer;
3313 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3314 unit->pointer_texcoord_offset = bufferoffset;
3315 GL_ClientActiveTexture(unitnum);
3316 GL_BindVBO(bufferobject);
3317 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3322 // texture array unit is disabled, disable the array
3323 if (unit->arrayenabled)
3325 unit->arrayenabled = false;
3326 GL_ClientActiveTexture(unitnum);
3327 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3331 case RENDERPATH_GL20:
3332 case RENDERPATH_GLES2:
3336 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3337 // texture array unit is enabled, enable the array
3338 if (!unit->arrayenabled)
3340 unit->arrayenabled = true;
3341 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3344 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)
3346 unit->pointer_texcoord_components = components;
3347 unit->pointer_texcoord_gltype = gltype;
3348 unit->pointer_texcoord_stride = stride;
3349 unit->pointer_texcoord_pointer = pointer;
3350 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3351 unit->pointer_texcoord_offset = bufferoffset;
3352 GL_BindVBO(bufferobject);
3353 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3358 // texture array unit is disabled, disable the array
3359 if (unit->arrayenabled)
3361 unit->arrayenabled = false;
3362 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3366 case RENDERPATH_D3D9:
3367 case RENDERPATH_D3D10:
3368 case RENDERPATH_D3D11:
3369 case RENDERPATH_SOFT:
3374 int R_Mesh_TexBound(unsigned int unitnum, int id)
3376 gltextureunit_t *unit = gl_state.units + unitnum;
3377 if (unitnum >= vid.teximageunits)
3379 if (id == GL_TEXTURE_2D)
3381 if (id == GL_TEXTURE_3D)
3383 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3384 return unit->tcubemap;
3388 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3390 switch(vid.renderpath)
3392 case RENDERPATH_GL11:
3393 case RENDERPATH_GL13:
3394 case RENDERPATH_GL20:
3395 case RENDERPATH_GLES1:
3396 case RENDERPATH_GLES2:
3397 R_Mesh_TexBind(0, tex);
3398 GL_ActiveTexture(0);CHECKGLERROR
3399 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3401 case RENDERPATH_D3D9:
3404 IDirect3DSurface9 *currentsurface = NULL;
3405 IDirect3DSurface9 *texturesurface = NULL;
3408 sourcerect.left = sx;
3409 sourcerect.top = sy;
3410 sourcerect.right = sx + width;
3411 sourcerect.bottom = sy + height;
3414 destrect.right = tx + width;
3415 destrect.bottom = ty + height;
3416 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3418 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3420 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3421 IDirect3DSurface9_Release(currentsurface);
3423 IDirect3DSurface9_Release(texturesurface);
3428 case RENDERPATH_D3D10:
3429 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3431 case RENDERPATH_D3D11:
3432 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3434 case RENDERPATH_SOFT:
3435 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3441 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};
3444 void R_Mesh_ClearBindingsForTexture(int texnum)
3446 gltextureunit_t *unit;
3447 unsigned int unitnum;
3448 // 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)
3449 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3451 unit = gl_state.units + unitnum;
3452 if (unit->t2d == texnum)
3454 if (unit->t3d == texnum)
3456 if (unit->tcubemap == texnum)
3457 unit->tcubemap = -1;
3461 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3463 gltextureunit_t *unit = gl_state.units + unitnum;
3464 int tex2d, tex3d, texcubemap, texnum;
3465 if (unitnum >= vid.teximageunits)
3467 // if (unit->texture == tex)
3469 switch(vid.renderpath)
3471 case RENDERPATH_GL20:
3472 case RENDERPATH_GLES2:
3475 tex = r_texture_white;
3476 // not initialized enough yet...
3480 unit->texture = tex;
3481 texnum = R_GetTexture(tex);
3482 switch(tex->gltexturetypeenum)
3484 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3485 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3486 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;
3489 case RENDERPATH_GL11:
3490 case RENDERPATH_GL13:
3491 case RENDERPATH_GLES1:
3492 unit->texture = tex;
3498 texnum = R_GetTexture(tex);
3499 switch(tex->gltexturetypeenum)
3507 case GL_TEXTURE_CUBE_MAP_ARB:
3508 texcubemap = texnum;
3512 // update 2d texture binding
3513 if (unit->t2d != tex2d)
3515 GL_ActiveTexture(unitnum);
3520 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3527 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3531 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3533 // update 3d texture binding
3534 if (unit->t3d != tex3d)
3536 GL_ActiveTexture(unitnum);
3541 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3548 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3552 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3554 // update cubemap texture binding
3555 if (unit->tcubemap != texcubemap)
3557 GL_ActiveTexture(unitnum);
3560 if (unit->tcubemap == 0)
3562 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3569 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3572 unit->tcubemap = texcubemap;
3573 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3576 case RENDERPATH_D3D9:
3579 extern cvar_t gl_texture_anisotropy;
3582 tex = r_texture_white;
3583 // not initialized enough yet...
3587 // upload texture if needed
3589 if (unit->texture == tex)
3591 unit->texture = tex;
3592 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3593 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3594 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3595 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3596 if (tex->d3daddressw)
3597 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3598 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3599 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3600 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3601 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3602 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3603 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3607 case RENDERPATH_D3D10:
3608 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3610 case RENDERPATH_D3D11:
3611 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3613 case RENDERPATH_SOFT:
3616 tex = r_texture_white;
3617 // not initialized enough yet...
3621 texnum = R_GetTexture(tex);
3622 if (unit->texture == tex)
3624 unit->texture = tex;
3625 DPSOFTRAST_SetTexture(unitnum, texnum);
3630 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3632 gltextureunit_t *unit = gl_state.units + unitnum;
3633 switch(vid.renderpath)
3635 case RENDERPATH_GL11:
3636 case RENDERPATH_GL13:
3637 case RENDERPATH_GL20:
3638 case RENDERPATH_GLES1:
3639 case RENDERPATH_GLES2:
3640 if (matrix && matrix->m[3][3])
3642 // texmatrix specified, check if it is different
3643 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3646 unit->texmatrixenabled = true;
3647 unit->matrix = *matrix;
3649 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3650 GL_ActiveTexture(unitnum);
3651 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3652 qglLoadMatrixf(glmatrix);CHECKGLERROR
3653 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3658 // no texmatrix specified, revert to identity
3659 if (unit->texmatrixenabled)
3661 unit->texmatrixenabled = false;
3662 unit->matrix = identitymatrix;
3664 GL_ActiveTexture(unitnum);
3665 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3666 qglLoadIdentity();CHECKGLERROR
3667 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3671 case RENDERPATH_D3D9:
3672 case RENDERPATH_D3D10:
3673 case RENDERPATH_D3D11:
3675 case RENDERPATH_SOFT:
3680 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3682 gltextureunit_t *unit = gl_state.units + unitnum;
3684 switch(vid.renderpath)
3686 case RENDERPATH_GL20:
3687 case RENDERPATH_GLES2:
3690 case RENDERPATH_GL13:
3691 case RENDERPATH_GLES1:
3692 // GL_ARB_texture_env_combine
3694 combinergb = GL_MODULATE;
3696 combinealpha = GL_MODULATE;
3701 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3703 if (combinergb == GL_DECAL)
3704 combinergb = GL_INTERPOLATE_ARB;
3705 if (unit->combine != GL_COMBINE_ARB)
3707 unit->combine = GL_COMBINE_ARB;
3708 GL_ActiveTexture(unitnum);
3709 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3710 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3712 if (unit->combinergb != combinergb)
3714 unit->combinergb = combinergb;
3715 GL_ActiveTexture(unitnum);
3716 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3718 if (unit->combinealpha != combinealpha)
3720 unit->combinealpha = combinealpha;
3721 GL_ActiveTexture(unitnum);
3722 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3724 if (unit->rgbscale != rgbscale)
3726 unit->rgbscale = rgbscale;
3727 GL_ActiveTexture(unitnum);
3728 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3730 if (unit->alphascale != alphascale)
3732 unit->alphascale = alphascale;
3733 GL_ActiveTexture(unitnum);
3734 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3739 if (unit->combine != combinergb)
3741 unit->combine = combinergb;
3742 GL_ActiveTexture(unitnum);
3743 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3747 case RENDERPATH_GL11:
3750 combinergb = GL_MODULATE;
3751 if (unit->combine != combinergb)
3753 unit->combine = combinergb;
3754 GL_ActiveTexture(unitnum);
3755 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3758 case RENDERPATH_D3D9:
3759 case RENDERPATH_D3D10:
3760 case RENDERPATH_D3D11:
3762 case RENDERPATH_SOFT:
3767 void R_Mesh_ResetTextureState(void)
3769 unsigned int unitnum;
3773 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3774 R_Mesh_TexBind(unitnum, NULL);
3775 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3776 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3777 switch(vid.renderpath)
3779 case RENDERPATH_GL20:
3780 case RENDERPATH_GLES2:
3781 case RENDERPATH_D3D9:
3782 case RENDERPATH_D3D10:
3783 case RENDERPATH_D3D11:
3784 case RENDERPATH_SOFT:
3786 case RENDERPATH_GL11:
3787 case RENDERPATH_GL13:
3788 case RENDERPATH_GLES1:
3789 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3791 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3792 R_Mesh_TexMatrix(unitnum, NULL);
3801 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3802 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3803 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3805 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3807 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3811 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3813 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3814 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3815 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3819 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3821 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3822 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4f ), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3823 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3824 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3825 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3826 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3827 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3831 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3832 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3833 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3836 static void R_Mesh_InitVertexDeclarations(void)
3839 r_vertex3f_d3d9decl = NULL;
3840 r_vertexgeneric_d3d9decl = NULL;
3841 r_vertexmesh_d3d9decl = NULL;
3842 switch(vid.renderpath)
3844 case RENDERPATH_GL20:
3845 case RENDERPATH_GL13:
3846 case RENDERPATH_GL11:
3847 case RENDERPATH_GLES1:
3848 case RENDERPATH_GLES2:
3850 case RENDERPATH_D3D9:
3851 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3852 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3853 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3855 case RENDERPATH_D3D10:
3856 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3858 case RENDERPATH_D3D11:
3859 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3861 case RENDERPATH_SOFT:
3867 static void R_Mesh_DestroyVertexDeclarations(void)
3870 if (r_vertex3f_d3d9decl)
3871 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3872 r_vertex3f_d3d9decl = NULL;
3873 if (r_vertexgeneric_d3d9decl)
3874 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3875 r_vertexgeneric_d3d9decl = NULL;
3876 if (r_vertexmesh_d3d9decl)
3877 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3878 r_vertexmesh_d3d9decl = NULL;
3882 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3884 // upload temporary vertexbuffer for this rendering
3885 if (!gl_state.usevbo_staticvertex)
3886 vertexbuffer = NULL;
3887 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3889 if (gl_state.preparevertices_dynamicvertexbuffer)
3890 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3892 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3893 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3895 switch(vid.renderpath)
3897 case RENDERPATH_GL20:
3898 case RENDERPATH_GLES2:
3901 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3902 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3903 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3904 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3905 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3906 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3907 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3911 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3912 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3913 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3914 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3915 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3916 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3917 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3920 case RENDERPATH_GL13:
3921 case RENDERPATH_GLES1:
3924 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3925 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3926 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3927 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3931 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3932 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3933 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3934 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3937 case RENDERPATH_GL11:
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);
3946 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3947 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3948 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3951 case RENDERPATH_D3D9:
3953 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3955 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3957 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3958 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3959 gl_state.d3dvertexdata = (void *)vertex3f;
3960 gl_state.d3dvertexsize = sizeof(float[3]);
3963 case RENDERPATH_D3D10:
3964 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3966 case RENDERPATH_D3D11:
3967 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3969 case RENDERPATH_SOFT:
3970 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3971 DPSOFTRAST_SetColorPointer(NULL, 0);
3972 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3973 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3974 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3975 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3976 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3983 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3986 size = sizeof(r_vertexgeneric_t) * numvertices;
3987 if (gl_state.preparevertices_tempdatamaxsize < size)
3989 gl_state.preparevertices_tempdatamaxsize = size;
3990 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3992 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3993 gl_state.preparevertices_numvertices = numvertices;
3994 return gl_state.preparevertices_vertexgeneric;
3997 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
3999 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4000 gl_state.preparevertices_vertexgeneric = NULL;
4001 gl_state.preparevertices_numvertices = 0;
4005 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4008 r_vertexgeneric_t *vertex;
4009 switch(vid.renderpath)
4011 case RENDERPATH_GL20:
4012 case RENDERPATH_GLES2:
4013 if (!vid.useinterleavedarrays)
4015 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4016 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4017 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4018 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4019 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4020 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4021 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4025 case RENDERPATH_GL11:
4026 case RENDERPATH_GL13:
4027 case RENDERPATH_GLES1:
4028 if (!vid.useinterleavedarrays)
4030 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4031 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4032 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4033 if (vid.texunits >= 2)
4034 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4035 if (vid.texunits >= 3)
4036 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4040 case RENDERPATH_D3D9:
4041 case RENDERPATH_D3D10:
4042 case RENDERPATH_D3D11:
4044 case RENDERPATH_SOFT:
4045 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4046 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4047 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4048 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4049 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4050 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4051 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4055 // no quick path for this case, convert to vertex structs
4056 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4057 for (i = 0;i < numvertices;i++)
4058 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4061 for (i = 0;i < numvertices;i++)
4062 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4066 for (i = 0;i < numvertices;i++)
4067 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4070 for (i = 0;i < numvertices;i++)
4071 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4072 R_Mesh_PrepareVertices_Generic_Unlock();
4073 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4076 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4078 // upload temporary vertexbuffer for this rendering
4079 if (!gl_state.usevbo_staticvertex)
4080 vertexbuffer = NULL;
4081 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4083 if (gl_state.preparevertices_dynamicvertexbuffer)
4084 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4086 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4087 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4089 switch(vid.renderpath)
4091 case RENDERPATH_GL20:
4092 case RENDERPATH_GLES2:
4095 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4096 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4097 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4098 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4099 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4100 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4101 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4105 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4106 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4107 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4108 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4109 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4110 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4111 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4114 case RENDERPATH_GL13:
4115 case RENDERPATH_GLES1:
4118 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4119 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4120 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4121 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4125 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4126 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4127 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4128 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4131 case RENDERPATH_GL11:
4134 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4135 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4136 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4140 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4141 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4142 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4145 case RENDERPATH_D3D9:
4147 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4149 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4151 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4152 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4153 gl_state.d3dvertexdata = (void *)vertex;
4154 gl_state.d3dvertexsize = sizeof(*vertex);
4157 case RENDERPATH_D3D10:
4158 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4160 case RENDERPATH_D3D11:
4161 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4163 case RENDERPATH_SOFT:
4164 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4165 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4166 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4167 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4168 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4169 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4170 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4177 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4180 size = sizeof(r_vertexmesh_t) * numvertices;
4181 if (gl_state.preparevertices_tempdatamaxsize < size)
4183 gl_state.preparevertices_tempdatamaxsize = size;
4184 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4186 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4187 gl_state.preparevertices_numvertices = numvertices;
4188 return gl_state.preparevertices_vertexmesh;
4191 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4193 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4194 gl_state.preparevertices_vertexmesh = NULL;
4195 gl_state.preparevertices_numvertices = 0;
4199 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)
4202 r_vertexmesh_t *vertex;
4203 switch(vid.renderpath)
4205 case RENDERPATH_GL20:
4206 case RENDERPATH_GLES2:
4207 if (!vid.useinterleavedarrays)
4209 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4210 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4211 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4212 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4213 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4214 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4215 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4219 case RENDERPATH_GL11:
4220 case RENDERPATH_GL13:
4221 case RENDERPATH_GLES1:
4222 if (!vid.useinterleavedarrays)
4224 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4225 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4226 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4227 if (vid.texunits >= 2)
4228 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4229 if (vid.texunits >= 3)
4230 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4234 case RENDERPATH_D3D9:
4235 case RENDERPATH_D3D10:
4236 case RENDERPATH_D3D11:
4238 case RENDERPATH_SOFT:
4239 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4240 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4241 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4242 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4243 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4244 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4245 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4249 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4250 for (i = 0;i < numvertices;i++)
4251 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4253 for (i = 0;i < numvertices;i++)
4254 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4256 for (i = 0;i < numvertices;i++)
4257 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4259 for (i = 0;i < numvertices;i++)
4260 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4263 for (i = 0;i < numvertices;i++)
4264 Vector4Copy(color4f + 4*i, vertex[i].color4f);
4268 for (i = 0;i < numvertices;i++)
4269 Vector4Copy(gl_state.color4f, vertex[i].color4f);
4271 if (texcoordtexture2f)
4272 for (i = 0;i < numvertices;i++)
4273 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4274 if (texcoordlightmap2f)
4275 for (i = 0;i < numvertices;i++)
4276 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4277 R_Mesh_PrepareVertices_Mesh_Unlock();
4278 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4281 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4283 // upload temporary vertexbuffer for this rendering
4284 if (!gl_state.usevbo_staticvertex)
4285 vertexbuffer = NULL;
4286 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4288 if (gl_state.preparevertices_dynamicvertexbuffer)
4289 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4291 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4292 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4294 switch(vid.renderpath)
4296 case RENDERPATH_GL20:
4297 case RENDERPATH_GLES2:
4300 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4301 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4302 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4303 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4304 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4305 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4306 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4310 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4311 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4312 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4313 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4314 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4315 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4316 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4319 case RENDERPATH_GL13:
4320 case RENDERPATH_GLES1:
4323 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4324 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4325 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4326 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4330 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4331 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4332 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4333 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4336 case RENDERPATH_GL11:
4339 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4340 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
4341 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4345 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4346 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
4347 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4350 case RENDERPATH_D3D9:
4352 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4354 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4356 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4357 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4358 gl_state.d3dvertexdata = (void *)vertex;
4359 gl_state.d3dvertexsize = sizeof(*vertex);
4362 case RENDERPATH_D3D10:
4363 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4365 case RENDERPATH_D3D11:
4366 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4368 case RENDERPATH_SOFT:
4369 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4370 DPSOFTRAST_SetColorPointer(vertex->color4f, sizeof(*vertex));
4371 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4372 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4373 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4374 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4375 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);