3 #include "cl_collision.h"
5 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
6 cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0", "use glBegin(GL_TRIANGLES);glArrayElement();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
7 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)"};
8 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
9 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
11 cvar_t r_render = {0, "r_render", "1", "enables rendering calls (you want this on!)"};
12 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
13 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
14 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
15 cvar_t gl_lockarrays = {0, "gl_lockarrays", "1", "enables use of glLockArraysEXT, may cause glitches with some broken drivers"};
17 int gl_maxdrawrangeelementsvertices;
18 int gl_maxdrawrangeelementsindices;
23 void GL_PrintError(int errornumber, char *filename, int linenumber)
27 #ifdef GL_INVALID_ENUM
29 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
32 #ifdef GL_INVALID_VALUE
33 case GL_INVALID_VALUE:
34 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
37 #ifdef GL_INVALID_OPERATION
38 case GL_INVALID_OPERATION:
39 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
42 #ifdef GL_STACK_OVERFLOW
43 case GL_STACK_OVERFLOW:
44 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
47 #ifdef GL_STACK_UNDERFLOW
48 case GL_STACK_UNDERFLOW:
49 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
52 #ifdef GL_OUT_OF_MEMORY
53 case GL_OUT_OF_MEMORY:
54 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
57 #ifdef GL_TABLE_TOO_LARGE
58 case GL_TABLE_TOO_LARGE:
59 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
63 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
69 #define BACKENDACTIVECHECK if (!backendactive) Sys_Error("GL backend function called when backend is not active");
71 void SCR_ScreenShot_f (void);
73 static matrix4x4_t backend_viewmatrix;
74 static matrix4x4_t backend_modelmatrix;
75 static matrix4x4_t backend_modelviewmatrix;
76 static matrix4x4_t backend_glmodelviewmatrix;
77 static matrix4x4_t backend_projectmatrix;
79 static unsigned int backendunits, backendimageunits, backendarrayunits, backendactive;
82 note: here's strip order for a terrain row:
89 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
91 *elements++ = i + row;
93 *elements++ = i + row + 1;
96 *elements++ = i + row + 1;
99 for (y = 0;y < rows - 1;y++)
101 for (x = 0;x < columns - 1;x++)
104 *elements++ = i + columns;
106 *elements++ = i + columns + 1;
109 *elements++ = i + columns + 1;
120 for (y = 0;y < rows - 1;y++)
122 for (x = 0;x < columns - 1;x++)
126 *elements++ = i + columns;
127 *elements++ = i + columns + 1;
128 *elements++ = i + columns;
129 *elements++ = i + columns + 1;
135 int polygonelements[(POLYGONELEMENTS_MAXPOINTS-2)*3];
136 int quadelements[QUADELEMENTS_MAXQUADS*6];
139 static void R_Mesh_CacheArray_Startup(void);
140 static void R_Mesh_CacheArray_Shutdown(void);
142 void GL_Backend_AllocArrays(void)
145 R_Mesh_CacheArray_Startup();
149 void GL_Backend_FreeArrays(void)
152 R_Mesh_CacheArray_Shutdown();
156 static void gl_backend_start(void)
158 Con_Print("OpenGL Backend starting...\n");
161 if (qglDrawRangeElements != NULL)
164 qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices);
166 qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices);
168 Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices);
171 backendunits = min(MAX_TEXTUREUNITS, gl_textureunits);
172 backendimageunits = backendunits;
173 backendarrayunits = backendunits;
174 if (gl_support_fragment_shader)
177 qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, (int *)&backendimageunits);
179 qglGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, (int *)&backendarrayunits);
181 Con_Printf("GLSL shader support detected: texture units = %i texenv, %i image, %i array\n", backendunits, backendimageunits, backendarrayunits);
183 else if (backendunits > 1)
184 Con_Printf("multitexture detected: texture units = %i\n", backendunits);
186 Con_Printf("singletexture\n");
188 GL_Backend_AllocArrays();
190 Con_Printf("OpenGL backend started.\n");
194 backendactive = true;
197 static void gl_backend_shutdown(void)
200 backendimageunits = 0;
201 backendarrayunits = 0;
202 backendactive = false;
204 Con_Print("OpenGL Backend shutting down\n");
206 GL_Backend_FreeArrays();
209 static void gl_backend_newmap(void)
213 void gl_backend_init(void)
217 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
219 polygonelements[i * 3 + 0] = 0;
220 polygonelements[i * 3 + 1] = i + 1;
221 polygonelements[i * 3 + 2] = i + 2;
223 // elements for rendering a series of quads as triangles
224 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
226 quadelements[i * 6 + 0] = i * 4;
227 quadelements[i * 6 + 1] = i * 4 + 1;
228 quadelements[i * 6 + 2] = i * 4 + 2;
229 quadelements[i * 6 + 3] = i * 4;
230 quadelements[i * 6 + 4] = i * 4 + 2;
231 quadelements[i * 6 + 5] = i * 4 + 3;
234 Cvar_RegisterVariable(&r_render);
235 Cvar_RegisterVariable(&r_waterwarp);
236 Cvar_RegisterVariable(&gl_polyblend);
237 Cvar_RegisterVariable(&gl_dither);
238 Cvar_RegisterVariable(&gl_lockarrays);
239 Cvar_RegisterVariable(&gl_paranoid);
240 Cvar_RegisterVariable(&gl_printcheckerror);
242 Cvar_SetValue("r_render", 0);
245 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
246 Cvar_RegisterVariable(&gl_mesh_testarrayelement);
247 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
249 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
252 void GL_SetupView_Orientation_Identity (void)
254 backend_viewmatrix = identitymatrix;
255 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
258 void GL_SetupView_Orientation_FromEntity(matrix4x4_t *matrix)
260 matrix4x4_t tempmatrix, basematrix;
261 Matrix4x4_Invert_Simple(&tempmatrix, matrix);
262 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
263 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
264 Matrix4x4_Concat(&backend_viewmatrix, &basematrix, &tempmatrix);
265 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[2], 1, 0, 0);
266 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[0], 0, 1, 0);
267 //Matrix4x4_ConcatRotate(&backend_viewmatrix, -angles[1], 0, 0, 1);
268 //Matrix4x4_ConcatTranslate(&backend_viewmatrix, -origin[0], -origin[1], -origin[2]);
269 memset(&backend_modelmatrix, 0, sizeof(backend_modelmatrix));
272 void GL_SetupView_Mode_Perspective (double frustumx, double frustumy, double zNear, double zFar)
276 if (!r_render.integer)
280 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
281 qglLoadIdentity();CHECKGLERROR
283 qglFrustum(-frustumx * zNear, frustumx * zNear, -frustumy * zNear, frustumy * zNear, zNear, zFar);CHECKGLERROR
284 qglGetDoublev(GL_PROJECTION_MATRIX, m);
285 backend_projectmatrix.m[0][0] = m[0];
286 backend_projectmatrix.m[1][0] = m[1];
287 backend_projectmatrix.m[2][0] = m[2];
288 backend_projectmatrix.m[3][0] = m[3];
289 backend_projectmatrix.m[0][1] = m[4];
290 backend_projectmatrix.m[1][1] = m[5];
291 backend_projectmatrix.m[2][1] = m[6];
292 backend_projectmatrix.m[3][1] = m[7];
293 backend_projectmatrix.m[0][2] = m[8];
294 backend_projectmatrix.m[1][2] = m[9];
295 backend_projectmatrix.m[2][2] = m[10];
296 backend_projectmatrix.m[3][2] = m[11];
297 backend_projectmatrix.m[0][3] = m[12];
298 backend_projectmatrix.m[1][3] = m[13];
299 backend_projectmatrix.m[2][3] = m[14];
300 backend_projectmatrix.m[3][3] = m[15];
301 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
302 GL_SetupView_Orientation_Identity();
305 void GL_SetupView_Mode_PerspectiveInfiniteFarClip (double frustumx, double frustumy, double zNear)
309 if (!r_render.integer)
313 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
314 qglLoadIdentity();CHECKGLERROR
316 nudge = 1.0 - 1.0 / (1<<23);
317 m[ 0] = 1.0 / frustumx;
322 m[ 5] = 1.0 / frustumy;
331 m[14] = -2 * zNear * nudge;
334 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
335 GL_SetupView_Orientation_Identity();
336 backend_projectmatrix.m[0][0] = m[0];
337 backend_projectmatrix.m[1][0] = m[1];
338 backend_projectmatrix.m[2][0] = m[2];
339 backend_projectmatrix.m[3][0] = m[3];
340 backend_projectmatrix.m[0][1] = m[4];
341 backend_projectmatrix.m[1][1] = m[5];
342 backend_projectmatrix.m[2][1] = m[6];
343 backend_projectmatrix.m[3][1] = m[7];
344 backend_projectmatrix.m[0][2] = m[8];
345 backend_projectmatrix.m[1][2] = m[9];
346 backend_projectmatrix.m[2][2] = m[10];
347 backend_projectmatrix.m[3][2] = m[11];
348 backend_projectmatrix.m[0][3] = m[12];
349 backend_projectmatrix.m[1][3] = m[13];
350 backend_projectmatrix.m[2][3] = m[14];
351 backend_projectmatrix.m[3][3] = m[15];
354 void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar)
358 if (!r_render.integer)
362 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
363 qglLoadIdentity();CHECKGLERROR
364 qglOrtho(x1, x2, y2, y1, zNear, zFar);
365 qglGetDoublev(GL_PROJECTION_MATRIX, m);
366 backend_projectmatrix.m[0][0] = m[0];
367 backend_projectmatrix.m[1][0] = m[1];
368 backend_projectmatrix.m[2][0] = m[2];
369 backend_projectmatrix.m[3][0] = m[3];
370 backend_projectmatrix.m[0][1] = m[4];
371 backend_projectmatrix.m[1][1] = m[5];
372 backend_projectmatrix.m[2][1] = m[6];
373 backend_projectmatrix.m[3][1] = m[7];
374 backend_projectmatrix.m[0][2] = m[8];
375 backend_projectmatrix.m[1][2] = m[9];
376 backend_projectmatrix.m[2][2] = m[10];
377 backend_projectmatrix.m[3][2] = m[11];
378 backend_projectmatrix.m[0][3] = m[12];
379 backend_projectmatrix.m[1][3] = m[13];
380 backend_projectmatrix.m[2][3] = m[14];
381 backend_projectmatrix.m[3][3] = m[15];
382 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
383 GL_SetupView_Orientation_Identity();
386 typedef struct gltextureunit_s
388 int t1d, t2d, t3d, tcubemap;
390 unsigned int arraycomponents;
391 const void *pointer_texcoord;
392 float rgbscale, alphascale;
393 int combinergb, combinealpha;
394 // FIXME: add more combine stuff
395 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
396 int texmatrixenabled;
401 static struct gl_state_s
407 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
411 unsigned int clientunit;
412 gltextureunit_t units[MAX_TEXTUREUNITS];
416 const void *pointer_vertex;
417 const void *pointer_color;
421 void GL_SetupTextureState(void)
424 gltextureunit_t *unit;
426 gl_state.unit = MAX_TEXTUREUNITS;
427 gl_state.clientunit = MAX_TEXTUREUNITS;
428 for (i = 0;i < MAX_TEXTUREUNITS;i++)
430 unit = gl_state.units + i;
435 unit->arrayenabled = false;
436 unit->arraycomponents = 0;
437 unit->pointer_texcoord = NULL;
439 unit->alphascale = 1;
440 unit->combinergb = GL_MODULATE;
441 unit->combinealpha = GL_MODULATE;
442 unit->texmatrixenabled = false;
443 unit->matrix = identitymatrix;
446 for (i = 0;i < backendimageunits;i++)
449 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
450 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
453 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
455 if (gl_texturecubemap)
457 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
461 for (i = 0;i < backendarrayunits;i++)
463 GL_ClientActiveTexture(i);
464 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
465 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
468 for (i = 0;i < backendunits;i++)
471 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
472 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
475 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
477 if (gl_texturecubemap)
479 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
481 qglMatrixMode(GL_TEXTURE);
483 qglMatrixMode(GL_MODELVIEW);
484 if (gl_combine.integer)
486 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
487 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);CHECKGLERROR
488 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);CHECKGLERROR
489 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
490 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
491 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
492 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);CHECKGLERROR
493 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);CHECKGLERROR
494 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);CHECKGLERROR
495 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);CHECKGLERROR
496 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);CHECKGLERROR
497 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT_ARB);CHECKGLERROR
498 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
499 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
500 qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);CHECKGLERROR
501 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
502 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
506 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
512 void GL_Backend_ResetState(void)
514 memset(&gl_state, 0, sizeof(gl_state));
515 gl_state.depthtest = true;
516 gl_state.blendfunc1 = GL_ONE;
517 gl_state.blendfunc2 = GL_ZERO;
518 gl_state.blend = false;
519 gl_state.depthmask = GL_TRUE;
520 gl_state.colormask = 15;
521 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
522 gl_state.lockrange_first = 0;
523 gl_state.lockrange_count = 0;
524 gl_state.pointer_vertex = NULL;
525 gl_state.pointer_color = NULL;
529 qglColorMask(1, 1, 1, 1);
530 qglEnable(GL_CULL_FACE);CHECKGLERROR
531 qglCullFace(GL_FRONT);CHECKGLERROR
532 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
533 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
534 qglDisable(GL_BLEND);CHECKGLERROR
535 qglDepthMask(gl_state.depthmask);CHECKGLERROR
537 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
538 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
540 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
541 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
543 GL_Color(0, 0, 0, 0);
544 GL_Color(1, 1, 1, 1);
546 GL_SetupTextureState();
549 void GL_ActiveTexture(unsigned int num)
551 if (gl_state.unit != num)
554 if (qglActiveTexture)
556 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
562 void GL_ClientActiveTexture(unsigned int num)
564 if (gl_state.clientunit != num)
566 gl_state.clientunit = num;
567 if (qglActiveTexture)
569 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
575 void GL_BlendFunc(int blendfunc1, int blendfunc2)
577 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
581 qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR
582 if (gl_state.blendfunc2 == GL_ZERO)
584 if (gl_state.blendfunc1 == GL_ONE)
589 qglDisable(GL_BLEND);CHECKGLERROR
597 qglEnable(GL_BLEND);CHECKGLERROR
606 qglEnable(GL_BLEND);CHECKGLERROR
612 void GL_DepthMask(int state)
614 if (gl_state.depthmask != state)
618 qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
622 void GL_DepthTest(int state)
624 if (gl_state.depthtest != state)
626 if (r_showtrispass && r_showdisabledepthtest.integer)
628 gl_state.depthtest = state;
629 if (gl_state.depthtest)
631 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
635 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
640 void GL_ColorMask(int r, int g, int b, int a)
642 int state = r*8 + g*4 + b*2 + a*1;
643 if (gl_state.colormask != state)
645 gl_state.colormask = state;
646 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
650 void GL_Color(float cr, float cg, float cb, float ca)
652 if (gl_state.pointer_color || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
656 gl_state.color4f[0] = cr;
657 gl_state.color4f[1] = cg;
658 gl_state.color4f[2] = cb;
659 gl_state.color4f[3] = ca;
661 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
666 void GL_ShowTrisColor(float cr, float cg, float cb, float ca)
671 GL_Color(cr * r_showtris.value, cg * r_showtris.value, cb * r_showtris.value, ca);
676 void GL_LockArrays(int first, int count)
678 if (gl_state.lockrange_count != count || gl_state.lockrange_first != first)
680 if (gl_state.lockrange_count)
682 gl_state.lockrange_count = 0;
684 qglUnlockArraysEXT();
687 if (count && gl_supportslockarrays && gl_lockarrays.integer && r_render.integer)
689 gl_state.lockrange_first = first;
690 gl_state.lockrange_count = count;
692 qglLockArraysEXT(first, count);
698 void GL_Scissor (int x, int y, int width, int height)
701 qglScissor(x, vid.height - (y + height),width,height);
705 void GL_ScissorTest(int state)
707 if(gl_state.scissortest == state)
711 if((gl_state.scissortest = state))
712 qglEnable(GL_SCISSOR_TEST);
714 qglDisable(GL_SCISSOR_TEST);
718 void GL_Clear(int mask)
720 // in showtris rendering, don't clear the color buffer as that would hide
721 // the accumulated lines
723 mask &= ~GL_COLOR_BUFFER_BIT;
724 qglClear(mask);CHECKGLERROR
727 void GL_TransformToScreen(const vec4_t in, vec4_t out)
731 Matrix4x4_Transform4 (&backend_viewmatrix, in, temp);
732 Matrix4x4_Transform4 (&backend_projectmatrix, temp, out);
734 out[0] = r_view_x + (out[0] * iw + 1.0f) * r_view_width * 0.5f;
735 out[1] = r_view_y + (out[1] * iw + 1.0f) * r_view_height * 0.5f;
736 out[2] = r_view_z + (out[2] * iw + 1.0f) * r_view_depth * 0.5f;
739 // called at beginning of frame
740 void R_Mesh_Start(void)
744 GL_Backend_ResetState();
747 unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
749 GLint vertexshadercompiled, fragmentshadercompiled, programlinked;
750 GLuint vertexshaderobject, fragmentshaderobject, programobject = 0;
751 char compilelog[MAX_INPUTLINE];
754 programobject = qglCreateProgramObjectARB();
759 if (vertexstrings_count)
762 vertexshaderobject = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
763 if (!vertexshaderobject)
765 qglDeleteObjectARB(programobject);
769 qglShaderSourceARB(vertexshaderobject, vertexstrings_count, vertexstrings_list, NULL);
770 qglCompileShaderARB(vertexshaderobject);
772 qglGetObjectParameterivARB(vertexshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &vertexshadercompiled);
773 qglGetInfoLogARB(vertexshaderobject, sizeof(compilelog), NULL, compilelog);
775 Con_DPrintf("vertex shader compile log:\n%s\n", compilelog);
776 if (!vertexshadercompiled)
778 qglDeleteObjectARB(programobject);
779 qglDeleteObjectARB(vertexshaderobject);
783 qglAttachObjectARB(programobject, vertexshaderobject);
784 qglDeleteObjectARB(vertexshaderobject);
788 if (fragmentstrings_count)
791 fragmentshaderobject = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
792 if (!fragmentshaderobject)
794 qglDeleteObjectARB(programobject);
798 qglShaderSourceARB(fragmentshaderobject, fragmentstrings_count, fragmentstrings_list, NULL);
799 qglCompileShaderARB(fragmentshaderobject);
801 qglGetObjectParameterivARB(fragmentshaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &fragmentshadercompiled);
802 qglGetInfoLogARB(fragmentshaderobject, sizeof(compilelog), NULL, compilelog);
804 Con_DPrintf("fragment shader compile log:\n%s\n", compilelog);
805 if (!fragmentshadercompiled)
807 qglDeleteObjectARB(programobject);
808 qglDeleteObjectARB(fragmentshaderobject);
812 qglAttachObjectARB(programobject, fragmentshaderobject);
813 qglDeleteObjectARB(fragmentshaderobject);
817 qglLinkProgramARB(programobject);
819 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);
820 qglGetInfoLogARB(programobject, sizeof(compilelog), NULL, compilelog);
823 Con_DPrintf("program link log:\n%s\n", compilelog);
824 // software vertex shader is ok but software fragment shader is WAY
825 // too slow, fail program if so.
826 // NOTE: this string might be ATI specific, but that's ok because the
827 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
828 // software fragment shader due to low instruction and dependent
830 if (strstr(compilelog, "fragment shader will run in software"))
831 programlinked = false;
836 qglDeleteObjectARB(programobject);
840 return programobject;
843 void GL_Backend_FreeProgram(unsigned int prog)
846 qglDeleteObjectARB(prog);
850 int gl_backend_rebindtextures;
852 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
857 for (i = 0;i < count;i++)
858 *out++ = *in++ + offset;
861 memcpy(out, in, sizeof(*out) * count);
864 // renders triangles using vertices from the active arrays
865 int paranoidblah = 0;
866 void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements)
868 unsigned int numelements = numtriangles * 3;
869 if (numvertices < 3 || numtriangles < 1)
871 Con_Printf("R_Mesh_Draw(%d, %d, %d, %08p);\n", firstvertex, numvertices, numtriangles, elements);
877 R_Mesh_Draw_ShowTris(firstvertex, numvertices, numtriangles, elements);
880 renderstats.meshes++;
881 renderstats.meshes_elements += numelements;
882 if (gl_paranoid.integer)
884 unsigned int i, j, size;
886 if (!qglIsEnabled(GL_VERTEX_ARRAY))
887 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
888 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
890 if (gl_state.pointer_color)
892 if (!qglIsEnabled(GL_COLOR_ARRAY))
893 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
894 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
897 for (i = 0;i < backendarrayunits;i++)
899 if (gl_state.units[i].arrayenabled)
901 GL_ClientActiveTexture(i);
902 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
903 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
904 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++)
908 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
910 if (elements[i] < firstvertex || elements[i] >= firstvertex + numvertices)
912 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in elements list\n", elements[i], firstvertex, firstvertex + numvertices);
918 if (r_render.integer)
921 if (gl_mesh_testmanualfeeding.integer)
925 qglBegin(GL_TRIANGLES);
926 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
928 for (j = 0;j < backendarrayunits;j++)
930 if (gl_state.units[j].pointer_texcoord)
932 if (backendarrayunits > 1)
934 if (gl_state.units[j].arraycomponents == 4)
936 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
937 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
939 else if (gl_state.units[j].arraycomponents == 3)
941 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
942 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
944 else if (gl_state.units[j].arraycomponents == 2)
946 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
947 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
951 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
952 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
957 if (gl_state.units[j].arraycomponents == 4)
959 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
960 qglTexCoord4f(p[0], p[1], p[2], p[3]);
962 else if (gl_state.units[j].arraycomponents == 3)
964 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
965 qglTexCoord3f(p[0], p[1], p[2]);
967 else if (gl_state.units[j].arraycomponents == 2)
969 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
970 qglTexCoord2f(p[0], p[1]);
974 p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
980 if (gl_state.pointer_color)
982 p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4;
983 qglColor4f(p[0], p[1], p[2], p[3]);
985 p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3;
986 qglVertex3f(p[0], p[1], p[2]);
991 else if (gl_mesh_testarrayelement.integer)
994 qglBegin(GL_TRIANGLES);
995 for (i = 0;i < numtriangles * 3;i++)
997 qglArrayElement(elements[i]);
1002 else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
1004 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, elements);
1009 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, elements);
1015 // restores backend state, used when done with 3D rendering
1016 void R_Mesh_Finish(void)
1021 GL_LockArrays(0, 0);
1024 for (i = 0;i < backendimageunits;i++)
1026 GL_ActiveTexture(i);
1027 qglBindTexture(GL_TEXTURE_1D, 0);CHECKGLERROR
1028 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1031 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1033 if (gl_texturecubemap)
1035 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1038 for (i = 0;i < backendarrayunits;i++)
1040 GL_ActiveTexture(backendarrayunits - 1 - i);
1041 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1043 for (i = 0;i < backendunits;i++)
1045 GL_ActiveTexture(backendunits - 1 - i);
1046 qglDisable(GL_TEXTURE_1D);CHECKGLERROR
1047 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1050 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1052 if (gl_texturecubemap)
1054 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1056 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1057 if (gl_combine.integer)
1059 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);CHECKGLERROR
1060 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);CHECKGLERROR
1063 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1064 qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1066 qglDisable(GL_BLEND);CHECKGLERROR
1067 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1068 qglDepthMask(GL_TRUE);CHECKGLERROR
1069 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
1072 void R_Mesh_Matrix(const matrix4x4_t *matrix)
1074 if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
1076 backend_modelmatrix = *matrix;
1077 Matrix4x4_Concat(&backend_modelviewmatrix, &backend_viewmatrix, matrix);
1078 Matrix4x4_Transpose(&backend_glmodelviewmatrix, &backend_modelviewmatrix);
1079 qglLoadMatrixf(&backend_glmodelviewmatrix.m[0][0]);
1083 void R_Mesh_VertexPointer(const float *vertex3f)
1085 if (gl_state.pointer_vertex != vertex3f)
1087 gl_state.pointer_vertex = vertex3f;
1089 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), gl_state.pointer_vertex);
1094 void R_Mesh_ColorPointer(const float *color4f)
1098 if (gl_state.pointer_color != color4f)
1101 if (!gl_state.pointer_color)
1103 qglEnableClientState(GL_COLOR_ARRAY);
1108 qglDisableClientState(GL_COLOR_ARRAY);
1110 // when color array is on the glColor gets trashed, set it again
1111 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
1114 gl_state.pointer_color = color4f;
1115 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), gl_state.pointer_color);
1120 void R_Mesh_TexCoordPointer(unsigned int unitnum, unsigned int numcomponents, const float *texcoord)
1122 gltextureunit_t *unit = gl_state.units + unitnum;
1125 // update array settings
1129 if (unit->pointer_texcoord != texcoord || unit->arraycomponents != numcomponents)
1131 unit->pointer_texcoord = texcoord;
1132 unit->arraycomponents = numcomponents;
1133 GL_ClientActiveTexture(unitnum);
1134 qglTexCoordPointer(unit->arraycomponents, GL_FLOAT, sizeof(float) * unit->arraycomponents, unit->pointer_texcoord);
1137 // texture array unit is enabled, enable the array
1138 if (!unit->arrayenabled)
1140 unit->arrayenabled = true;
1141 GL_ClientActiveTexture(unitnum);
1142 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1147 // texture array unit is disabled, disable the array
1148 if (unit->arrayenabled)
1150 unit->arrayenabled = false;
1151 GL_ClientActiveTexture(unitnum);
1152 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1157 void R_Mesh_TexBindAll(unsigned int unitnum, int tex1d, int tex2d, int tex3d, int texcubemap)
1159 gltextureunit_t *unit = gl_state.units + unitnum;
1160 if (unitnum >= backendimageunits)
1164 // update 1d texture binding
1165 if (unit->t1d != tex1d)
1167 GL_ActiveTexture(unitnum);
1168 if (unitnum < backendunits)
1173 qglEnable(GL_TEXTURE_1D);
1178 qglDisable(GL_TEXTURE_1D);
1182 qglBindTexture(GL_TEXTURE_1D, unit->t1d);
1185 // update 2d texture binding
1186 if (unit->t2d != tex2d)
1188 GL_ActiveTexture(unitnum);
1189 if (unitnum < backendunits)
1194 qglEnable(GL_TEXTURE_2D);
1199 qglDisable(GL_TEXTURE_2D);
1203 qglBindTexture(GL_TEXTURE_2D, unit->t2d);
1206 // update 3d texture binding
1207 if (unit->t3d != tex3d)
1209 GL_ActiveTexture(unitnum);
1210 if (unitnum < backendunits)
1215 qglEnable(GL_TEXTURE_3D);
1220 qglDisable(GL_TEXTURE_3D);
1224 qglBindTexture(GL_TEXTURE_3D, unit->t3d);
1227 // update cubemap texture binding
1228 if (unit->tcubemap != texcubemap)
1230 GL_ActiveTexture(unitnum);
1231 if (unitnum < backendunits)
1235 if (unit->tcubemap == 0)
1236 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);
1241 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);
1244 unit->tcubemap = texcubemap;
1245 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);
1250 void R_Mesh_TexBind1D(unsigned int unitnum, int texnum)
1252 gltextureunit_t *unit = gl_state.units + unitnum;
1253 if (unitnum >= backendimageunits)
1257 // update 1d texture binding
1258 if (unit->t1d != texnum)
1260 GL_ActiveTexture(unitnum);
1261 if (unitnum < backendunits)
1266 qglEnable(GL_TEXTURE_1D);
1271 qglDisable(GL_TEXTURE_1D);
1275 qglBindTexture(GL_TEXTURE_1D, unit->t1d);
1278 // update 2d texture binding
1281 GL_ActiveTexture(unitnum);
1282 if (unitnum < backendunits)
1285 qglDisable(GL_TEXTURE_2D);
1288 qglBindTexture(GL_TEXTURE_2D, unit->t2d);
1291 // update 3d texture binding
1294 GL_ActiveTexture(unitnum);
1295 if (unitnum < backendunits)
1298 qglDisable(GL_TEXTURE_3D);
1301 qglBindTexture(GL_TEXTURE_3D, unit->t3d);
1304 // update cubemap texture binding
1307 GL_ActiveTexture(unitnum);
1308 if (unitnum < backendunits)
1311 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);
1314 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);
1319 void R_Mesh_TexBind(unsigned int unitnum, int texnum)
1321 gltextureunit_t *unit = gl_state.units + unitnum;
1322 if (unitnum >= backendimageunits)
1326 // update 1d texture binding
1329 GL_ActiveTexture(unitnum);
1330 if (unitnum < backendunits)
1333 qglDisable(GL_TEXTURE_1D);
1336 qglBindTexture(GL_TEXTURE_1D, unit->t1d);
1339 // update 2d texture binding
1340 if (unit->t2d != texnum)
1342 GL_ActiveTexture(unitnum);
1343 if (unitnum < backendunits)
1348 qglEnable(GL_TEXTURE_2D);
1353 qglDisable(GL_TEXTURE_2D);
1357 qglBindTexture(GL_TEXTURE_2D, unit->t2d);
1360 // update 3d texture binding
1363 GL_ActiveTexture(unitnum);
1364 if (unitnum < backendunits)
1367 qglDisable(GL_TEXTURE_3D);
1370 qglBindTexture(GL_TEXTURE_3D, unit->t3d);
1373 // update cubemap texture binding
1374 if (unit->tcubemap != 0)
1376 GL_ActiveTexture(unitnum);
1377 if (unitnum < backendunits)
1380 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);
1383 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);
1388 void R_Mesh_TexBind3D(unsigned int unitnum, int texnum)
1390 gltextureunit_t *unit = gl_state.units + unitnum;
1391 if (unitnum >= backendimageunits)
1395 // update 1d texture binding
1398 GL_ActiveTexture(unitnum);
1399 if (unitnum < backendunits)
1402 qglDisable(GL_TEXTURE_1D);
1405 qglBindTexture(GL_TEXTURE_1D, unit->t1d);
1408 // update 2d texture binding
1411 GL_ActiveTexture(unitnum);
1412 if (unitnum < backendunits)
1415 qglDisable(GL_TEXTURE_2D);
1418 qglBindTexture(GL_TEXTURE_2D, unit->t2d);
1421 // update 3d texture binding
1422 if (unit->t3d != texnum)
1424 GL_ActiveTexture(unitnum);
1425 if (unitnum < backendunits)
1430 qglEnable(GL_TEXTURE_3D);
1435 qglDisable(GL_TEXTURE_3D);
1439 qglBindTexture(GL_TEXTURE_3D, unit->t3d);
1442 // update cubemap texture binding
1443 if (unit->tcubemap != 0)
1445 GL_ActiveTexture(unitnum);
1446 if (unitnum < backendunits)
1449 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);
1452 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);
1457 void R_Mesh_TexBindCubeMap(unsigned int unitnum, int texnum)
1459 gltextureunit_t *unit = gl_state.units + unitnum;
1460 if (unitnum >= backendimageunits)
1464 // update 1d texture binding
1467 GL_ActiveTexture(unitnum);
1468 if (unitnum < backendunits)
1471 qglDisable(GL_TEXTURE_1D);
1474 qglBindTexture(GL_TEXTURE_1D, unit->t1d);
1477 // update 2d texture binding
1480 GL_ActiveTexture(unitnum);
1481 if (unitnum < backendunits)
1484 qglDisable(GL_TEXTURE_2D);
1487 qglBindTexture(GL_TEXTURE_2D, unit->t2d);
1490 // update 3d texture binding
1493 GL_ActiveTexture(unitnum);
1494 if (unitnum < backendunits)
1497 qglDisable(GL_TEXTURE_3D);
1500 qglBindTexture(GL_TEXTURE_3D, unit->t3d);
1503 // update cubemap texture binding
1504 if (unit->tcubemap != texnum)
1506 GL_ActiveTexture(unitnum);
1507 if (unitnum < backendunits)
1511 if (unit->tcubemap == 0)
1512 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);
1517 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);
1520 unit->tcubemap = texnum;
1521 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);
1526 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
1528 gltextureunit_t *unit = gl_state.units + unitnum;
1531 if (matrix->m[3][3])
1533 // texmatrix specified, check if it is different
1534 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
1536 matrix4x4_t tempmatrix;
1537 unit->texmatrixenabled = true;
1538 unit->matrix = *matrix;
1539 Matrix4x4_Transpose(&tempmatrix, &unit->matrix);
1540 qglMatrixMode(GL_TEXTURE);
1541 GL_ActiveTexture(unitnum);
1542 qglLoadMatrixf(&tempmatrix.m[0][0]);
1543 qglMatrixMode(GL_MODELVIEW);
1548 // no texmatrix specified, revert to identity
1549 if (unit->texmatrixenabled)
1551 unit->texmatrixenabled = false;
1552 qglMatrixMode(GL_TEXTURE);
1553 GL_ActiveTexture(unitnum);
1555 qglMatrixMode(GL_MODELVIEW);
1560 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
1562 gltextureunit_t *unit = gl_state.units + unitnum;
1565 if (gl_combine.integer)
1567 // GL_ARB_texture_env_combine
1569 combinergb = GL_MODULATE;
1571 combinealpha = GL_MODULATE;
1576 if (unit->combinergb != combinergb)
1578 unit->combinergb = combinergb;
1579 GL_ActiveTexture(unitnum);
1580 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1582 if (unit->combinealpha != combinealpha)
1584 unit->combinealpha = combinealpha;
1585 GL_ActiveTexture(unitnum);
1586 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1588 if (unit->rgbscale != rgbscale)
1590 GL_ActiveTexture(unitnum);
1591 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (unit->rgbscale = rgbscale));CHECKGLERROR
1593 if (unit->alphascale != alphascale)
1595 GL_ActiveTexture(unitnum);
1596 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, (unit->alphascale = alphascale));CHECKGLERROR
1603 combinergb = GL_MODULATE;
1604 if (unit->combinergb != combinergb)
1606 unit->combinergb = combinergb;
1607 GL_ActiveTexture(unitnum);
1608 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combinergb);CHECKGLERROR
1613 void R_Mesh_State(const rmeshstate_t *m)
1619 R_Mesh_VertexPointer(m->pointer_vertex);
1620 R_Mesh_ColorPointer(m->pointer_color);
1622 if (gl_backend_rebindtextures)
1624 gl_backend_rebindtextures = false;
1625 GL_SetupTextureState();
1628 for (i = 0;i < backendimageunits;i++)
1629 R_Mesh_TexBindAll(i, m->tex1d[i], m->tex[i], m->tex3d[i], m->texcubemap[i]);
1630 for (i = 0;i < backendarrayunits;i++)
1632 if (m->pointer_texcoord3f[i])
1633 R_Mesh_TexCoordPointer(i, 3, m->pointer_texcoord3f[i]);
1635 R_Mesh_TexCoordPointer(i, 2, m->pointer_texcoord[i]);
1637 for (i = 0;i < backendunits;i++)
1639 R_Mesh_TexMatrix(i, &m->texmatrix[i]);
1640 R_Mesh_TexCombine(i, m->texcombinergb[i], m->texcombinealpha[i], m->texrgbscale[i], m->texalphascale[i]);
1644 void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
1647 for (;numtriangles;numtriangles--, elements += 3)
1649 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
1650 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
1651 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
1657 //===========================================================================
1658 // dynamic vertex array buffer subsystem
1659 //===========================================================================
1661 // FIXME: someday this should be dynamically allocated and resized?
1662 float varray_vertex3f[65536*3];
1663 float varray_svector3f[65536*3];
1664 float varray_tvector3f[65536*3];
1665 float varray_normal3f[65536*3];
1666 float varray_color4f[65536*4];
1667 float varray_texcoord2f[4][65536*2];
1668 float varray_texcoord3f[4][65536*3];
1669 int earray_element3i[65536];
1670 float varray_vertex3f2[65536*3];
1673 //===========================================================================
1674 // vertex array caching subsystem
1675 //===========================================================================
1677 typedef struct rcachearraylink_s
1679 struct rcachearraylink_s *next, *prev;
1680 struct rcachearrayitem_s *data;
1684 typedef struct rcachearrayitem_s
1686 // the original request structure
1687 rcachearrayrequest_t request;
1690 // offset into r_mesh_rcachedata
1692 // for linking this into the sequential list
1693 rcachearraylink_t sequentiallink;
1694 // for linking this into the lookup list
1695 rcachearraylink_t hashlink;
1699 #define RCACHEARRAY_HASHSIZE 65536
1700 #define RCACHEARRAY_ITEMS 4096
1701 #define RCACHEARRAY_DEFAULTSIZE (4 << 20)
1703 // all active items are linked into this chain in sorted order
1704 static rcachearraylink_t r_mesh_rcachesequentialchain;
1705 // all inactive items are linked into this chain in unknown order
1706 static rcachearraylink_t r_mesh_rcachefreechain;
1707 // all active items are also linked into these chains (using their hashlink)
1708 static rcachearraylink_t r_mesh_rcachechain[RCACHEARRAY_HASHSIZE];
1710 // all items are stored here, whether active or inactive
1711 static rcachearrayitem_t r_mesh_rcacheitems[RCACHEARRAY_ITEMS];
1713 // size of data buffer
1714 static int r_mesh_rcachedata_size = RCACHEARRAY_DEFAULTSIZE;
1716 static unsigned char r_mesh_rcachedata[RCACHEARRAY_DEFAULTSIZE];
1719 static int r_mesh_rcachedata_offset;
1720 static rcachearraylink_t *r_mesh_rcachesequentialchain_current;
1722 static void R_Mesh_CacheArray_Startup(void)
1725 rcachearraylink_t *l;
1726 // prepare all the linked lists
1727 l = &r_mesh_rcachesequentialchain;l->next = l->prev = l;l->data = NULL;
1728 l = &r_mesh_rcachefreechain;l->next = l->prev = l;l->data = NULL;
1729 memset(&r_mesh_rcachechain, 0, sizeof(r_mesh_rcachechain));
1730 for (i = 0;i < RCACHEARRAY_HASHSIZE;i++)
1732 l = &r_mesh_rcachechain[i];
1733 l->next = l->prev = l;
1736 memset(&r_mesh_rcacheitems, 0, sizeof(r_mesh_rcacheitems));
1737 for (i = 0;i < RCACHEARRAY_ITEMS;i++)
1739 r_mesh_rcacheitems[i].hashlink.data = r_mesh_rcacheitems[i].sequentiallink.data = &r_mesh_rcacheitems[i];
1740 l = &r_mesh_rcacheitems[i].sequentiallink;
1741 l->next = &r_mesh_rcachefreechain;
1742 l->prev = l->next->prev;
1743 l->next->prev = l->prev->next = l;
1745 // clear other state
1746 r_mesh_rcachedata_offset = 0;
1747 r_mesh_rcachesequentialchain_current = &r_mesh_rcachesequentialchain;
1750 static void R_Mesh_CacheArray_Shutdown(void)
1755 static void R_Mesh_CacheArray_ValidateState(int num)
1757 rcachearraylink_t *l, *lhead;
1758 lhead = &r_mesh_rcachesequentialchain;
1759 if (r_mesh_rcachesequentialchain_current == lhead)
1761 for (l = lhead->next;l != lhead;l = l->next)
1762 if (r_mesh_rcachesequentialchain_current == l)
1764 Sys_Error("%i", num);
1768 int R_Mesh_CacheArray(rcachearrayrequest_t *r)
1770 rcachearraylink_t *l, *lhead, *lnext;
1771 rcachearrayitem_t *d;
1772 int hashindex, offset, offsetend;
1774 //R_Mesh_CacheArray_ValidateState(3);
1775 // calculate a hashindex to choose a cache chain
1777 hashindex = CRC_Block((unsigned char *)r, sizeof(*r)) % RCACHEARRAY_HASHSIZE;
1779 // is it already cached?
1780 for (lhead = &r_mesh_rcachechain[hashindex], l = lhead->next;l != lhead;l = l->next)
1782 if (!memcmp(&l->data->request, r, sizeof(l->data->request)))
1784 // we have it cached already
1785 r->data = r_mesh_rcachedata + l->data->offset;
1790 // we need to add a new cache item, this means finding a place for the new
1791 // data and making sure we have a free item available, lots of work...
1793 // check if buffer needs to wrap
1794 if (r_mesh_rcachedata_offset + r->data_size > r_mesh_rcachedata_size)
1797 if (r->data_size * 10 > r_mesh_rcachedata_size)
1799 // realloc whole cache
1802 // reset back to start
1803 r_mesh_rcachedata_offset = 0;
1804 r_mesh_rcachesequentialchain_current = &r_mesh_rcachesequentialchain;
1806 offset = r_mesh_rcachedata_offset;
1807 r_mesh_rcachedata_offset += r->data_size;
1808 offsetend = r_mesh_rcachedata_offset;
1809 //R_Mesh_CacheArray_ValidateState(4);
1814 for (lhead = &r_mesh_rcachesequentialchain, l = lhead->next, n = 0;l != lhead;l = l->next, n++);
1815 Con_Printf("R_Mesh_CacheArray: new data range %i:%i, %i items are already linked\n", offset, offsetend, n);
1819 // make room for the new data (remove old items)
1820 lhead = &r_mesh_rcachesequentialchain;
1821 l = r_mesh_rcachesequentialchain_current;
1824 while (l != lhead && l->data->offset < offsetend && l->data->offset + l->data->request.data_size > offset)
1826 //r_mesh_rcachesequentialchain_current = l;
1827 //R_Mesh_CacheArray_ValidateState(8);
1829 // if at the end of the chain, wrap around
1831 lnext = lnext->next;
1832 //r_mesh_rcachesequentialchain_current = lnext;
1833 //R_Mesh_CacheArray_ValidateState(10);
1835 // unlink from sequential chain
1836 l->next->prev = l->prev;
1837 l->prev->next = l->next;
1838 //R_Mesh_CacheArray_ValidateState(11);
1839 // link into free chain
1840 l->next = &r_mesh_rcachefreechain;
1841 l->prev = l->next->prev;
1842 l->next->prev = l->prev->next = l;
1843 //R_Mesh_CacheArray_ValidateState(12);
1845 l = &l->data->hashlink;
1846 // unlink from hash chain
1847 l->next->prev = l->prev;
1848 l->prev->next = l->next;
1851 //r_mesh_rcachesequentialchain_current = l;
1852 //R_Mesh_CacheArray_ValidateState(9);
1854 //r_mesh_rcachesequentialchain_current = l;
1855 //R_Mesh_CacheArray_ValidateState(5);
1856 // gobble an extra item if we have no free items available
1857 if (r_mesh_rcachefreechain.next == &r_mesh_rcachefreechain)
1861 // unlink from sequential chain
1862 l->next->prev = l->prev;
1863 l->prev->next = l->next;
1864 // link into free chain
1865 l->next = &r_mesh_rcachefreechain;
1866 l->prev = l->next->prev;
1867 l->next->prev = l->prev->next = l;
1869 l = &l->data->hashlink;
1870 // unlink from hash chain
1871 l->next->prev = l->prev;
1872 l->prev->next = l->next;
1876 r_mesh_rcachesequentialchain_current = l;
1877 //R_Mesh_CacheArray_ValidateState(6);
1879 // now take an item from the free chain
1880 l = r_mesh_rcachefreechain.next;
1886 l->next->prev = l->prev;
1887 l->prev->next = l->next;
1888 // relink to sequential
1889 l->next = r_mesh_rcachesequentialchain_current->prev;
1890 l->prev = l->next->prev;
1891 while (l->next->data && l->data && l->next->data->offset <= d->offset)
1894 l->next = l->next->next;
1895 l->prev = l->prev->next;
1897 while (l->prev->data && l->data && l->prev->data->offset >= d->offset)
1900 l->prev = l->prev->prev;
1901 l->next = l->next->prev;
1903 l->next->prev = l->prev->next = l;
1904 // also link into hash chain
1905 l = &l->data->hashlink;
1906 l->next = &r_mesh_rcachechain[hashindex];
1907 l->prev = l->next->prev;
1909 l->next->prev = l->prev->next = l;
1912 //r_mesh_rcachesequentialchain_current = d->sequentiallink.next;
1914 //R_Mesh_CacheArray_ValidateState(7);
1915 // and finally set the data pointer
1916 r->data = r_mesh_rcachedata + d->offset;
1917 // and tell the caller to fill the array