9 // 65536 is the max addressable on a Geforce 256 up until Geforce3
10 // (excluding MX), seems a reasonable number...
11 cvar_t gl_mesh_maxverts = {0, "gl_mesh_maxverts", "65536"};
12 cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"};
13 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1"};
15 cvar_t gl_mesh_vertex_array_range = {0, "gl_mesh_vertex_array_range", "0"};
16 cvar_t gl_mesh_vertex_array_range_readfrequency = {0, "gl_mesh_vertex_array_range_readfrequency", "0.2"};
17 cvar_t gl_mesh_vertex_array_range_writefrequency = {0, "gl_mesh_vertex_array_range_writefrequency", "0.2"};
18 cvar_t gl_mesh_vertex_array_range_priority = {0, "gl_mesh_vertex_array_range_priority", "0.7"};
21 cvar_t gl_mesh_batching = {0, "gl_mesh_batching", "1"};
23 cvar_t gl_mesh_copyarrays = {0, "gl_mesh_copyarrays", "1"};
24 cvar_t gl_delayfinish = {CVAR_SAVE, "gl_delayfinish", "0"};
26 cvar_t r_render = {0, "r_render", "1"};
27 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1"}; // whether or not to use dithering
28 cvar_t gl_lockarrays = {0, "gl_lockarrays", "1"};
30 int gl_maxdrawrangeelementsvertices;
31 int gl_maxdrawrangeelementsindices;
36 void GL_PrintError(int errornumber, char *filename, int linenumber)
40 #ifdef GL_INVALID_ENUM
42 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
45 #ifdef GL_INVALID_VALUE
46 case GL_INVALID_VALUE:
47 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
50 #ifdef GL_INVALID_OPERATION
51 case GL_INVALID_OPERATION:
52 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
55 #ifdef GL_STACK_OVERFLOW
56 case GL_STACK_OVERFLOW:
57 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
60 #ifdef GL_STACK_UNDERFLOW
61 case GL_STACK_UNDERFLOW:
62 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
65 #ifdef GL_OUT_OF_MEMORY
66 case GL_OUT_OF_MEMORY:
67 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
70 #ifdef GL_TABLE_TOO_LARGE
71 case GL_TABLE_TOO_LARGE:
72 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
76 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
82 #define BACKENDACTIVECHECK if (!backendactive) Sys_Error("GL backend function called when backend is not active\n");
84 int c_meshs, c_meshelements;
86 void SCR_ScreenShot_f (void);
88 // these are externally accessible
89 int r_lightmapscalebit;
91 GLfloat *varray_vertex3f, *varray_buf_vertex3f;
92 GLfloat *varray_color4f, *varray_buf_color4f;
93 GLfloat *varray_texcoord3f[MAX_TEXTUREUNITS], *varray_buf_texcoord3f[MAX_TEXTUREUNITS];
94 GLfloat *varray_texcoord2f[MAX_TEXTUREUNITS], *varray_buf_texcoord2f[MAX_TEXTUREUNITS];
95 static qbyte *varray_buf_color4b;
99 float mesh_var_readfrequency;
100 float mesh_var_writefrequency;
101 float mesh_var_priority;
103 int varray_offset = 0, varray_offsetnext = 0;
104 GLuint *varray_buf_elements3i;
105 int mesh_maxelements = 32768;
107 int gl_batchvertexfirst = 0;
108 int gl_batchvertexcount = 0;
109 int gl_batchelementcount = 0;
112 static matrix4x4_t backend_viewmatrix;
113 static matrix4x4_t backend_modelmatrix;
114 static matrix4x4_t backend_modelviewmatrix;
115 static matrix4x4_t backend_glmodelviewmatrix;
116 static matrix4x4_t backend_projectmatrix;
118 static int backendunits, backendactive;
119 static mempool_t *gl_backend_mempool;
122 note: here's strip order for a terrain row:
128 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
130 *elements++ = i + row;
132 *elements++ = i + row + 1;
135 *elements++ = i + row + 1;
138 void GL_Backend_AllocElementsArray(void)
140 if (varray_buf_elements3i)
141 Mem_Free(varray_buf_elements3i);
142 varray_buf_elements3i = Mem_Alloc(gl_backend_mempool, mesh_maxelements * sizeof(GLuint));
145 void GL_Backend_FreeElementArray(void)
147 if (varray_buf_elements3i)
148 Mem_Free(varray_buf_elements3i);
149 varray_buf_elements3i = NULL;
152 void GL_Backend_CheckCvars(void)
154 if (gl_mesh_maxverts.integer < 1024)
155 Cvar_SetValueQuick(&gl_mesh_maxverts, 1024);
156 if (gl_mesh_maxverts.integer > 65536)
157 Cvar_SetValueQuick(&gl_mesh_maxverts, 65536);
159 if (gl_mesh_vertex_array_range.integer && !gl_support_var)
160 Cvar_SetValueQuick(&gl_mesh_vertex_array_range, 0);
161 if (gl_mesh_vertex_array_range_readfrequency.value < 0)
162 Cvar_SetValueQuick(&gl_mesh_vertex_array_range_readfrequency, 0);
163 if (gl_mesh_vertex_array_range_readfrequency.value > 1)
164 Cvar_SetValueQuick(&gl_mesh_vertex_array_range_readfrequency, 1);
165 if (gl_mesh_vertex_array_range_writefrequency.value < 0)
166 Cvar_SetValueQuick(&gl_mesh_vertex_array_range_writefrequency, 0);
167 if (gl_mesh_vertex_array_range_writefrequency.value > 1)
168 Cvar_SetValueQuick(&gl_mesh_vertex_array_range_writefrequency, 1);
169 if (gl_mesh_vertex_array_range_priority.value < 0)
170 Cvar_SetValueQuick(&gl_mesh_vertex_array_range_priority, 0);
171 if (gl_mesh_vertex_array_range_priority.value > 1)
172 Cvar_SetValueQuick(&gl_mesh_vertex_array_range_priority, 1);
176 int polygonelements[768];
178 void GL_Backend_AllocArrays(void)
183 if (!gl_backend_mempool)
185 gl_backend_mempool = Mem_AllocPool("GL_Backend");
186 varray_buf_vertex3f = NULL;
187 varray_buf_color4f = NULL;
188 varray_buf_color4b = NULL;
189 varray_buf_elements3i = NULL;
190 for (i = 0;i < MAX_TEXTUREUNITS;i++)
191 varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL;
194 if (varray_buf_vertex3f)
196 VID_FreeVertexArrays(varray_buf_vertex3f);
198 Mem_Free(varray_buf_vertex3f);
200 varray_buf_vertex3f = NULL;
201 varray_buf_color4f = NULL;
202 varray_buf_color4b = NULL;
203 for (i = 0;i < MAX_TEXTUREUNITS;i++)
204 varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL;
206 mesh_maxverts = gl_mesh_maxverts.integer;
207 size = mesh_maxverts * (sizeof(float[3]) + sizeof(float[4]) + sizeof(qbyte[4]) + (sizeof(float[3]) + sizeof(float[2])) * backendunits);
209 mesh_var = gl_mesh_vertex_array_range.integer && gl_support_var;
210 mesh_var_readfrequency = gl_mesh_vertex_array_range_readfrequency.value;
211 mesh_var_writefrequency = gl_mesh_vertex_array_range_writefrequency.value;
212 mesh_var_priority = gl_mesh_vertex_array_range_priority.value;
213 data = VID_AllocVertexArrays(gl_backend_mempool, size, gl_mesh_vertex_array_range.integer, gl_mesh_vertex_array_range_readfrequency.value, gl_mesh_vertex_array_range_writefrequency.value, gl_mesh_vertex_array_range_priority.value);
215 data = Mem_Alloc(gl_backend_mempool, size);
218 varray_buf_vertex3f = (void *)data;data += sizeof(float[3]) * mesh_maxverts;
219 varray_buf_color4f = (void *)data;data += sizeof(float[4]) * mesh_maxverts;
220 for (i = 0;i < backendunits;i++)
222 varray_buf_texcoord3f[i] = (void *)data;data += sizeof(float[3]) * mesh_maxverts;
223 varray_buf_texcoord2f[i] = (void *)data;data += sizeof(float[2]) * mesh_maxverts;
225 for (;i < MAX_TEXTUREUNITS;i++)
226 varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL;
227 varray_buf_color4b = (void *)data;data += sizeof(qbyte[4]) * mesh_maxverts;
229 GL_Backend_AllocElementsArray();
235 qglVertexArrayRangeNV(size, varray_buf_vertex3f);
241 void GL_Backend_FreeArrays(void)
249 qglDisableClientState(GL_VERTEX_ARRAY_RANGE_NV);
254 if (varray_buf_vertex3f)
256 VID_FreeVertexArrays(varray_buf_vertex3f);
258 Mem_Free(varray_buf_vertex3f);
260 varray_buf_vertex3f = NULL;
261 varray_buf_color4f = NULL;
262 varray_buf_color4b = NULL;
263 for (i = 0;i < MAX_TEXTUREUNITS;i++)
264 varray_buf_texcoord3f[i] = varray_buf_texcoord2f[i] = NULL;
265 varray_buf_elements3i = NULL;
267 Mem_FreePool(&gl_backend_mempool);
270 static void gl_backend_start(void)
272 GL_Backend_CheckCvars();
274 Con_Printf("OpenGL Backend started with gl_mesh_maxverts %i\n", gl_mesh_maxverts.integer);
275 if (qglDrawRangeElements != NULL)
278 qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
280 qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
282 Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
284 if (strstr(gl_renderer, "3Dfx"))
286 Con_Printf("3Dfx driver detected, forcing gl_mesh_floatcolors to 0 to prevent crashs\n");
287 Cvar_SetValueQuick(&gl_mesh_floatcolors, 0);
290 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
292 GL_Backend_AllocArrays();
298 qglEnableClientState(GL_VERTEX_ARRAY_RANGE_NV);
302 varray_offset = varray_offsetnext = 0;
304 gl_batchvertexfirst = 0;
305 gl_batchvertexcount = 0;
306 gl_batchelementcount = 0;
309 backendactive = true;
312 static void gl_backend_shutdown(void)
315 backendactive = false;
317 Con_Printf("OpenGL Backend shutting down\n");
323 qglDisableClientState(GL_VERTEX_ARRAY_RANGE_NV);
328 GL_Backend_FreeArrays();
331 void GL_Backend_ResizeArrays(int numvertices)
333 Cvar_SetValueQuick(&gl_mesh_maxverts, numvertices);
334 GL_Backend_CheckCvars();
335 mesh_maxverts = gl_mesh_maxverts.integer;
336 GL_Backend_AllocArrays();
339 static void gl_backend_newmap(void)
343 void gl_backend_init(void)
347 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
349 polygonelements[i * 3 + 0] = 0;
350 polygonelements[i * 3 + 1] = i + 1;
351 polygonelements[i * 3 + 2] = i + 2;
354 Cvar_RegisterVariable(&r_render);
355 Cvar_RegisterVariable(&gl_dither);
356 Cvar_RegisterVariable(&gl_lockarrays);
357 Cvar_RegisterVariable(&gl_delayfinish);
359 Cvar_SetValue("r_render", 0);
362 Cvar_RegisterVariable(&gl_mesh_maxverts);
363 Cvar_RegisterVariable(&gl_mesh_floatcolors);
364 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
366 Cvar_RegisterVariable(&gl_mesh_vertex_array_range);
367 Cvar_RegisterVariable(&gl_mesh_vertex_array_range_readfrequency);
368 Cvar_RegisterVariable(&gl_mesh_vertex_array_range_writefrequency);
369 Cvar_RegisterVariable(&gl_mesh_vertex_array_range_priority);
372 Cvar_RegisterVariable(&gl_mesh_batching);
374 Cvar_RegisterVariable(&gl_mesh_copyarrays);
375 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
378 void GL_SetupView_ViewPort (int x, int y, int width, int height)
380 if (!r_render.integer)
383 // y is weird beause OpenGL is bottom to top, we use top to bottom
384 qglViewport(x, vid.realheight - (y + height), width, height);
388 void GL_SetupView_Orientation_Identity (void)
390 Matrix4x4_CreateIdentity(&backend_viewmatrix);
391 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
394 void GL_SetupView_Orientation_FromEntity (vec3_t origin, vec3_t angles)
396 Matrix4x4_CreateRotate(&backend_viewmatrix, -90, 1, 0, 0);
397 Matrix4x4_ConcatRotate(&backend_viewmatrix, 90, 0, 0, 1);
398 Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
399 Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
400 Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
401 Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
402 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
405 void GL_SetupView_Mode_Perspective (double fovx, double fovy, double zNear, double zFar)
409 if (!r_render.integer)
413 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
414 qglLoadIdentity();CHECKGLERROR
416 xmax = zNear * tan(fovx * M_PI / 360.0);
417 ymax = zNear * tan(fovy * M_PI / 360.0);
419 qglFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar);CHECKGLERROR
420 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
421 GL_SetupView_Orientation_Identity();
424 void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double fovx, double fovy, double zNear)
428 if (!r_render.integer)
432 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
433 qglLoadIdentity();CHECKGLERROR
435 nudge = 1.0 - 1.0 / (1<<23);
436 m[ 0] = 1.0 / tan(fovx * M_PI / 360.0);
441 m[ 5] = 1.0 / tan(fovy * M_PI / 360.0);
450 m[14] = -2 * zNear * nudge;
453 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
454 GL_SetupView_Orientation_Identity();
455 backend_projectmatrix.m[0][0] = m[0];
456 backend_projectmatrix.m[1][0] = m[1];
457 backend_projectmatrix.m[2][0] = m[2];
458 backend_projectmatrix.m[3][0] = m[3];
459 backend_projectmatrix.m[0][1] = m[4];
460 backend_projectmatrix.m[1][1] = m[5];
461 backend_projectmatrix.m[2][1] = m[6];
462 backend_projectmatrix.m[3][1] = m[7];
463 backend_projectmatrix.m[0][2] = m[8];
464 backend_projectmatrix.m[1][2] = m[9];
465 backend_projectmatrix.m[2][2] = m[10];
466 backend_projectmatrix.m[3][2] = m[11];
467 backend_projectmatrix.m[0][3] = m[12];
468 backend_projectmatrix.m[1][3] = m[13];
469 backend_projectmatrix.m[2][3] = m[14];
470 backend_projectmatrix.m[3][3] = m[15];
473 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
475 if (!r_render.integer)
479 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
480 qglLoadIdentity();CHECKGLERROR
481 qglOrtho(x1, x2, y2, y1, zNear, zFar);
482 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
483 GL_SetupView_Orientation_Identity();
486 typedef struct gltextureunit_s
488 int t1d, t2d, t3d, tcubemap;
489 int arrayenabled, arrayis3d;
490 void *pointer_texcoord;
491 float rgbscale, alphascale;
492 int combinergb, combinealpha;
493 // FIXME: add more combine stuff
506 gltextureunit_t units[MAX_TEXTUREUNITS];
511 int pointervertexcount;
512 void *pointer_vertex;
517 void GL_SetupTextureState(void)
520 gltextureunit_t *unit;
521 for (i = 0;i < backendunits;i++)
523 if (qglActiveTexture)
524 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
525 if (qglClientActiveTexture)
526 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
527 unit = gl_state.units + i;
532 unit->arrayenabled = false;
533 unit->arrayis3d = false;
534 unit->pointer_texcoord = NULL;
536 unit->alphascale = 1;
537 unit->combinergb = GL_MODULATE;
538 unit->combinealpha = GL_MODULATE;
539 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
540 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), varray_buf_texcoord2f[i]);CHECKGLERROR
541 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
542 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
545 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
547 if (gl_texturecubemap)
549 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
551 if (gl_combine.integer)
553 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
554 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
555 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
556 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
557 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB);CHECKGLERROR
558 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
559 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
560 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
561 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
562 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
563 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
564 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
565 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
566 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
567 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
568 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
569 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
573 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
578 void GL_Backend_ResetState(void)
580 memset(&gl_state, 0, sizeof(gl_state));
581 gl_state.depthdisable = false;
582 gl_state.blendfunc1 = GL_ONE;
583 gl_state.blendfunc2 = GL_ZERO;
584 gl_state.blend = false;
585 gl_state.depthmask = GL_TRUE;
586 gl_state.colorarray = false;
587 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
588 gl_state.lockrange_first = 0;
589 gl_state.lockrange_count = 0;
590 gl_state.pointervertexcount = 0;
591 gl_state.pointer_vertex = NULL;
592 gl_state.pointer_color = NULL;
595 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
596 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
598 qglEnable(GL_CULL_FACE);CHECKGLERROR
599 qglCullFace(GL_FRONT);CHECKGLERROR
600 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
601 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
602 qglDisable(GL_BLEND);CHECKGLERROR
603 qglDepthMask(gl_state.depthmask);CHECKGLERROR
604 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), varray_buf_vertex3f);CHECKGLERROR
605 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
606 if (gl_mesh_floatcolors.integer)
608 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), varray_buf_color4f);CHECKGLERROR
612 qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), varray_buf_color4b);CHECKGLERROR
614 GL_Color(0, 0, 0, 0);
615 GL_Color(1, 1, 1, 1);
617 GL_SetupTextureState();
620 void GL_UseColorArray(void)
622 if (!gl_state.colorarray)
625 if (gl_batchelementcount)
628 gl_state.colorarray = true;
629 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
633 void GL_Color(float cr, float cg, float cb, float ca)
635 if (gl_state.colorarray)
638 if (gl_batchelementcount)
641 gl_state.colorarray = false;
642 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
643 gl_state.color4f[0] = cr;
644 gl_state.color4f[1] = cg;
645 gl_state.color4f[2] = cb;
646 gl_state.color4f[3] = ca;
647 qglColor4f(cr, cg, cb, ca);
651 if (gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
654 if (gl_batchelementcount)
657 gl_state.color4f[0] = cr;
658 gl_state.color4f[1] = cg;
659 gl_state.color4f[2] = cb;
660 gl_state.color4f[3] = ca;
661 qglColor4f(cr, cg, cb, ca);
666 void GL_LockArrays(int first, int count)
668 if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
670 if (gl_state.lockrange_count)
672 gl_state.lockrange_count = 0;
674 qglUnlockArraysEXT();
677 if (count && gl_supportslockarrays && gl_lockarrays.integer)
679 gl_state.lockrange_first = first;
680 gl_state.lockrange_count = count;
682 qglLockArraysEXT(first, count);
688 void GL_TransformToScreen(const vec4_t in, vec4_t out)
692 Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
693 Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
695 out[0] = r_refdef.x + (out[0] * iw + 1.0f) * r_refdef.width * 0.5f;
696 out[1] = r_refdef.y + (out[1] * iw + 1.0f) * r_refdef.height * 0.5f;
697 out[2] = out[2] * iw;
700 // called at beginning of frame
701 void R_Mesh_Start(void)
707 GL_Backend_CheckCvars();
708 if (mesh_maxverts != gl_mesh_maxverts.integer
710 || mesh_var != (gl_mesh_vertex_array_range.integer && gl_support_var)
711 || mesh_var_readfrequency != gl_mesh_vertex_array_range_readfrequency.value
712 || mesh_var_writefrequency != gl_mesh_vertex_array_range_writefrequency.value
713 || mesh_var_priority != gl_mesh_vertex_array_range_priority.value
716 GL_Backend_ResizeArrays(gl_mesh_maxverts.integer);
718 GL_Backend_ResetState();
722 gl_batchvertexfirst = gl_batchvertexcount = gl_batchelementcount = 0;
723 varray_offset = varray_offsetnext = 0;
726 varray_offset = varray_offsetnext = 0;
730 int gl_backend_rebindtextures;
732 void GL_ConvertColorsFloatToByte(int first, int count)
735 union {float f[4];int i[4];} *color4fi;
736 struct {GLubyte c[4];} *color4b;
738 // shift float to have 8bit fraction at base of number
739 color4fi = (void *)(varray_buf_color4f + first * 4);
740 for (i = 0;i < count;i++, color4fi++)
742 color4fi->f[0] += 32768.0f;
743 color4fi->f[1] += 32768.0f;
744 color4fi->f[2] += 32768.0f;
745 color4fi->f[3] += 32768.0f;
748 // then read as integer and kill float bits...
749 color4fi = (void *)(varray_buf_color4f + first * 4);
750 color4b = (void *)(varray_buf_color4b + first * 4);
751 for (i = 0;i < count;i++, color4fi++, color4b++)
753 k = color4fi->i[0] & 0x7FFFFF;color4b->c[0] = (GLubyte) min(k, 255);
754 k = color4fi->i[1] & 0x7FFFFF;color4b->c[1] = (GLubyte) min(k, 255);
755 k = color4fi->i[2] & 0x7FFFFF;color4b->c[2] = (GLubyte) min(k, 255);
756 k = color4fi->i[3] & 0x7FFFFF;color4b->c[3] = (GLubyte) min(k, 255);
761 // enlarges geometry buffers if they are too small
762 void _R_Mesh_ResizeCheck(int numverts)
764 if (numverts > mesh_maxverts)
767 GL_Backend_ResizeArrays(numverts + 100);
768 GL_Backend_ResetState();
773 void R_Mesh_EndBatch(void)
776 if (gl_batchelementcount)
778 if (gl_state.pointervertexcount)
779 Host_Error("R_Mesh_EndBatch: called with pointers enabled\n");
781 if (gl_state.colorarray && !gl_mesh_floatcolors.integer && gl_state.pointer_color == NULL)
782 GL_ConvertColorsFloatToByte(gl_batchvertexfirst, gl_batchvertexcount);
783 if (r_render.integer)
785 //int i;for (i = 0;i < gl_batchelementcount;i++) if (varray_buf_elements3i[i] < gl_batchvertexfirst || varray_buf_elements3i[i] >= (gl_batchvertexfirst + gl_batchvertexcount)) Host_Error("R_Mesh_EndBatch: invalid element #%i (value %i) outside range %i-%i\n", i, varray_buf_elements3i[i], gl_batchvertexfirst, gl_batchvertexfirst + gl_batchvertexcount);
787 GL_LockArrays(gl_batchvertexfirst, gl_batchvertexcount);
788 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
790 qglDrawRangeElements(GL_TRIANGLES, gl_batchvertexfirst, gl_batchvertexfirst + gl_batchvertexcount, gl_batchelementcount, GL_UNSIGNED_INT, (const GLuint *) varray_buf_elements3i);CHECKGLERROR
794 qglDrawElements(GL_TRIANGLES, gl_batchelementcount, GL_UNSIGNED_INT, (const GLuint *) varray_buf_elements3i);CHECKGLERROR
798 gl_batchelementcount = 0;
799 gl_batchvertexcount = 0;
804 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
808 for (i = 0;i < count;i++)
809 *out++ = *in++ + offset;
811 // memcpy(out, in, sizeof(*out) * count);
814 // gets vertex buffer space for use with a following R_Mesh_Draw
815 // (can be multiple Draw calls per GetSpace)
816 void R_Mesh_GetSpace(int numverts)
820 if (gl_state.pointervertexcount)
821 Host_Error("R_Mesh_GetSpace: called with pointers enabled\n");
822 if (gl_state.lockrange_count)
823 Host_Error("R_Mesh_GetSpace: called with arrays locked\n");
825 varray_offset = varray_offsetnext;
826 if (varray_offset + numverts > mesh_maxverts)
828 //Con_Printf("R_Mesh_GetSpace: vertex buffer wrap\n");
830 if (gl_batchelementcount)
838 qglFlushVertexArrayRangeNV();
842 if (numverts > mesh_maxverts)
844 GL_Backend_ResizeArrays(numverts + 100);
845 GL_Backend_ResetState();
851 if (gl_mesh_batching.integer)
853 if (gl_batchvertexcount == 0)
854 gl_batchvertexfirst = varray_offset;
855 gl_batchvertexcount += numverts;
859 varray_vertex3f = varray_buf_vertex3f + varray_offset * 3;
860 varray_color4f = varray_buf_color4f + varray_offset * 4;
861 for (i = 0;i < backendunits;i++)
863 varray_texcoord3f[i] = varray_buf_texcoord3f[i] + varray_offset * 3;
864 varray_texcoord2f[i] = varray_buf_texcoord2f[i] + varray_offset * 2;
867 varray_offsetnext = varray_offset + numverts;
870 // renders triangles using vertices from the most recent GetSpace call
871 // (can be multiple Draw calls per GetSpace)
872 void R_Mesh_Draw(int numverts, int numtriangles, const int *elements)
874 int numelements = numtriangles * 3;
875 if (numtriangles == 0 || numverts == 0)
877 Con_Printf("R_Mesh_Draw(%d, %d, %08p);\n", numverts, numtriangles, elements);
881 c_meshelements += numelements;
883 if (gl_state.pointervertexcount)
886 if (gl_batchelementcount)
889 if (r_render.integer)
891 GL_LockArrays(0, gl_state.pointervertexcount);
892 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
894 qglDrawRangeElements(GL_TRIANGLES, 0, gl_state.pointervertexcount, numelements, GL_UNSIGNED_INT, elements);CHECKGLERROR
898 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, elements);CHECKGLERROR
904 else if (gl_mesh_batching.integer)
906 if (mesh_maxelements < gl_batchelementcount + numelements)
908 //Con_Printf("R_Mesh_Draw: enlarging elements array\n");
909 if (gl_batchelementcount)
911 // round up to a multiple of 1024 and add another 1024 just for good measure
912 mesh_maxelements = (gl_batchelementcount + numelements + 1024 + 1023) & ~1023;
913 GL_Backend_AllocElementsArray();
915 if (varray_offset < gl_batchvertexfirst && gl_batchelementcount)
917 if (gl_batchelementcount == 0)
919 gl_batchvertexfirst = varray_offset;
920 gl_batchvertexcount = 0;
922 if (gl_batchvertexcount < varray_offsetnext - gl_batchvertexfirst)
923 gl_batchvertexcount = varray_offsetnext - gl_batchvertexfirst;
924 GL_Backend_RenumberElements(varray_buf_elements3i + gl_batchelementcount, numelements, elements, varray_offset);
925 //Con_Printf("off %i:%i, vertex %i:%i, element %i:%i\n", varray_offset, varray_offsetnext, gl_batchvertexfirst, gl_batchvertexfirst + gl_batchvertexcount, gl_batchelementcount, gl_batchelementcount + numelements);
926 gl_batchelementcount += numelements;
927 //{int i;for (i = 0;i < gl_batchelementcount;i++) if (varray_buf_elements3i[i] < gl_batchvertexfirst || varray_buf_elements3i[i] >= (gl_batchvertexfirst + gl_batchvertexcount)) Host_Error("R_Mesh_EndBatch: invalid element #%i (value %i) outside range %i-%i, there were previously %i elements and there are now %i elements, varray_offset is %i\n", i, varray_buf_elements3i[i], gl_batchvertexfirst, gl_batchvertexfirst + gl_batchvertexcount, gl_batchelementcount - numelements, gl_batchelementcount, varray_offset);}
932 GL_Backend_RenumberElements(varray_buf_elements3i, numelements, elements, varray_offset);
933 if (r_render.integer)
935 GL_LockArrays(varray_offset, numverts);
936 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
938 qglDrawRangeElements(GL_TRIANGLES, varray_offset, varray_offset + numverts, numelements, GL_UNSIGNED_INT, varray_buf_elements3i);CHECKGLERROR
942 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, varray_buf_elements3i);CHECKGLERROR
949 // restores backend state, used when done with 3D rendering
950 void R_Mesh_Finish(void)
955 if (gl_batchelementcount)
960 for (i = backendunits - 1;i >= 0;i--)
962 if (qglActiveTexture)
963 qglActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR
964 if (qglClientActiveTexture)
965 qglClientActiveTexture(GL_TEXTURE0_ARB + i);CHECKGLERROR
966 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
967 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
968 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
971 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
973 if (gl_texturecubemap)
975 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
977 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
978 if (gl_combine.integer)
980 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
981 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
984 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
985 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
987 qglDisable(GL_BLEND);CHECKGLERROR
988 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
989 qglDepthMask(GL_TRUE);CHECKGLERROR
990 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
993 void R_Mesh_Matrix(const matrix4x4_t *matrix)
995 if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
998 if (gl_batchelementcount)
1001 backend_modelmatrix = *matrix;
1002 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
1003 Matrix4x4_Transpose(&backend_glmodelviewmatrix, &backend_modelviewmatrix);
1004 qglLoadMatrixf(&backend_glmodelviewmatrix.m[0][0]);
1008 // sets up the requested state
1009 void R_Mesh_MainState(const rmeshstate_t *m)
1014 if (gl_state.blendfunc1 != m->blendfunc1 || gl_state.blendfunc2 != m->blendfunc2)
1017 if (gl_batchelementcount)
1020 qglBlendFunc(gl_state.blendfunc1 = m->blendfunc1, gl_state.blendfunc2 = m->blendfunc2);CHECKGLERROR
1021 if (gl_state.blendfunc2 == GL_ZERO)
1023 if (gl_state.blendfunc1 == GL_ONE)
1028 qglDisable(GL_BLEND);CHECKGLERROR
1033 if (!gl_state.blend)
1036 qglEnable(GL_BLEND);CHECKGLERROR
1042 if (!gl_state.blend)
1045 qglEnable(GL_BLEND);CHECKGLERROR
1049 if (gl_state.depthdisable != m->depthdisable)
1052 if (gl_batchelementcount)
1055 gl_state.depthdisable = m->depthdisable;
1056 if (gl_state.depthdisable)
1057 qglDisable(GL_DEPTH_TEST);
1059 qglEnable(GL_DEPTH_TEST);
1061 if (gl_state.depthmask != (m->blendfunc2 == GL_ZERO || m->depthwrite))
1064 if (gl_batchelementcount)
1067 qglDepthMask(gl_state.depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite));CHECKGLERROR
1070 if (gl_state.pointervertexcount != m->pointervertexcount)
1073 if (gl_batchelementcount)
1076 gl_state.pointervertexcount = m->pointervertexcount;
1079 p = gl_state.pointervertexcount ? m->pointer_vertex : NULL;
1080 if (gl_state.pointer_vertex != p)
1083 if (gl_batchelementcount)
1086 gl_state.pointer_vertex = p;
1087 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), p ? p : varray_buf_vertex3f);CHECKGLERROR
1090 if (gl_state.colorarray)
1092 p = gl_state.pointervertexcount ? m->pointer_color : NULL;
1093 if (gl_state.pointer_color != p)
1096 if (gl_batchelementcount)
1099 gl_state.pointer_color = p;
1100 if (p != varray_buf_color4f || gl_mesh_floatcolors.integer)
1101 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), p ? p : varray_buf_color4f);
1103 qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GLubyte[4]), p ? p : varray_buf_color4b);
1109 void R_Mesh_TextureState(const rmeshstate_t *m)
1111 int i, combinergb, combinealpha;
1113 gltextureunit_t *unit;
1118 if (gl_backend_rebindtextures)
1120 gl_backend_rebindtextures = false;
1121 GL_SetupTextureState();
1124 for (i = 0;i < backendunits;i++)
1126 unit = gl_state.units + i;
1127 if (unit->t1d != m->tex1d[i] || unit->t2d != m->tex[i] || unit->t3d != m->tex3d[i] || unit->tcubemap != m->texcubemap[i])
1129 if (m->tex3d[i] || m->texcubemap[i])
1131 if (!unit->arrayis3d)
1134 if (gl_batchelementcount)
1137 unit->arrayis3d = true;
1138 if (gl_state.clientunit != i)
1140 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
1142 qglTexCoordPointer(3, GL_FLOAT, sizeof(float[3]), varray_buf_texcoord3f[i]);
1144 if (!unit->arrayenabled)
1147 if (gl_batchelementcount)
1150 unit->arrayenabled = true;
1151 if (gl_state.clientunit != i)
1153 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
1155 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1158 else if (m->tex1d[i] || m->tex[i])
1160 if (unit->arrayis3d)
1163 if (gl_batchelementcount)
1166 unit->arrayis3d = false;
1167 if (gl_state.clientunit != i)
1169 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
1171 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), varray_buf_texcoord2f[i]);
1173 if (!unit->arrayenabled)
1176 if (gl_batchelementcount)
1179 unit->arrayenabled = true;
1180 if (gl_state.clientunit != i)
1182 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
1184 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1189 if (unit->arrayenabled)
1192 if (gl_batchelementcount)
1195 unit->arrayenabled = false;
1196 if (gl_state.clientunit != i)
1198 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
1200 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1203 if (unit->t1d != m->tex1d[i])
1206 if (gl_batchelementcount)
1209 if (gl_state.unit != i)
1211 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
1216 qglEnable(GL_TEXTURE_1D);CHECKGLERROR
1221 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1223 qglBindTexture(GL_TEXTURE_1D, (unit->t1d = m->tex1d[i]));CHECKGLERROR
1225 if (unit->t2d != m->tex[i])
1228 if (gl_batchelementcount)
1231 if (gl_state.unit != i)
1233 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
1238 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1243 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1245 qglBindTexture(GL_TEXTURE_2D, (unit->t2d = m->tex[i]));CHECKGLERROR
1247 if (unit->t3d != m->tex3d[i])
1250 if (gl_batchelementcount)
1253 if (gl_state.unit != i)
1255 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
1260 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1265 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1267 qglBindTexture(GL_TEXTURE_3D, (unit->t3d = m->tex3d[i]));CHECKGLERROR
1269 if (unit->tcubemap != m->texcubemap[i])
1272 if (gl_batchelementcount)
1275 if (gl_state.unit != i)
1277 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
1279 if (m->texcubemap[i])
1281 if (unit->tcubemap == 0)
1282 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1287 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1289 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, (unit->tcubemap = m->texcubemap[i]));CHECKGLERROR
1292 combinergb = m->texcombinergb[i];
1294 combinergb = GL_MODULATE;
1295 if (unit->combinergb != combinergb)
1298 if (gl_batchelementcount)
1301 if (gl_state.unit != i)
1303 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
1305 unit->combinergb = combinergb;
1306 if (gl_combine.integer)
1308 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1312 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1315 combinealpha = m->texcombinealpha[i];
1317 combinealpha = GL_MODULATE;
1318 if (unit->combinealpha != combinealpha)
1321 if (gl_batchelementcount)
1324 if (gl_state.unit != i)
1326 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
1328 unit->combinealpha = combinealpha;
1329 if (gl_combine.integer)
1331 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1334 scale = max(m->texrgbscale[i], 1);
1335 if (gl_state.units[i].rgbscale != scale)
1338 if (gl_batchelementcount)
1341 if (gl_state.unit != i)
1343 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
1345 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (gl_state.units[i].rgbscale = scale));CHECKGLERROR
1347 scale = max(m->texalphascale[i], 1);
1348 if (gl_state.units[i].alphascale != scale)
1351 if (gl_batchelementcount)
1354 if (gl_state.unit != i)
1356 qglActiveTexture(GL_TEXTURE0_ARB + (gl_state.unit = i));CHECKGLERROR
1358 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (gl_state.units[i].alphascale = scale));CHECKGLERROR
1360 if (unit->arrayenabled)
1362 p = gl_state.pointervertexcount ? m->pointer_texcoord[i] : NULL;
1363 if (unit->pointer_texcoord != p)
1366 if (gl_batchelementcount)
1369 unit->pointer_texcoord = p;
1370 if (gl_state.clientunit != i)
1372 qglClientActiveTexture(GL_TEXTURE0_ARB + (gl_state.clientunit = i));CHECKGLERROR
1374 if (unit->arrayis3d)
1375 qglTexCoordPointer(3, GL_FLOAT, sizeof(float[3]), p ? p : varray_buf_texcoord3f[i]);
1377 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), p ? p : varray_buf_texcoord2f[i]);
1384 void R_Mesh_State(const rmeshstate_t *m)
1386 R_Mesh_MainState(m);
1387 R_Mesh_TextureState(m);
1391 ==============================================================================
1395 ==============================================================================
1398 qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height, qboolean jpeg)
1404 if (!r_render.integer)
1407 buffer = Mem_Alloc(tempmempool, width*height*3);
1408 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
1411 // LordHavoc: compensate for v_overbrightbits when using hardware gamma
1412 if (v_hwgamma.integer)
1414 for (i = 0;i < width * height * 3;i++)
1416 j = buffer[i] << v_overbrightbits.integer;
1417 buffer[i] = (qbyte) (bound(0, j, 255));
1422 ret = JPEG_SaveImage_preflipped (filename, width, height, buffer);
1424 ret = Image_WriteTGARGB_preflipped (filename, width, height, buffer);
1430 //=============================================================================
1432 void R_ClearScreen(void)
1434 if (r_render.integer)
1437 qglClearColor(0,0,0,0);CHECKGLERROR
1438 qglClearDepth(1);CHECKGLERROR
1441 // LordHavoc: we use a stencil centered around 128 instead of 0,
1442 // to avoid clamping interfering with strange shadow volume
1444 qglClearStencil(128);CHECKGLERROR
1447 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));CHECKGLERROR
1448 // set dithering mode
1449 if (gl_dither.integer)
1451 qglEnable(GL_DITHER);CHECKGLERROR
1455 qglDisable(GL_DITHER);CHECKGLERROR
1464 This is called every frame, and can also be called explicitly to flush
1468 void SCR_UpdateScreen (void)
1470 if (gl_delayfinish.integer)
1474 R_TimeReport("finish");
1477 if (r_textureunits.integer > gl_textureunits)
1478 Cvar_SetValueQuick(&r_textureunits, gl_textureunits);
1479 if (r_textureunits.integer < 1)
1480 Cvar_SetValueQuick(&r_textureunits, 1);
1482 if (gl_combine.integer && (!gl_combine_extension || r_textureunits.integer < 2))
1483 Cvar_SetValueQuick(&gl_combine, 0);
1486 r_colorscale = 1.0f / (float) (1 << v_overbrightbits.integer);
1489 r_lightmapscalebit = v_overbrightbits.integer;
1490 if (gl_combine.integer && r_textureunits.integer > 1)
1491 r_lightmapscalebit += 2;
1493 R_TimeReport("setup");
1497 R_TimeReport("clear");
1499 if (scr_conlines < vid.conheight && cls.signon == SIGNONS)
1505 if (gl_delayfinish.integer)
1507 // tell driver to commit it's partially full geometry queue to the rendering queue
1508 // (this doesn't wait for the commands themselves to complete)
1515 R_TimeReport("finish");
1519 // utility functions
1521 void R_Mesh_CopyVertex3f(const float *vertex3f, int numverts)
1526 float *out = varray_vertex3f;
1529 *out++ = *vertex3f++;
1530 *out++ = *vertex3f++;
1531 *out++ = *vertex3f++;
1536 memcpy(varray_vertex3f, vertex3f, numverts * sizeof(float[3]));
1539 void R_Mesh_CopyTexCoord2f(int tmu, const float *texcoord2f, int numverts)
1544 float *out = varray_texcoord2f[tmu];
1547 *out++ = *texcoord2f++;
1548 *out++ = *texcoord2f++;
1553 memcpy(varray_texcoord2f[tmu], texcoord2f, numverts * sizeof(float[2]));
1556 void R_Mesh_CopyColor4f(const float *color4f, int numverts)
1561 float *out = varray_color4f;
1564 *out++ = *color4f++;
1565 *out++ = *color4f++;
1566 *out++ = *color4f++;
1567 *out++ = *color4f++;
1572 memcpy(varray_color4f, color4f, numverts * sizeof(float[4]));