DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
gl_backend.c
Go to the documentation of this file.
1
2#include "quakedef.h"
3#include "cl_collision.h"
4
5#define MAX_RENDERTARGETS 4
6
7cvar_t gl_debug = {CF_CLIENT, "gl_debug", "0", "enables OpenGL 4.3 debug output, 0 = off, 1 = HIGH severity only, 2 = also MEDIUM severity, 3 = also LOW severity messages. (note: enabling may not take effect until vid_restart on some drivers, and only X11 and Windows are known to support the debug context)"};
8cvar_t gl_paranoid = {CF_CLIENT, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
9cvar_t gl_printcheckerror = {CF_CLIENT, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
10
11cvar_t r_render = {CF_CLIENT, "r_render", "1", "enables rendering 3D views (you want this on!)"};
12cvar_t r_renderview = {CF_CLIENT, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
13cvar_t r_waterwarp = {CF_CLIENT | CF_ARCHIVE, "r_waterwarp", "1", "warp view while underwater"};
14#ifdef USE_GLES2
15cvar_t gl_polyblend = {CF_CLIENT | CF_ARCHIVE, "gl_polyblend", "0", "tints view while underwater, hurt, etc"};
16#else
17cvar_t gl_polyblend = {CF_CLIENT | CF_ARCHIVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
18#endif
19
20cvar_t v_flipped = {CF_CLIENT, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
22
32
33#ifdef DEBUGGL
34void GL_PrintError(GLenum errornumber, const char *filename, unsigned int linenumber)
35{
36 switch(errornumber)
37 {
38#ifdef GL_INVALID_ENUM
39 case GL_INVALID_ENUM:
40 Con_Printf(CON_ERROR "GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
41 break;
42#endif
43#ifdef GL_INVALID_VALUE
45 Con_Printf(CON_ERROR "GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
46 break;
47#endif
48#ifdef GL_INVALID_OPERATION
50 Con_Printf(CON_ERROR "GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
51 break;
52#endif
53#ifdef GL_STACK_OVERFLOW
55 Con_Printf(CON_ERROR "GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
56 break;
57#endif
58#ifdef GL_STACK_UNDERFLOW
60 Con_Printf(CON_ERROR "GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
61 break;
62#endif
63#ifdef GL_OUT_OF_MEMORY
65 Con_Printf(CON_ERROR "GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
66 break;
67#endif
68#ifdef GL_INVALID_FRAMEBUFFER_OPERATION
70 Con_Printf(CON_ERROR "GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
71 break;
72#endif
73 default:
74 Con_Printf(CON_ERROR "GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
75 break;
76 }
77}
78#endif // DEBUGGL
79
81{
82 const char *sev = "ENUM?", *typ = "ENUM?", *src = "ENUM?", *col = "";
83 switch (severity)
84 {
85 case GL_DEBUG_SEVERITY_LOW_ARB: sev = "LOW"; break;
86 case GL_DEBUG_SEVERITY_MEDIUM_ARB: sev = "MED"; col = CON_WARN; break;
87 case GL_DEBUG_SEVERITY_HIGH_ARB: sev = "HIGH"; col = CON_ERROR; break;
88 }
89 switch (type)
90 {
91 case GL_DEBUG_TYPE_ERROR_ARB: typ = "ERROR"; col = CON_ERROR; break;
92 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: typ = "DEPRECATED"; break;
93 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: typ = "UNDEFINED"; break;
94 case GL_DEBUG_TYPE_PORTABILITY_ARB: typ = "PORTABILITY"; break;
95 case GL_DEBUG_TYPE_PERFORMANCE_ARB: typ = "PERFORMANCE"; break;
96 case GL_DEBUG_TYPE_OTHER_ARB: typ = "OTHER"; break;
97 }
98 switch (source)
99 {
100 case GL_DEBUG_SOURCE_API_ARB: src = "API"; break;
101 case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: src = "SHADER"; break;
102 case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: src = "WIN"; break;
103 case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: src = "THIRDPARTY"; break;
104 case GL_DEBUG_SOURCE_APPLICATION_ARB: src = "APP"; break;
105 case GL_DEBUG_SOURCE_OTHER_ARB: src = "OTHER"; break;
106 }
107 Con_Printf("gl_debug: %s%s %s %s: %u: %s\n", col, sev, typ, src, (unsigned int)id, message);
108}
109
110#define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
111
113
128
129typedef struct gl_state_s
130{
137 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
140 float depthrange[2];
141 float polygonoffset[2];
144 unsigned int unit;
146 float color4f[4];
153 int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
155
156 // GL3.2 Core requires that we have a GL_VERTEX_ARRAY_OBJECT, but... just one.
157 unsigned int defaultvao;
158
165
172
176
178
180}
182
184
185
186/*
187note: here's strip order for a terrain row:
1880--1--2--3--4
189|\ |\ |\ |\ |
190| \| \| \| \|
191A--B--C--D--E
192clockwise
193
194A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
195
196*elements++ = i + row;
197*elements++ = i;
198*elements++ = i + row + 1;
199*elements++ = i;
200*elements++ = i + 1;
201*elements++ = i + row + 1;
202
203
204for (y = 0;y < rows - 1;y++)
205{
206 for (x = 0;x < columns - 1;x++)
207 {
208 i = y * rows + x;
209 *elements++ = i + columns;
210 *elements++ = i;
211 *elements++ = i + columns + 1;
212 *elements++ = i;
213 *elements++ = i + 1;
214 *elements++ = i + columns + 1;
215 }
216}
217
218alternative:
2190--1--2--3--4
220| /| /|\ | /|
221|/ |/ | \|/ |
222A--B--C--D--E
223counterclockwise
224
225for (y = 0;y < rows - 1;y++)
226{
227 for (x = 0;x < columns - 1;x++)
228 {
229 i = y * rows + x;
230 *elements++ = i;
231 *elements++ = i + columns;
232 *elements++ = i + columns + 1;
233 *elements++ = i + columns;
234 *elements++ = i + columns + 1;
235 *elements++ = i + 1;
236 }
237}
238*/
239
244
246{
247 GL_Mesh_ListVBOs(true);
248}
249
250static void GL_Backend_ResetState(void);
251
252static void gl_backend_start(void)
253{
254 memset(&gl_state, 0, sizeof(gl_state));
255
257
258 Con_Printf("OpenGL backend started\n");
259
261
262 switch(vid.renderpath)
263 {
264#ifndef USE_GLES2
265 case RENDERPATH_GL32:
266 // GL3.2 Core requires that we have a VAO bound - but using more than one has no performance benefit so this is just placeholder
267 qglGenVertexArrays(1, &gl_state.defaultvao);
268 qglBindVertexArray(gl_state.defaultvao);
269 // fall through
270#endif //USE_GLES2
271 case RENDERPATH_GLES2:
272 // fetch current fbo here (default fbo is not 0 on some GLES devices)
275 break;
276 }
277
279}
280
281static void gl_backend_shutdown(void)
282{
283 Con_Print("OpenGL backend shutting down\n");
284
285 switch(vid.renderpath)
286 {
287 case RENDERPATH_GL32:
288 case RENDERPATH_GLES2:
289 break;
290 }
291
294
296
297 memset(&gl_state, 0, sizeof(gl_state));
298}
299
300static void gl_backend_newmap(void)
301{
302}
303
304static void gl_backend_devicelost(void)
305{
306 int i, endindex;
308 switch(vid.renderpath)
309 {
310 case RENDERPATH_GL32:
311 case RENDERPATH_GLES2:
312 break;
313 }
315 for (i = 0;i < endindex;i++)
316 {
318 if (!buffer || !buffer->isdynamic)
319 continue;
320 switch(vid.renderpath)
321 {
322 case RENDERPATH_GL32:
323 case RENDERPATH_GLES2:
324 break;
325 }
326 }
327}
328
330{
331 switch(vid.renderpath)
332 {
333 case RENDERPATH_GL32:
334 case RENDERPATH_GLES2:
335 break;
336 }
337}
338
340{
341 int i;
342
343 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
344 {
345 polygonelement3s[i * 3 + 0] = 0;
346 polygonelement3s[i * 3 + 1] = i + 1;
347 polygonelement3s[i * 3 + 2] = i + 2;
348 }
349 // elements for rendering a series of quads as triangles
350 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
351 {
352 quadelement3s[i * 6 + 0] = i * 4;
353 quadelement3s[i * 6 + 1] = i * 4 + 1;
354 quadelement3s[i * 6 + 2] = i * 4 + 2;
355 quadelement3s[i * 6 + 3] = i * 4;
356 quadelement3s[i * 6 + 4] = i * 4 + 2;
357 quadelement3s[i * 6 + 5] = i * 4 + 3;
358 }
359
360 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
362 for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
364
372#ifdef DEBUGGL // gl_printcheckerror does nothing in normal builds
374#endif
375
376 Cmd_AddCommand(CF_CLIENT, "gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
377
379}
380
381void GL_SetMirrorState(qbool state);
382
384{
385 vec4_t temp;
386 float iw;
387 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
388 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
389 iw = 1.0f / out[3];
390 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
391
392 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
393 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
394 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
395
396 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
397}
398
399void GL_Finish(void)
400{
401 switch(vid.renderpath)
402 {
403 case RENDERPATH_GL32:
404 case RENDERPATH_GLES2:
406 qglFinish();CHECKGLERROR
407 break;
408 }
409}
410
411static int bboxedges[12][2] =
412{
413 // top
414 {0, 1}, // +X
415 {0, 2}, // +Y
416 {1, 3}, // Y, +X
417 {2, 3}, // X, +Y
418 // bottom
419 {4, 5}, // +X
420 {4, 6}, // +Y
421 {5, 7}, // Y, +X
422 {6, 7}, // X, +Y
423 // verticals
424 {0, 4}, // +Z
425 {1, 5}, // X, +Z
426 {2, 6}, // Y, +Z
427 {3, 7}, // XY, +Z
428};
429
430qbool R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
431{
432 int i, ix1, iy1, ix2, iy2;
433 float x1, y1, x2, y2;
434 vec4_t v, v2;
435 float vertex[20][3];
436 int j, k;
437 vec4_t plane4f;
438 int numvertices;
439 float corner[8][4];
440 float dist[8];
441 int sign[8];
442 float f;
443
444 scissor[0] = r_refdef.view.viewport.x;
445 scissor[1] = r_refdef.view.viewport.y;
446 scissor[2] = r_refdef.view.viewport.width;
447 scissor[3] = r_refdef.view.viewport.height;
448
449 // if view is inside the box, just say yes it's visible
451 return false;
452
453 // transform all corners that are infront of the nearclip plane
455 plane4f[3] = r_refdef.view.frustum[4].dist;
456 numvertices = 0;
457 for (i = 0;i < 8;i++)
458 {
459 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
460 dist[i] = DotProduct4(corner[i], plane4f);
461 sign[i] = dist[i] > 0;
462 if (!sign[i])
463 {
464 VectorCopy(corner[i], vertex[numvertices]);
465 numvertices++;
466 }
467 }
468 // if some points are behind the nearclip, add clipped edge points to make
469 // sure that the scissor boundary is complete
470 if (numvertices > 0 && numvertices < 8)
471 {
472 // add clipped edge points
473 for (i = 0;i < 12;i++)
474 {
475 j = bboxedges[i][0];
476 k = bboxedges[i][1];
477 if (sign[j] != sign[k])
478 {
479 f = dist[j] / (dist[j] - dist[k]);
480 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
481 numvertices++;
482 }
483 }
484 }
485
486 // if we have no points to check, it is behind the view plane
487 if (!numvertices)
488 return true;
489
490 // if we have some points to transform, check what screen area is covered
491 x1 = y1 = x2 = y2 = 0;
492 v[3] = 1.0f;
493 //Con_Printf("%i vertices to transform...\n", numvertices);
494 for (i = 0;i < numvertices;i++)
495 {
496 VectorCopy(vertex[i], v);
498 //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]);
499 if (i)
500 {
501 if (x1 > v2[0]) x1 = v2[0];
502 if (x2 < v2[0]) x2 = v2[0];
503 if (y1 > v2[1]) y1 = v2[1];
504 if (y2 < v2[1]) y2 = v2[1];
505 }
506 else
507 {
508 x1 = x2 = v2[0];
509 y1 = y2 = v2[1];
510 }
511 }
512
513 // now convert the scissor rectangle to integer screen coordinates
514 ix1 = (int)(x1 - 1.0f);
515 //iy1 = vid.height - (int)(y2 - 1.0f);
516 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
517 iy1 = (int)(y1 - 1.0f);
518 ix2 = (int)(x2 + 1.0f);
519 //iy2 = vid.height - (int)(y1 + 1.0f);
520 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
521 iy2 = (int)(y2 + 1.0f);
522 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
523
524 // clamp it to the screen
525 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
526 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
529
530 // if it is inside out, it's not visible
531 if (ix2 <= ix1 || iy2 <= iy1)
532 return true;
533
534 // the light area is visible, set up the scissor rectangle
535 scissor[0] = ix1;
536 scissor[1] = iy1;
537 scissor[2] = ix2 - ix1;
538 scissor[3] = iy2 - iy1;
539
540 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
541 switch(vid.renderpath)
542 {
543 case RENDERPATH_GL32:
544 case RENDERPATH_GLES2:
545 break;
546 }
547
548 return false;
549}
550
551
552static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
553{
554 float q[4];
555 float d;
556 float clipPlane[4], v3[3], v4[3];
557 float normal[3];
558
559 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
560
561 VectorSet(normal, normalx, normaly, normalz);
562 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
563 VectorScale(normal, -dist, v3);
564 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
565 // FIXME: LadyHavoc: I think this can be done more efficiently somehow but I can't remember the technique
566 clipPlane[3] = -DotProduct(v4, clipPlane);
567
568 // Calculate the clip-space corner point opposite the clipping plane
569 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
570 // transform it into camera space by multiplying it
571 // by the inverse of the projection matrix
572 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
573 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
574 q[2] = -1.0f;
575 q[3] = (1.0f + m[10]) / m[14];
576
577 // Calculate the scaled plane vector
578 d = 2.0f / DotProduct4(clipPlane, q);
579
580 // Replace the third row of the projection matrix
581 m[2] = clipPlane[0] * d;
582 m[6] = clipPlane[1] * d;
583 m[10] = clipPlane[2] * d + 1.0f;
584 m[14] = clipPlane[3] * d;
585}
586
587void 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)
588{
589 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
590 float m[16];
591 memset(v, 0, sizeof(*v));
592 v->type = R_VIEWPORTTYPE_ORTHO;
593 v->cameramatrix = *cameramatrix;
594 v->x = x;
595 v->y = y;
596 v->z = 0;
597 v->width = width;
598 v->height = height;
599 v->depth = 1;
600 memset(m, 0, sizeof(m));
601 m[0] = 2/(right - left);
602 m[5] = 2/(top - bottom);
603 m[10] = -2/(zFar - zNear);
604 m[12] = - (right + left)/(right - left);
605 m[13] = - (top + bottom)/(top - bottom);
606 m[14] = - (zFar + zNear)/(zFar - zNear);
607 m[15] = 1;
608 switch(vid.renderpath)
609 {
610 case RENDERPATH_GL32:
611 case RENDERPATH_GLES2:
612 break;
613 }
614 v->screentodepth[0] = -farclip / (farclip - nearclip);
615 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
616
617 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
618
619 if (nearplane)
620 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
621
622 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
623
624#if 0
625 {
626 vec4_t test1;
627 vec4_t test2;
628 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
629 R_Viewport_TransformToScreen(v, test1, test2);
630 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
631 }
632#endif
633}
634
635void R_Viewport_InitOrtho3D(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)
636{
637 matrix4x4_t tempmatrix, basematrix;
638 float m[16];
639 memset(v, 0, sizeof(*v));
640
642 v->cameramatrix = *cameramatrix;
643 v->x = x;
644 v->y = y;
645 v->z = 0;
646 v->width = width;
647 v->height = height;
648 v->depth = 1;
649 memset(m, 0, sizeof(m));
650 m[0] = 1.0 / frustumx;
651 m[5] = 1.0 / frustumy;
652 m[10] = -2 / (farclip - nearclip);
653 m[14] = -(farclip + nearclip) / (farclip - nearclip);
654 m[15] = 1;
655 v->screentodepth[0] = -farclip / (farclip - nearclip);
656 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
657
658 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
659 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
660 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
661 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
662
663 if (nearplane)
664 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
665
667 {
668 m[0] = -m[0];
669 m[4] = -m[4];
670 m[8] = -m[8];
671 m[12] = -m[12];
672 }
673
674 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
675}
676
677void 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)
678{
679 matrix4x4_t tempmatrix, basematrix;
680 float m[16];
681 memset(v, 0, sizeof(*v));
682
684 v->cameramatrix = *cameramatrix;
685 v->x = x;
686 v->y = y;
687 v->z = 0;
688 v->width = width;
689 v->height = height;
690 v->depth = 1;
691 memset(m, 0, sizeof(m));
692 m[0] = 1.0 / frustumx;
693 m[5] = 1.0 / frustumy;
694 m[10] = -(farclip + nearclip) / (farclip - nearclip);
695 m[11] = -1;
696 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
697 v->screentodepth[0] = -farclip / (farclip - nearclip);
698 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
699
700 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
701 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
702 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
703 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
704
705 if (nearplane)
706 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
707
709 {
710 m[0] = -m[0];
711 m[4] = -m[4];
712 m[8] = -m[8];
713 m[12] = -m[12];
714 }
715
716 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
717}
718
719void 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)
720{
721 matrix4x4_t tempmatrix, basematrix;
722 const float nudge = 1.0 - 1.0 / (1<<23);
723 float m[16];
724 memset(v, 0, sizeof(*v));
725
727 v->cameramatrix = *cameramatrix;
728 v->x = x;
729 v->y = y;
730 v->z = 0;
731 v->width = width;
732 v->height = height;
733 v->depth = 1;
734 memset(m, 0, sizeof(m));
735 m[ 0] = 1.0 / frustumx;
736 m[ 5] = 1.0 / frustumy;
737 m[10] = -nudge;
738 m[11] = -1;
739 m[14] = -2 * nearclip * nudge;
740 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
741 v->screentodepth[1] = m[14] * -0.5;
742
743 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
744 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
745 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
746 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
747
748 if (nearplane)
749 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
750
752 {
753 m[0] = -m[0];
754 m[4] = -m[4];
755 m[8] = -m[8];
756 m[12] = -m[12];
757 }
758
759 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
760}
761
762float cubeviewmatrix[6][16] =
763{
764 // standard cubemap projections
765 { // +X
766 0, 0,-1, 0,
767 0,-1, 0, 0,
768 -1, 0, 0, 0,
769 0, 0, 0, 1,
770 },
771 { // -X
772 0, 0, 1, 0,
773 0,-1, 0, 0,
774 1, 0, 0, 0,
775 0, 0, 0, 1,
776 },
777 { // +Y
778 1, 0, 0, 0,
779 0, 0,-1, 0,
780 0, 1, 0, 0,
781 0, 0, 0, 1,
782 },
783 { // -Y
784 1, 0, 0, 0,
785 0, 0, 1, 0,
786 0,-1, 0, 0,
787 0, 0, 0, 1,
788 },
789 { // +Z
790 1, 0, 0, 0,
791 0,-1, 0, 0,
792 0, 0,-1, 0,
793 0, 0, 0, 1,
794 },
795 { // -Z
796 -1, 0, 0, 0,
797 0,-1, 0, 0,
798 0, 0, 1, 0,
799 0, 0, 0, 1,
800 },
801};
802float rectviewmatrix[6][16] =
803{
804 // sign-preserving cubemap projections
805 { // +X
806 0, 0,-1, 0,
807 0, 1, 0, 0,
808 1, 0, 0, 0,
809 0, 0, 0, 1,
810 },
811 { // -X
812 0, 0, 1, 0,
813 0, 1, 0, 0,
814 1, 0, 0, 0,
815 0, 0, 0, 1,
816 },
817 { // +Y
818 1, 0, 0, 0,
819 0, 0,-1, 0,
820 0, 1, 0, 0,
821 0, 0, 0, 1,
822 },
823 { // -Y
824 1, 0, 0, 0,
825 0, 0, 1, 0,
826 0, 1, 0, 0,
827 0, 0, 0, 1,
828 },
829 { // +Z
830 1, 0, 0, 0,
831 0, 1, 0, 0,
832 0, 0,-1, 0,
833 0, 0, 0, 1,
834 },
835 { // -Z
836 1, 0, 0, 0,
837 0, 1, 0, 0,
838 0, 0, 1, 0,
839 0, 0, 0, 1,
840 },
841};
842
843void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
844{
845 matrix4x4_t tempmatrix, basematrix;
846 float m[16];
847 memset(v, 0, sizeof(*v));
849 v->cameramatrix = *cameramatrix;
850 v->width = size;
851 v->height = size;
852 v->depth = 1;
853 memset(m, 0, sizeof(m));
854 m[0] = m[5] = 1.0f;
855 m[10] = -(farclip + nearclip) / (farclip - nearclip);
856 m[11] = -1;
857 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
858
859 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
860 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
861 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
862
863 if (nearplane)
864 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
865
866 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
867}
868
869void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane, int offsetx, int offsety)
870{
871 matrix4x4_t tempmatrix, basematrix;
872 float m[16];
873 memset(v, 0, sizeof(*v));
875 v->cameramatrix = *cameramatrix;
876 v->x = offsetx + (side & 1) * size;
877 v->y = offsety + (side >> 1) * size;
878 v->width = size;
879 v->height = size;
880 v->depth = 1;
881 memset(m, 0, sizeof(m));
882 m[0] = m[5] = 1.0f * ((float)size - border) / size;
883 m[10] = -(farclip + nearclip) / (farclip - nearclip);
884 m[11] = -1;
885 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
886
887 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
888 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
889 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
890
891 if (nearplane)
892 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
893
894 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
895}
896
898{
899 gl_viewport = *v;
900
901 // FIXME: v_flipped_state is evil, this probably breaks somewhere
903
904 // copy over the matrices to our state
905 gl_viewmatrix = v->viewmatrix;
906 gl_projectionmatrix = v->projectmatrix;
907
908 switch(vid.renderpath)
909 {
910 case RENDERPATH_GL32:
911 case RENDERPATH_GLES2:
913 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
914 break;
915 }
916
917 // force an update of the derived matrices
920}
921
923{
924 *v = gl_viewport;
925}
926
927static void GL_BindVBO(int bufferobject)
928{
929 if (gl_state.vertexbufferobject != bufferobject)
930 {
931 gl_state.vertexbufferobject = bufferobject;
933 qglBindBuffer(GL_ARRAY_BUFFER, bufferobject);CHECKGLERROR
934 }
935}
936
937static void GL_BindEBO(int bufferobject)
938{
939 if (gl_state.elementbufferobject != bufferobject)
940 {
941 gl_state.elementbufferobject = bufferobject;
943 qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferobject);CHECKGLERROR
944 }
945}
946
947static void GL_BindUBO(int bufferobject)
948{
949 if (gl_state.uniformbufferobject != bufferobject)
950 {
951 gl_state.uniformbufferobject = bufferobject;
952#ifdef GL_UNIFORM_BUFFER
954 qglBindBuffer(GL_UNIFORM_BUFFER, bufferobject);CHECKGLERROR
955#endif
956 }
957}
958
960int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
961{
962 int temp;
963 GLuint status;
964 switch(vid.renderpath)
965 {
966 case RENDERPATH_GL32:
967 case RENDERPATH_GLES2:
969 qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
970
971#ifndef USE_GLES2
972 R_Mesh_SetRenderTargets(temp); // This breaks GLES2.
973 // GL_ARB_framebuffer_object (GL3-class hardware) - depth stencil attachment
974#endif
975
976#ifdef USE_GLES2
977 // FIXME: separate stencil attachment on GLES
978 if (depthtexture && depthtexture->texnum ) { qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR }
979 if (depthtexture && depthtexture->renderbuffernum ) { qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR }
980#else
981 if (depthtexture && depthtexture->texnum )
982 {
983 qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
984 if (depthtexture->glisdepthstencil) { qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR }
985 }
986 if (depthtexture && depthtexture->renderbuffernum )
987 {
988 qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
989 if (depthtexture->glisdepthstencil) { qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR }
990 }
991#endif
992
993 if (colortexture && colortexture->texnum ) { qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR }
994 if (colortexture2 && colortexture2->texnum) { qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR }
995 if (colortexture3 && colortexture3->texnum) { qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR }
996 if (colortexture4 && colortexture4->texnum) { qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR }
997 if (colortexture && colortexture->renderbuffernum ) { qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR }
998 if (colortexture2 && colortexture2->renderbuffernum) { qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR }
999 if (colortexture3 && colortexture3->renderbuffernum) { qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR }
1000 if (colortexture4 && colortexture4->renderbuffernum) { qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR }
1001
1002#ifndef USE_GLES2
1003 if (colortexture4)
1004 {
1005 qglDrawBuffers(4, drawbuffers);CHECKGLERROR
1006 qglReadBuffer(GL_NONE);CHECKGLERROR
1007 }
1008 else if (colortexture3)
1009 {
1010 qglDrawBuffers(3, drawbuffers);CHECKGLERROR
1011 qglReadBuffer(GL_NONE);CHECKGLERROR
1012 }
1013 else if (colortexture2)
1014 {
1015 qglDrawBuffers(2, drawbuffers);CHECKGLERROR
1016 qglReadBuffer(GL_NONE);CHECKGLERROR
1017 }
1018 else if (colortexture)
1019 {
1020 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1021 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1022 }
1023 else
1024 {
1025 qglDrawBuffer(GL_NONE);CHECKGLERROR
1026 qglReadBuffer(GL_NONE);CHECKGLERROR
1027 }
1028#endif
1029 status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
1030 if (status != GL_FRAMEBUFFER_COMPLETE)
1031 {
1032 Con_Printf(CON_ERROR "R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
1033 gl_state.framebufferobject = 0; // GL unbinds it for us
1034 qglDeleteFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
1035 temp = 0;
1036 }
1037 return temp;
1038 }
1039 return 0;
1040}
1041
1043{
1044 switch(vid.renderpath)
1045 {
1046 case RENDERPATH_GL32:
1047 case RENDERPATH_GLES2:
1048 if (fbo)
1049 {
1050 // GL clears the binding if we delete something bound
1051 if (gl_state.framebufferobject == fbo)
1053 qglDeleteFramebuffers(1, (GLuint*)&fbo);CHECKGLERROR
1054 }
1055 break;
1056 }
1057}
1058
1060{
1061 // set up framebuffer object or render targets for the active rendering API
1062 switch (vid.renderpath)
1063 {
1064 case RENDERPATH_GL32:
1065 case RENDERPATH_GLES2:
1066 if (gl_state.framebufferobject != fbo)
1067 {
1070 }
1071 break;
1072 }
1073}
1074
1075static void GL_Backend_ResetState(void)
1076{
1077 gl_state.active = true;
1078 gl_state.depthtest = true;
1079 gl_state.alphatocoverage = false;
1082 gl_state.blend = false;
1084 gl_state.colormask = 15;
1089 gl_state.cullfaceenable = false;
1090 gl_state.polygonoffset[0] = 0;
1091 gl_state.polygonoffset[1] = 0;
1094
1095 switch(vid.renderpath)
1096 {
1097 case RENDERPATH_GL32:
1098 case RENDERPATH_GLES2:
1099 // set up debug output early
1101 {
1102 GLuint unused = 0;
1104 Con_Print("gl_debug: GL_ARB_debug_output is supported, enabling callback\n");
1105 if (gl_debug.integer >= 1)
1107 if (gl_debug.integer >= 3)
1108 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, &unused, gl_debug.integer >= 3 ? GL_TRUE : GL_FALSE);
1109 else if (gl_debug.integer >= 1)
1110 {
1111 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, &unused, gl_debug.integer >= 3 ? GL_TRUE : GL_FALSE);
1112 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM_ARB, 0, &unused, gl_debug.integer >= 2 ? GL_TRUE : GL_FALSE);
1113 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH_ARB, 0, &unused, gl_debug.integer >= 1 ? GL_TRUE : GL_FALSE);
1114 }
1115 else
1116 qglDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, &unused, GL_FALSE);
1117 qglDebugMessageCallbackARB(GL_DebugOutputCallback, NULL);
1118 }
1120 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1122 qglDisable(GL_BLEND);CHECKGLERROR
1123 qglCullFace(gl_state.cullface);CHECKGLERROR
1124 qglDisable(GL_CULL_FACE);CHECKGLERROR
1125 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1126 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1127 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1128 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1129 qglBindBuffer(GL_ARRAY_BUFFER, 0);
1130 qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1132 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1133 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1134 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1137 break;
1138 }
1139}
1140
1141void GL_ActiveTexture(unsigned int num)
1142{
1143 if (gl_state.unit != num)
1144 {
1145 gl_state.unit = num;
1146 switch(vid.renderpath)
1147 {
1148 case RENDERPATH_GL32:
1149 case RENDERPATH_GLES2:
1151 qglActiveTexture(GL_TEXTURE0 + gl_state.unit);CHECKGLERROR
1152 break;
1153 }
1154 }
1155}
1156
1157void GL_BlendFunc(int blendfunc1, int blendfunc2)
1158{
1159 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1160 {
1161 qbool blendenable;
1162 gl_state.blendfunc1 = blendfunc1;
1163 gl_state.blendfunc2 = blendfunc2;
1164 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1165 switch(vid.renderpath)
1166 {
1167 case RENDERPATH_GL32:
1168 case RENDERPATH_GLES2:
1170 if (qglBlendFuncSeparate)
1171 {
1172 qglBlendFuncSeparate(gl_state.blendfunc1, gl_state.blendfunc2, GL_ZERO, GL_ONE);CHECKGLERROR // ELUAN: Adreno 225 (and others) compositing workaround
1173 }
1174 else
1175 {
1177 }
1178 if (gl_state.blend != blendenable)
1179 {
1180 gl_state.blend = blendenable;
1181 if (!gl_state.blend)
1182 {
1183 qglDisable(GL_BLEND);CHECKGLERROR
1184 }
1185 else
1186 {
1187 qglEnable(GL_BLEND);CHECKGLERROR
1188 }
1189 }
1190 break;
1191 }
1192 }
1193}
1194
1195void GL_DepthMask(int state)
1196{
1197 if (gl_state.depthmask != state)
1198 {
1199 gl_state.depthmask = state;
1200 switch(vid.renderpath)
1201 {
1202 case RENDERPATH_GL32:
1203 case RENDERPATH_GLES2:
1205 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1206 break;
1207 }
1208 }
1209}
1210
1211void GL_DepthTest(int state)
1212{
1213 if (gl_state.depthtest != state)
1214 {
1215 gl_state.depthtest = state;
1216 switch(vid.renderpath)
1217 {
1218 case RENDERPATH_GL32:
1219 case RENDERPATH_GLES2:
1221 if (gl_state.depthtest)
1222 {
1223 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1224 }
1225 else
1226 {
1227 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1228 }
1229 break;
1230 }
1231 }
1232}
1233
1234void GL_DepthFunc(int state)
1235{
1236 if (gl_state.depthfunc != state)
1237 {
1238 gl_state.depthfunc = state;
1239 switch(vid.renderpath)
1240 {
1241 case RENDERPATH_GL32:
1242 case RENDERPATH_GLES2:
1244 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1245 break;
1246 }
1247 }
1248}
1249
1250void GL_DepthRange(float nearfrac, float farfrac)
1251{
1252 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1253 {
1254 gl_state.depthrange[0] = nearfrac;
1255 gl_state.depthrange[1] = farfrac;
1256 switch(vid.renderpath)
1257 {
1258 case RENDERPATH_GL32:
1259 case RENDERPATH_GLES2:
1261#ifdef USE_GLES2
1262 qglDepthRangef(gl_state.depthrange[0], gl_state.depthrange[1]);CHECKGLERROR
1263#else
1264 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);CHECKGLERROR
1265#endif
1266 break;
1267 }
1268 }
1269}
1270
1271void R_SetStencil(qbool enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1272{
1273 switch (vid.renderpath)
1274 {
1275 case RENDERPATH_GL32:
1276 case RENDERPATH_GLES2:
1278 if (enable)
1279 {
1280 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1281 }
1282 else
1283 {
1284 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1285 }
1286 qglStencilMask(writemask);CHECKGLERROR
1287 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1288 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1290 break;
1291 }
1292}
1293
1294void GL_PolygonOffset(float planeoffset, float depthoffset)
1295{
1296 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1297 {
1298 gl_state.polygonoffset[0] = planeoffset;
1299 gl_state.polygonoffset[1] = depthoffset;
1300 switch(vid.renderpath)
1301 {
1302 case RENDERPATH_GL32:
1303 case RENDERPATH_GLES2:
1306 break;
1307 }
1308 }
1309}
1310
1312{
1313 if (v_flipped_state != state)
1314 {
1315 v_flipped_state = state;
1316 if (gl_state.cullface == GL_BACK)
1318 else if (gl_state.cullface == GL_FRONT)
1320 else
1321 return;
1322 switch(vid.renderpath)
1323 {
1324 case RENDERPATH_GL32:
1325 case RENDERPATH_GLES2:
1327 qglCullFace(gl_state.cullface);CHECKGLERROR
1328 break;
1329 }
1330 }
1331}
1332
1333void GL_CullFace(int state)
1334{
1335 if(v_flipped_state)
1336 {
1337 if(state == GL_FRONT)
1338 state = GL_BACK;
1339 else if(state == GL_BACK)
1340 state = GL_FRONT;
1341 }
1342
1343 switch(vid.renderpath)
1344 {
1345 case RENDERPATH_GL32:
1346 case RENDERPATH_GLES2:
1348
1349 if (state != GL_NONE)
1350 {
1352 {
1353 gl_state.cullfaceenable = true;
1354 qglEnable(GL_CULL_FACE);CHECKGLERROR
1355 }
1356 if (gl_state.cullface != state)
1357 {
1358 gl_state.cullface = state;
1359 qglCullFace(gl_state.cullface);CHECKGLERROR
1360 }
1361 }
1362 else
1363 {
1365 {
1366 gl_state.cullfaceenable = false;
1367 qglDisable(GL_CULL_FACE);CHECKGLERROR
1368 }
1369 }
1370 break;
1371 }
1372}
1373
1375{
1376 if (gl_state.alphatocoverage != state)
1377 {
1378 gl_state.alphatocoverage = state;
1379 switch(vid.renderpath)
1380 {
1381 case RENDERPATH_GLES2:
1382 break;
1383 case RENDERPATH_GL32:
1384#ifndef USE_GLES2
1385 // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
1388 {
1390// qglEnable(GL_MULTISAMPLE);CHECKGLERROR
1391 }
1392 else
1393 {
1395// qglDisable(GL_MULTISAMPLE);CHECKGLERROR
1396 }
1397#endif
1398 break;
1399 }
1400 }
1401}
1402
1403void GL_ColorMask(int r, int g, int b, int a)
1404{
1405 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
1406 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
1407 if (gl_state.colormask != state)
1408 {
1409 gl_state.colormask = state;
1410 switch(vid.renderpath)
1411 {
1412 case RENDERPATH_GL32:
1413 case RENDERPATH_GLES2:
1415 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
1416 break;
1417 }
1418 }
1419}
1420
1421void GL_Color(float cr, float cg, float cb, float ca)
1422{
1423 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)
1424 {
1425 gl_state.color4f[0] = cr;
1426 gl_state.color4f[1] = cg;
1427 gl_state.color4f[2] = cb;
1428 gl_state.color4f[3] = ca;
1429 switch(vid.renderpath)
1430 {
1431 case RENDERPATH_GL32:
1432 case RENDERPATH_GLES2:
1433 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);CHECKGLERROR
1434 break;
1435 }
1436 }
1437}
1438
1439void GL_Scissor (int x, int y, int width, int height)
1440{
1441 switch(vid.renderpath)
1442 {
1443 case RENDERPATH_GL32:
1444 case RENDERPATH_GLES2:
1446 qglScissor(x, y,width,height);CHECKGLERROR
1447 break;
1448 }
1449}
1450
1451void GL_ScissorTest(int state)
1452{
1453 if (gl_state.scissortest != state)
1454 {
1455 gl_state.scissortest = state;
1456 switch(vid.renderpath)
1457 {
1458 case RENDERPATH_GL32:
1459 case RENDERPATH_GLES2:
1462 qglEnable(GL_SCISSOR_TEST);
1463 else
1464 qglDisable(GL_SCISSOR_TEST);
1466 break;
1467 }
1468 }
1469}
1470
1471void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
1472{
1473 // opaque black - if you want transparent black, you'll need to pass in a colorvalue
1474 static const float blackcolor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
1475 // prevent warnings when trying to clear a buffer that does not exist
1476 if (!colorvalue)
1477 colorvalue = blackcolor;
1478 if (!vid.stencil)
1479 {
1480 mask &= ~GL_STENCIL_BUFFER_BIT;
1481 stencilvalue = 0;
1482 }
1483 switch(vid.renderpath)
1484 {
1485 case RENDERPATH_GL32:
1486 case RENDERPATH_GLES2:
1489 {
1490 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
1491 }
1493 {
1494#ifdef USE_GLES2
1495 //qglClearDepthf(depthvalue);CHECKGLERROR
1496#else
1497 qglClearDepth(depthvalue);CHECKGLERROR
1498#endif
1499 }
1501 {
1502 qglClearStencil(stencilvalue);CHECKGLERROR
1503 }
1504 qglClear(mask);CHECKGLERROR
1505 break;
1506 }
1507}
1508
1509void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
1510{
1511 switch(vid.renderpath)
1512 {
1513 case RENDERPATH_GL32:
1515 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
1516 break;
1517 case RENDERPATH_GLES2: // glReadPixels() lacks GL_BGRA support (even in ES 3.2)
1519 {
1520 int i;
1521 int r;
1522 // int g;
1523 int b;
1524 // int a;
1525 qglReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
1526 for (i = 0;i < width * height * 4;i += 4)
1527 {
1528 r = outpixels[i+0];
1529 // g = outpixels[i+1];
1530 b = outpixels[i+2];
1531 // a = outpixels[i+3];
1532 outpixels[i+0] = b;
1533 // outpixels[i+1] = g;
1534 outpixels[i+2] = r;
1535 // outpixels[i+3] = a;
1536 }
1537 }
1538 break;
1539 }
1540}
1541
1542
1543#ifdef CONFIG_VIDEO_CAPTURE
1544/*
1545 * GL_CaptureVideo*
1546 * GPU scaling and async DMA transfer of completed frames
1547 * Minimum GL version: 3.0, for glBlitFramebuffer
1548 * Minimum GLES version: 3.0, for glBlitFramebuffer and GL_PIXEL_PACK_BUFFER (PBOs)
1549 */
1550
1552{
1553 int width = cls.capturevideo.width, height = cls.capturevideo.height;
1554 // format is GL_BGRA type is GL_UNSIGNED_BYTE
1555 GLsizeiptr data_size = width * height * 4;
1556
1557// create PBOs
1558 qglGenBuffers(PBO_COUNT, cls.capturevideo.PBOs);
1559 for (int i = 0; i < PBO_COUNT; ++i)
1560 {
1561 qglBindBuffer(GL_PIXEL_PACK_BUFFER, cls.capturevideo.PBOs[i]);
1562 // Allocate memory and leave it uninitialised.
1563 qglBufferData(GL_PIXEL_PACK_BUFFER, data_size, NULL, GL_DYNAMIC_READ);CHECKGLERROR
1564 }
1565 qglBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
1566
1567// If scaling is necessary create an FBO with attached texture
1568 if (width == vid.mode.width && height == vid.mode.height)
1569 {
1570 cls.capturevideo.FBO = 0;
1571 return;
1572 }
1573 qglGenFramebuffers(1, &cls.capturevideo.FBO);
1574 qglBindFramebuffer(GL_FRAMEBUFFER, cls.capturevideo.FBO);
1575 qglGenTextures(1, &cls.capturevideo.FBOtex);
1576 qglBindTexture(GL_TEXTURE_2D, cls.capturevideo.FBOtex);
1577 // Allocate memory and leave it uninitialised (format and type don't matter: data is NULL).
1578 // Same internalformat as TEXTYPE_COLORBUFFER.
1580 qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cls.capturevideo.FBOtex, 0);CHECKGLERROR
1581 qglBindTexture(GL_TEXTURE_2D, 0);
1582 qglBindFramebuffer(GL_FRAMEBUFFER, 0);
1583}
1584
1585void GL_CaptureVideo_VideoFrame(int newframestepframenum)
1586{
1587 int width = cls.capturevideo.width, height = cls.capturevideo.height;
1588 GLubyte *pixbuf;
1589 GLuint oldestPBOindex;
1590
1591 if (++cls.capturevideo.PBOindex >= PBO_COUNT)
1592 cls.capturevideo.PBOindex = 0;
1593 if ((oldestPBOindex = cls.capturevideo.PBOindex + 1) >= PBO_COUNT)
1594 oldestPBOindex = 0;
1595
1596 // Ensure we'll read from the default FB
1598
1599 // If necessary, scale the newest frame with linear filtering
1600 if (cls.capturevideo.FBO)
1601 {
1602 qglBindFramebuffer(GL_DRAW_FRAMEBUFFER, cls.capturevideo.FBO);
1603 qglBlitFramebuffer(0, 0, vid.mode.width, vid.mode.height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);CHECKGLERROR
1604 qglBindFramebuffer(GL_READ_FRAMEBUFFER, cls.capturevideo.FBO);
1605 }
1606
1607 // Copy the newest frame to a PBO for later CPU access.
1608 qglBindBuffer(GL_PIXEL_PACK_BUFFER, cls.capturevideo.PBOs[cls.capturevideo.PBOindex]);
1609 qglReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, 0);CHECKGLERROR
1610
1611 if (cls.capturevideo.FBO)
1612 qglBindFramebuffer(GL_FRAMEBUFFER, 0);
1613
1614 // Save the oldest frame from its PBO (blocks until sync if still not ready)
1615 // speed is critical here, so do saving as directly as possible
1616 if (newframestepframenum >= PBO_COUNT) // Don't read uninitialised memory, newframestepframenum starts at 1
1617 {
1618 qglBindBuffer(GL_PIXEL_PACK_BUFFER, cls.capturevideo.PBOs[oldestPBOindex]);
1620 if(pixbuf)
1621 {
1622 cls.capturevideo.writeVideoFrame(newframestepframenum - cls.capturevideo.framestepframe, pixbuf);
1623 qglUnmapBuffer(GL_PIXEL_PACK_BUFFER);
1624 }
1625 }
1626
1627 qglBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
1628}
1629
1630void GL_CaptureVideo_EndVideo(void)
1631{
1632 // SCR_CaptureVideo won't call GL_CaptureVideo_VideoFrame again
1633 // but the last frame(s) are waiting in PBO(s) due to async transfer.
1634 // On the last normal frame we queued to 1 PBO and saved from 1, so we have PBO_COUNT-1 left
1635 for (int i = 1; i < PBO_COUNT; ++i)
1636 GL_CaptureVideo_VideoFrame(cls.capturevideo.framestepframe + i);
1637
1638 qglDeleteTextures(1, &cls.capturevideo.FBOtex);
1639 qglDeleteFramebuffers(1, &cls.capturevideo.FBO);
1640 qglDeleteBuffers(PBO_COUNT, cls.capturevideo.PBOs);
1641}
1642#endif
1643
1644
1645// called at beginning of frame
1647{
1650#ifdef DEBUGGL // gl_printcheckerror isn't registered in normal builds
1652 {
1653 Con_Printf(CON_WARN "WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
1655 }
1656#endif
1657}
1658
1659static qbool GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
1660{
1661 int shaderobject;
1662 int shadercompiled;
1663 char compilelog[MAX_INPUTLINE];
1664 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
1665 if (!shaderobject)
1666 return false;
1667 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
1668 qglCompileShader(shaderobject);CHECKGLERROR
1669 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
1670 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
1671 if (compilelog[0] && ((strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error")) || ((strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")) && developer.integer) || developer_extra.integer))
1672 {
1673 int i, j, pretextlines = 0;
1674 for (i = 0;i < numstrings - 1;i++)
1675 for (j = 0;strings[i][j];j++)
1676 if (strings[i][j] == '\n')
1677 pretextlines++;
1678 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
1679 }
1680 if (!shadercompiled)
1681 {
1682 qglDeleteShader(shaderobject);CHECKGLERROR
1683 return false;
1684 }
1685 qglAttachShader(programobject, shaderobject);CHECKGLERROR
1686 qglDeleteShader(shaderobject);CHECKGLERROR
1687 return true;
1688}
1689
1690unsigned 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)
1691{
1692 GLint programlinked;
1693 GLuint programobject = 0;
1694 char linklog[MAX_INPUTLINE];
1696
1697 programobject = qglCreateProgram();CHECKGLERROR
1698 if (!programobject)
1699 return 0;
1700
1701 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
1702 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
1703 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
1704 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
1705 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
1706 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
1707 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
1708 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
1709 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_SkeletalIndex");
1710 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_SkeletalWeight");
1711#ifndef USE_GLES2
1712 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
1713#endif
1715
1716 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
1717 goto cleanup;
1718
1719#if defined(GL_GEOMETRY_SHADER) && !defined(USE_GLES2)
1720 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
1721 goto cleanup;
1722#endif
1723
1724 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
1725 goto cleanup;
1726
1727 qglLinkProgram(programobject);CHECKGLERROR
1728 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
1729 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
1730
1731 if (linklog[0])
1732 {
1733
1734 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer)
1735 Con_DPrintf("program link log:\n%s\n", linklog);
1736
1737 // software vertex shader is ok but software fragment shader is WAY
1738 // too slow, fail program if so.
1739 // NOTE: this string might be ATI specific, but that's ok because the
1740 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
1741 // software fragment shader due to low instruction and dependent
1742 // texture limits.
1743 if (strstr(linklog, "fragment shader will run in software"))
1744 programlinked = false;
1745 }
1746
1747 if (!programlinked)
1748 goto cleanup;
1749
1750 return programobject;
1751cleanup:
1752 qglDeleteProgram(programobject);CHECKGLERROR
1753 return 0;
1754}
1755
1756void GL_Backend_FreeProgram(unsigned int prog)
1757{
1759 qglDeleteProgram(prog);
1761}
1762
1763// renders triangles using vertices from the active arrays
1764void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, int element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, int element3s_bufferoffset)
1765{
1766 unsigned int numelements = numtriangles * 3;
1767 int bufferobject3i;
1768 size_t bufferoffset3i;
1769 int bufferobject3s;
1770 size_t bufferoffset3s;
1771 if (numvertices < 3 || numtriangles < 1)
1772 {
1773 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
1774 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);
1775 return;
1776 }
1777 // adjust the pointers for firsttriangle
1778 if (element3i)
1779 element3i += firsttriangle * 3;
1780 if (element3i_indexbuffer)
1781 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
1782 if (element3s)
1783 element3s += firsttriangle * 3;
1784 if (element3s_indexbuffer)
1785 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
1786 // upload a dynamic index buffer if needed
1787 if (element3s)
1788 {
1789 if (!element3s_indexbuffer)
1790 element3s_indexbuffer = R_BufferData_Store(numelements * sizeof(*element3s), (void *)element3s, R_BUFFERDATA_INDEX16, &element3s_bufferoffset);
1791 }
1792 else if (element3i)
1793 {
1794 if (!element3i_indexbuffer)
1795 element3i_indexbuffer = R_BufferData_Store(numelements * sizeof(*element3i), (void *)element3i, R_BUFFERDATA_INDEX32, &element3i_bufferoffset);
1796 }
1797 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
1798 bufferoffset3i = element3i_bufferoffset;
1799 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
1800 bufferoffset3s = element3s_bufferoffset;
1802 r_refdef.stats[r_stat_draws_vertices] += numvertices;
1803 r_refdef.stats[r_stat_draws_elements] += numelements;
1804 if (gl_paranoid.integer)
1805 {
1806 unsigned int i;
1807 if (element3i)
1808 {
1809 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1810 {
1811 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
1812 {
1813 Con_Printf(CON_WARN "R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
1814 return;
1815 }
1816 }
1817 }
1818 if (element3s)
1819 {
1820 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1821 {
1822 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
1823 {
1824 Con_Printf(CON_WARN "R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
1825 return;
1826 }
1827 }
1828 }
1829 }
1831 {
1832 switch(vid.renderpath)
1833 {
1834 case RENDERPATH_GL32:
1835 case RENDERPATH_GLES2:
1837 if (bufferobject3s)
1838 {
1839 GL_BindEBO(bufferobject3s);
1840 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);CHECKGLERROR
1841 }
1842 else if (bufferobject3i)
1843 {
1844 GL_BindEBO(bufferobject3i);
1845 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);CHECKGLERROR
1846 }
1847 else
1848 {
1849 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);CHECKGLERROR
1850 }
1851 break;
1852 }
1853 }
1854}
1855
1856// restores backend state, used when done with 3D rendering
1858{
1860}
1861
1862r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qbool isindexbuffer, qbool isuniformbuffer, qbool isdynamic, qbool isindex16)
1863{
1866 memset(buffer, 0, sizeof(*buffer));
1867 buffer->bufferobject = 0;
1868 buffer->devicebuffer = NULL;
1869 buffer->size = size;
1870 buffer->isindexbuffer = isindexbuffer;
1871 buffer->isuniformbuffer = isuniformbuffer;
1872 buffer->isdynamic = isdynamic;
1873 buffer->isindex16 = isindex16;
1874 dp_strlcpy(buffer->name, name, sizeof(buffer->name));
1876 return buffer;
1877}
1878
1879void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size, qbool subdata, size_t offset)
1880{
1881 if (!buffer)
1882 return;
1883 if (buffer->isindexbuffer)
1884 {
1887 }
1888 else
1889 {
1892 }
1893 if (!subdata)
1894 buffer->size = size;
1895 switch(vid.renderpath)
1896 {
1897 case RENDERPATH_GL32:
1898 case RENDERPATH_GLES2:
1899 if (!buffer->bufferobject)
1900 qglGenBuffers(1, (GLuint *)&buffer->bufferobject);
1902 if (buffer->isuniformbuffer)
1903 GL_BindUBO(buffer->bufferobject);
1904 else if (buffer->isindexbuffer)
1905 GL_BindEBO(buffer->bufferobject);
1906 else
1907 GL_BindVBO(buffer->bufferobject);
1908
1909 {
1910 int buffertype;
1911 buffertype = buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
1912#ifdef GL_UNIFORM_BUFFER
1913 if (buffer->isuniformbuffer)
1914 buffertype = GL_UNIFORM_BUFFER;
1915#endif
1917 if (subdata)
1918 qglBufferSubData(buffertype, offset, size, data);
1919 else
1920 qglBufferData(buffertype, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW);
1922 }
1923 if (buffer->isuniformbuffer)
1924 GL_BindUBO(0);
1925 break;
1926 }
1927}
1928
1930{
1931 if (!buffer)
1932 return;
1933 switch(vid.renderpath)
1934 {
1935 case RENDERPATH_GL32:
1936 case RENDERPATH_GLES2:
1937 // GL clears the binding if we delete something bound
1938 if (gl_state.uniformbufferobject == buffer->bufferobject)
1940 if (gl_state.vertexbufferobject == buffer->bufferobject)
1942 if (gl_state.elementbufferobject == buffer->bufferobject)
1945 qglDeleteBuffers(1, (GLuint *)&buffer->bufferobject);CHECKGLERROR
1946 break;
1947 }
1949}
1950
1951static const char *buffertypename[R_BUFFERDATA_COUNT] = {"vertex", "index16", "index32", "uniform"};
1953{
1954 int i, endindex;
1955 int type;
1956 int isdynamic;
1957 int index16count, index16mem;
1958 int index32count, index32mem;
1959 int vertexcount, vertexmem;
1960 int uniformcount, uniformmem;
1961 int totalcount, totalmem;
1962 size_t bufferstat[R_BUFFERDATA_COUNT][2][2];
1964 memset(bufferstat, 0, sizeof(bufferstat));
1966 for (i = 0;i < endindex;i++)
1967 {
1969 if (!buffer)
1970 continue;
1971 if (buffer->isuniformbuffer)
1973 else if (buffer->isindexbuffer && buffer->isindex16)
1975 else if (buffer->isindexbuffer)
1977 else
1979 isdynamic = buffer->isdynamic;
1980 bufferstat[type][isdynamic][0]++;
1981 bufferstat[type][isdynamic][1] += buffer->size;
1982 if (printeach)
1983 Con_Printf("buffer #%i %s = %i bytes (%s %s)\n", i, buffer->name, (int)buffer->size, isdynamic ? "dynamic" : "static", buffertypename[type]);
1984 }
1985 index16count = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][0] + bufferstat[R_BUFFERDATA_INDEX16][1][0]);
1986 index16mem = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][1] + bufferstat[R_BUFFERDATA_INDEX16][1][1]);
1987 index32count = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][0] + bufferstat[R_BUFFERDATA_INDEX32][1][0]);
1988 index32mem = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][1] + bufferstat[R_BUFFERDATA_INDEX32][1][1]);
1989 vertexcount = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][0] + bufferstat[R_BUFFERDATA_VERTEX ][1][0]);
1990 vertexmem = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][1] + bufferstat[R_BUFFERDATA_VERTEX ][1][1]);
1991 uniformcount = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][0] + bufferstat[R_BUFFERDATA_UNIFORM][1][0]);
1992 uniformmem = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][1] + bufferstat[R_BUFFERDATA_UNIFORM][1][1]);
1993 totalcount = index16count + index32count + vertexcount + uniformcount;
1994 totalmem = index16mem + index32mem + vertexmem + uniformmem;
1995 Con_Printf("%i 16bit indexbuffers totalling %i bytes (%.3f MB)\n%i 32bit indexbuffers totalling %i bytes (%.3f MB)\n%i vertexbuffers totalling %i bytes (%.3f MB)\n%i uniformbuffers totalling %i bytes (%.3f MB)\ncombined %i buffers totalling %i bytes (%.3fMB)\n", index16count, index16mem, index16mem / 10248576.0, index32count, index32mem, index32mem / 10248576.0, vertexcount, vertexmem, vertexmem / 10248576.0, uniformcount, uniformmem, uniformmem / 10248576.0, totalcount, totalmem, totalmem / 10248576.0);
1996}
1997
1998
1999
2000void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2001{
2002 switch(vid.renderpath)
2003 {
2004 case RENDERPATH_GL32:
2005 case RENDERPATH_GLES2:
2007 {
2008 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2009 if (!bufferobject && gl_paranoid.integer)
2010 Con_DPrintf(CON_WARN "Warning: no bufferobject in R_Mesh_VertexPointer(%i, %i, %i, %p, %p, %08x)", components, gltype, (int)stride, pointer, (void *)vertexbuffer, (unsigned int)bufferoffset);
2016 gl_state.pointer_vertex_offset = bufferoffset;
2018 GL_BindVBO(bufferobject);
2019 // LadyHavoc: special flag added to gltype for unnormalized types
2020 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2021 }
2022 break;
2023 }
2024}
2025
2026void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2027{
2028 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
2029 // the pointer only.
2030 switch(vid.renderpath)
2031 {
2032 case RENDERPATH_GL32:
2033 case RENDERPATH_GLES2:
2035 if (pointer)
2036 {
2037 // caller wants color array enabled
2038 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2040 {
2043 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
2044 }
2046 {
2051 gl_state.pointer_color_vertexbuffer = vertexbuffer;
2052 gl_state.pointer_color_offset = bufferoffset;
2054 GL_BindVBO(bufferobject);
2055 // LadyHavoc: special flag added to gltype for unnormalized types
2056 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2057 }
2058 }
2059 else
2060 {
2061 // caller wants color array disabled
2063 {
2066 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
2067 // when color array is on the current color gets trashed, set it again
2069 }
2070 }
2071 break;
2072 }
2073}
2074
2075void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2076{
2077 gltextureunit_t *unit = gl_state.units + unitnum;
2078 if (unitnum >= MAX_TEXTUREUNITS)
2079 Sys_Error("R_Mesh_TexCoordPointer: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
2080 // update array settings
2081 // note: there is no need to check bufferobject here because all cases
2082 // that involve a valid bufferobject also supply a texcoord array
2083 switch(vid.renderpath)
2084 {
2085 case RENDERPATH_GL32:
2086 case RENDERPATH_GLES2:
2088 if (pointer)
2089 {
2090 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2091 // texture array unit is enabled, enable the array
2092 if (!unit->arrayenabled)
2093 {
2094 unit->arrayenabled = true;
2095 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
2096 }
2097 // texcoord array
2098 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)
2099 {
2100 unit->pointer_texcoord_components = components;
2101 unit->pointer_texcoord_gltype = gltype;
2104 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
2105 unit->pointer_texcoord_offset = bufferoffset;
2106 GL_BindVBO(bufferobject);
2107 // LadyHavoc: special flag added to gltype for unnormalized types
2108 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2109 }
2110 }
2111 else
2112 {
2113 // texture array unit is disabled, disable the array
2114 if (unit->arrayenabled)
2115 {
2116 unit->arrayenabled = false;
2117 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
2118 }
2119 }
2120 break;
2121 }
2122}
2123
2124int R_Mesh_TexBound(unsigned int unitnum, int id)
2125{
2126 gltextureunit_t *unit = gl_state.units + unitnum;
2127 if (unitnum >= MAX_TEXTUREUNITS)
2128 Sys_Error("R_Mesh_TexCoordPointer: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
2129 if (id == GL_TEXTURE_2D)
2130 return unit->t2d;
2131 if (id == GL_TEXTURE_3D)
2132 return unit->t3d;
2133 if (id == GL_TEXTURE_CUBE_MAP)
2134 return unit->tcubemap;
2135 return 0;
2136}
2137
2138void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
2139{
2140 switch(vid.renderpath)
2141 {
2142 case RENDERPATH_GL32:
2143 case RENDERPATH_GLES2:
2144 R_Mesh_TexBind(0, tex);
2146 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
2147 break;
2148 }
2149}
2150
2152{
2153 gltextureunit_t *unit;
2154 unsigned int unitnum;
2155 // unbind the texture from any units it is bound on - this prevents accidental reuse of certain textures whose bindings can linger far too long otherwise (e.g. bouncegrid which is a 3D texture) and confuse the driver later.
2156 for (unitnum = 0; unitnum < MAX_TEXTUREUNITS; unitnum++)
2157 {
2158 unit = gl_state.units + unitnum;
2159 if (unit->texture && unit->texture->texnum == texnum)
2160 R_Mesh_TexBind(unitnum, NULL);
2161 }
2162}
2163
2164void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
2165{
2166 gltextureunit_t *unit = gl_state.units + unitnum;
2167 int texnum;
2168 if (unitnum >= MAX_TEXTUREUNITS)
2169 Sys_Error("R_Mesh_TexBind: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
2170 switch(vid.renderpath)
2171 {
2172 case RENDERPATH_GL32:
2173 case RENDERPATH_GLES2:
2174 if (tex)
2175 {
2176 texnum = R_GetTexture(tex);
2177 switch (tex->gltexturetypeenum)
2178 {
2179 case GL_TEXTURE_2D:
2180 if (unit->t2d != texnum) { GL_ActiveTexture(unitnum);qglBindTexture(GL_TEXTURE_2D, texnum); CHECKGLERROR unit->t2d = texnum; }
2181 if (unit->t3d) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_3D, 0); CHECKGLERROR unit->t3d = 0; }
2182 if (unit->tcubemap) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); CHECKGLERROR unit->tcubemap = 0; }
2183 break;
2184 case GL_TEXTURE_3D:
2185 if (unit->t2d) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_2D, 0); CHECKGLERROR unit->t2d = 0; }
2186 if (unit->t3d != texnum) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_3D, texnum); CHECKGLERROR unit->t3d = texnum; }
2187 if (unit->tcubemap) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); CHECKGLERROR unit->tcubemap = 0; }
2188 break;
2190 if (unit->t2d) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_2D, 0); CHECKGLERROR unit->t2d = 0; }
2191 if (unit->t3d) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_3D, 0); CHECKGLERROR unit->t3d = 0; }
2192 if (unit->tcubemap != texnum) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_CUBE_MAP, texnum); CHECKGLERROR unit->tcubemap = texnum; }
2193 break;
2194 }
2195 }
2196 else
2197 {
2198 if (unit->t2d) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_2D, 0); CHECKGLERROR unit->t2d = 0; }
2199 if (unit->t3d) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_3D, 0); CHECKGLERROR unit->t3d = 0; }
2200 if (unit->tcubemap) { GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); CHECKGLERROR unit->tcubemap = 0; }
2201 }
2202 }
2203 unit->texture = tex;
2204}
2205
2207{
2208#if 0
2209 unsigned int unitnum;
2210
2212
2213 for (unitnum = 0;unitnum < MAX_TEXTUREUNITS;unitnum++)
2214 R_Mesh_TexBind(unitnum, NULL);
2215#endif
2216}
2217
2218void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
2219{
2220 // upload temporary vertexbuffer for this rendering
2221 if (!vertexbuffer)
2222 vertexbuffer = R_BufferData_Store(numvertices * sizeof(float[3]), (void *)vertex3f, R_BUFFERDATA_VERTEX, &bufferoffset);
2223 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(float[3]) , vertex3f , vertexbuffer , bufferoffset );
2224 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(float[4]) , NULL , NULL , 0 );
2225 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2226 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2227 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2228 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2229 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2230 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2231 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2232 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2233}
2234
2235void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
2236{
2237 r_meshbuffer_t *buffer_vertex3f = NULL;
2238 r_meshbuffer_t *buffer_color4f = NULL;
2239 r_meshbuffer_t *buffer_texcoord2f = NULL;
2240 int bufferoffset_vertex3f = 0;
2241 int bufferoffset_color4f = 0;
2242 int bufferoffset_texcoord2f = 0;
2243 if (color4f)
2244 buffer_color4f = R_BufferData_Store(numvertices * sizeof(float[4]), color4f , R_BUFFERDATA_VERTEX, &bufferoffset_color4f );
2245 if (vertex3f)
2246 buffer_vertex3f = R_BufferData_Store(numvertices * sizeof(float[3]), vertex3f , R_BUFFERDATA_VERTEX, &bufferoffset_vertex3f );
2247 if (texcoord2f)
2248 buffer_texcoord2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoord2f, R_BUFFERDATA_VERTEX, &bufferoffset_texcoord2f);
2249 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(float[3]) , vertex3f , buffer_vertex3f , bufferoffset_vertex3f );
2250 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(float[4]) , color4f , buffer_color4f , bufferoffset_color4f );
2251 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(float[2]) , texcoord2f , buffer_texcoord2f , bufferoffset_texcoord2f );
2252 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2253 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2254 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2255 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2256 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2257 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2258 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2259}
2260
2261void 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)
2262{
2263 r_meshbuffer_t *buffer_vertex3f = NULL;
2264 r_meshbuffer_t *buffer_color4f = NULL;
2265 r_meshbuffer_t *buffer_texcoordtexture2f = NULL;
2266 r_meshbuffer_t *buffer_svector3f = NULL;
2267 r_meshbuffer_t *buffer_tvector3f = NULL;
2268 r_meshbuffer_t *buffer_normal3f = NULL;
2269 r_meshbuffer_t *buffer_texcoordlightmap2f = NULL;
2270 int bufferoffset_vertex3f = 0;
2271 int bufferoffset_color4f = 0;
2272 int bufferoffset_texcoordtexture2f = 0;
2273 int bufferoffset_svector3f = 0;
2274 int bufferoffset_tvector3f = 0;
2275 int bufferoffset_normal3f = 0;
2276 int bufferoffset_texcoordlightmap2f = 0;
2277 if (color4f)
2278 buffer_color4f = R_BufferData_Store(numvertices * sizeof(float[4]), color4f , R_BUFFERDATA_VERTEX, &bufferoffset_color4f );
2279 if (vertex3f)
2280 buffer_vertex3f = R_BufferData_Store(numvertices * sizeof(float[3]), vertex3f , R_BUFFERDATA_VERTEX, &bufferoffset_vertex3f );
2281 if (svector3f)
2282 buffer_svector3f = R_BufferData_Store(numvertices * sizeof(float[3]), svector3f , R_BUFFERDATA_VERTEX, &bufferoffset_svector3f );
2283 if (tvector3f)
2284 buffer_tvector3f = R_BufferData_Store(numvertices * sizeof(float[3]), tvector3f , R_BUFFERDATA_VERTEX, &bufferoffset_tvector3f );
2285 if (normal3f)
2286 buffer_normal3f = R_BufferData_Store(numvertices * sizeof(float[3]), normal3f , R_BUFFERDATA_VERTEX, &bufferoffset_normal3f );
2287 if (texcoordtexture2f)
2288 buffer_texcoordtexture2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoordtexture2f , R_BUFFERDATA_VERTEX, &bufferoffset_texcoordtexture2f );
2289 if (texcoordlightmap2f)
2290 buffer_texcoordlightmap2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoordlightmap2f, R_BUFFERDATA_VERTEX, &bufferoffset_texcoordlightmap2f);
2291 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(float[3]) , vertex3f , buffer_vertex3f , bufferoffset_vertex3f );
2292 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(float[4]) , color4f , buffer_color4f , bufferoffset_color4f );
2293 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(float[2]) , texcoordtexture2f , buffer_texcoordtexture2f , bufferoffset_texcoordtexture2f );
2294 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(float[3]) , svector3f , buffer_svector3f , bufferoffset_svector3f );
2295 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(float[3]) , tvector3f , buffer_tvector3f , bufferoffset_tvector3f );
2296 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(float[3]) , normal3f , buffer_normal3f , bufferoffset_normal3f );
2297 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(float[2]) , texcoordlightmap2f, buffer_texcoordlightmap2f, bufferoffset_texcoordlightmap2f);
2298 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2299 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2300 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2301}
2302
2304{
2306 if(negated)
2307 {
2308 switch(vid.renderpath)
2309 {
2310 case RENDERPATH_GL32:
2311 case RENDERPATH_GLES2:
2312 qglBlendEquation(GL_FUNC_REVERSE_SUBTRACT);CHECKGLERROR
2313 break;
2314 }
2315 }
2316 else
2317 {
2318 switch(vid.renderpath)
2319 {
2320 case RENDERPATH_GL32:
2321 case RENDERPATH_GLES2:
2322 qglBlendEquation(GL_FUNC_ADD);CHECKGLERROR
2323 break;
2324 }
2325 }
2326}
client_static_t cls
Definition cl_main.c:116
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
Definition cmd.c:1661
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define CON_WARN
Definition console.h:101
#define CON_ERROR
Definition console.h:102
vector size
vector mins
vector maxs
void Cvar_SetValueQuick(cvar_t *var, float value)
Definition cvar.c:473
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
static int(ZEXPORT *qz_inflate)(z_stream *strm
unsigned short quadelement3s[QUADELEMENTS_MAXQUADS *6]
Definition gl_backend.c:243
float rectviewmatrix[6][16]
Definition gl_backend.c:802
void R_Mesh_Start(void)
void GL_ActiveTexture(unsigned int num)
static void gl_backend_devicelost(void)
Definition gl_backend.c:304
static int bboxedges[12][2]
Definition gl_backend.c:411
void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
float gl_modelviewprojection16f[16]
Definition gl_backend.c:30
matrix4x4_t gl_modelmatrix
Definition gl_backend.c:24
void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
void GL_BlendEquationSubtract(qbool negated)
void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
cvar_t r_renderview
Definition gl_backend.c:12
void GL_CullFace(int state)
void GL_ColorMask(int r, int g, int b, int a)
unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2) *3]
Definition gl_backend.c:241
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)
static void GL_Backend_ResetState(void)
cvar_t r_render
Definition gl_backend.c:11
void GL_DepthMask(int state)
cvar_t v_flipped
Definition gl_backend.c:20
static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
Definition gl_backend.c:552
static void GL_VBOStats_f(cmd_state_t *cmd)
Definition gl_backend.c:245
void R_GetViewport(r_viewport_t *v)
Definition gl_backend.c:922
void SCR_ScreenShot_f(cmd_state_t *cmd)
int R_Mesh_TexBound(unsigned int unitnum, int id)
void GL_Backend_FreeProgram(unsigned int prog)
matrix4x4_t gl_modelviewprojectionmatrix
Definition gl_backend.c:28
static void gl_backend_shutdown(void)
Definition gl_backend.c:281
void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
void R_Mesh_Finish(void)
static void GL_BindVBO(int bufferobject)
Definition gl_backend.c:927
#define BACKENDACTIVECHECK
Definition gl_backend.c:110
int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2) *3]
Definition gl_backend.c:240
void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
Definition gl_backend.c:843
void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
void R_SetStencil(qbool enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
void GL_DepthFunc(int state)
void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, int element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, int element3s_bufferoffset)
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, int offsetx, int offsety)
Definition gl_backend.c:869
static void gl_backend_start(void)
Definition gl_backend.c:252
void GL_Mesh_ListVBOs(qbool printeach)
void R_Mesh_ClearBindingsForTexture(int texnum)
void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
Definition gl_backend.c:383
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)
Definition gl_backend.c:677
void GL_DepthTest(int state)
void GL_DepthRange(float nearfrac, float farfrac)
void R_Viewport_InitOrtho3D(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)
Definition gl_backend.c:635
void GL_Finish(void)
Definition gl_backend.c:399
cvar_t gl_printcheckerror
Definition gl_backend.c:9
void R_Mesh_SetRenderTargets(int fbo)
int quadelement3i[QUADELEMENTS_MAXQUADS *6]
Definition gl_backend.c:242
qbool v_flipped_state
Definition gl_backend.c:21
void GL_PolygonOffset(float planeoffset, float depthoffset)
r_meshbuffer_t * R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qbool isindexbuffer, qbool isuniformbuffer, qbool isdynamic, qbool isindex16)
int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
Definition gl_backend.c:960
static void gl_backend_devicerestored(void)
Definition gl_backend.c:329
cvar_t gl_polyblend
Definition gl_backend.c:17
static void GLAPIENTRY GL_DebugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const GLvoid *userParam)
Definition gl_backend.c:80
float cubeviewmatrix[6][16]
Definition gl_backend.c:762
void R_SetViewport(const r_viewport_t *v)
Definition gl_backend.c:897
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)
Definition gl_backend.c:587
matrix4x4_t gl_modelviewmatrix
Definition gl_backend.c:26
void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
cvar_t gl_debug
Definition gl_backend.c:7
void R_Mesh_ResetTextureState(void)
matrix4x4_t gl_projectionmatrix
Definition gl_backend.c:27
void GL_Color(float cr, float cg, float cb, float ca)
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)
static gl_state_t gl_state
Definition gl_backend.c:183
static void GL_BindUBO(int bufferobject)
Definition gl_backend.c:947
cvar_t r_waterwarp
Definition gl_backend.c:13
void GL_BlendFunc(int blendfunc1, int blendfunc2)
static void gl_backend_newmap(void)
Definition gl_backend.c:300
qbool R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
Definition gl_backend.c:430
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)
Definition gl_backend.c:719
void GL_AlphaToCoverage(qbool state)
void GL_Scissor(int x, int y, int width, int height)
float gl_modelview16f[16]
Definition gl_backend.c:29
void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
qbool gl_modelmatrixchanged
Definition gl_backend.c:31
static const GLuint drawbuffers[4]
Definition gl_backend.c:959
void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size, qbool subdata, size_t offset)
static const char * buffertypename[R_BUFFERDATA_COUNT]
static void GL_BindEBO(int bufferobject)
Definition gl_backend.c:937
matrix4x4_t gl_viewmatrix
Definition gl_backend.c:25
cvar_t gl_paranoid
Definition gl_backend.c:8
r_viewport_t gl_viewport
Definition gl_backend.c:23
static qbool GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
void R_Mesh_DestroyFramebufferObject(int fbo)
void GL_SetMirrorState(qbool state)
void GL_ScissorTest(int state)
void gl_backend_init(void)
Definition gl_backend.c:339
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)
void GL_CaptureVideo_BeginVideo(void)
void R_EntityMatrix(const matrix4x4_t *matrix)
Definition gl_rmain.c:4417
void GL_CaptureVideo_EndVideo(void)
void GL_CaptureVideo_VideoFrame(int newframestepframenum)
#define QUADELEMENTS_MAXQUADS
Definition gl_backend.h:18
#define POLYGONELEMENTS_MAXPOINTS
Definition gl_backend.h:15
mempool_t * r_main_mempool
Definition gl_rmain.c:42
r_refdef_t r_refdef
Definition gl_rmain.c:57
r_meshbuffer_t * R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
request space in a vertex/index/uniform buffer for the chosen data, returns the buffer pointer and of...
Definition gl_rmain.c:3707
unsigned char GLubyte
Definition glquake.h:52
#define GL_TRUE
Definition glquake.h:116
#define GL_INVALID_VALUE
Definition glquake.h:144
GLsizei GLsizei GLchar * source
Definition glquake.h:704
unsigned int GLuint
Definition glquake.h:54
#define GL_NONE
Definition glquake.h:127
GLenum GLsizei width
Definition glquake.h:622
GLenum GLsizei GLsizei height
Definition glquake.h:622
#define CHECKGLERROR
Definition glquake.h:1059
GLint GLenum GLsizei GLsizei GLint border
Definition glquake.h:647
GLfloat GLfloat GLfloat v2
Definition glquake.h:747
#define GL_TEXTURE0
Definition glquake.h:214
#define GL_FRAGMENT_SHADER
Definition glquake.h:510
#define GL_UNIFORM_BUFFER
Definition glquake.h:413
int GLint
Definition glquake.h:51
GLvoid *GLAPIENTRY * qglMapBuffer(GLenum target, GLenum access)
#define GL_TEXTURE_CUBE_MAP
Definition glquake.h:262
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
Definition glquake.h:609
#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB
Definition glquake.h:580
#define GL_UNSIGNED_SHORT
Definition glquake.h:121
GLuint buffer
Definition glquake.h:630
#define GL_DYNAMIC_READ
Definition glquake.h:307
#define GL_DEBUG_TYPE_PORTABILITY_ARB
Definition glquake.h:581
GLenum GLuint GLenum GLsizei length
Definition glquake.h:657
#define GL_DEBUG_SOURCE_APPLICATION_ARB
Definition glquake.h:576
#define GL_DEPTH_TEST
Definition glquake.h:69
const GLdouble * v
Definition glquake.h:762
#define GL_LINEAR
Definition glquake.h:101
#define GL_STENCIL_TEST
Definition glquake.h:173
#define GL_COLOR_ATTACHMENT0
Definition glquake.h:1005
unsigned char GLboolean
Definition glquake.h:46
#define GL_INVALID_OPERATION
Definition glquake.h:146
GLint GLenum GLint GLint y
Definition glquake.h:651
#define GL_BGRA
Definition glquake.h:547
GLenum GLvoid ** pointer
Definition glquake.h:714
#define GL_TRIANGLES
Definition glquake.h:113
#define GL_COLOR_ATTACHMENT2
Definition glquake.h:1007
#define GL_DEBUG_TYPE_PERFORMANCE_ARB
Definition glquake.h:582
GLint GLenum GLboolean GLsizei stride
Definition glquake.h:797
#define GL_BACK
Definition glquake.h:133
#define GL_STACK_OVERFLOW
Definition glquake.h:147
#define GL_UNSIGNED_INT
Definition glquake.h:123
#define GL_TEXTURE_3D
Definition glquake.h:1035
#define GL_FLOAT
Definition glquake.h:124
#define GL_COLOR_ATTACHMENT1
Definition glquake.h:1006
#define GL_ARRAY_BUFFER
Definition glquake.h:286
#define GL_ZERO
Definition glquake.h:73
#define GL_DEBUG_SEVERITY_HIGH_ARB
Definition glquake.h:587
GLint GLenum GLint x
Definition glquake.h:651
#define GL_DEBUG_SOURCE_API_ARB
Definition glquake.h:572
#define GL_COLOR_ATTACHMENT3
Definition glquake.h:1008
#define GL_FRAMEBUFFER_COMPLETE
Definition glquake.h:358
#define GL_DRAW_FRAMEBUFFER
Definition glquake.h:321
#define GL_UNSIGNED_BYTE
Definition glquake.h:119
GLsizeiptr const GLvoid * data
Definition glquake.h:639
#define GL_PIXEL_PACK_BUFFER
Definition glquake.h:317
#define GL_FUNC_REVERSE_SUBTRACT
Definition glquake.h:284
void GLvoid
Definition glquake.h:48
#define GL_DEBUG_SEVERITY_LOW_ARB
Definition glquake.h:589
#define GL_RENDERBUFFER
Definition glquake.h:322
#define GL_COMPILE_STATUS
Definition glquake.h:449
#define GL_LEQUAL
Definition glquake.h:162
#define GL_CULL_FACE
Definition glquake.h:70
unsigned int GLenum
Definition glquake.h:45
int GLsizei
Definition glquake.h:55
#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB
Definition glquake.h:579
#define GL_COLOR_BUFFER_BIT
Definition glquake.h:171
#define GL_SAMPLE_ALPHA_TO_COVERAGE
Definition glquake.h:550
GLenum zfail
Definition glquake.h:731
GLuint GLuint GLintptr offset
Definition glquake.h:632
#define GL_FRAMEBUFFER
Definition glquake.h:319
#define GL_RGBA
Definition glquake.h:155
#define GL_BLEND
Definition glquake.h:71
ptrdiff_t GLsizeiptr
Definition glquake.h:62
#define GL_ONE
Definition glquake.h:74
#define GLAPIENTRY
Definition glquake.h:42
#define GL_STREAM_DRAW
Definition glquake.h:300
#define GL_DEBUG_TYPE_ERROR_ARB
Definition glquake.h:578
#define GL_DONT_CARE
Definition glquake.h:66
#define GL_INVALID_FRAMEBUFFER_OPERATION
Definition glquake.h:150
#define GL_FRAMEBUFFER_BINDING
Definition glquake.h:366
#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB
Definition glquake.h:575
GLenum GLenum severity
Definition glquake.h:656
#define GL_READ_FRAMEBUFFER
Definition glquake.h:320
GLfloat GLfloat GLfloat GLfloat v3
Definition glquake.h:751
#define GL_STATIC_DRAW
Definition glquake.h:303
#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB
Definition glquake.h:573
#define GL_FALSE
Definition glquake.h:115
#define GL_SCISSOR_TEST
Definition glquake.h:273
#define GL_STENCIL_BUFFER_BIT
Definition glquake.h:170
#define GL_DEBUG_TYPE_OTHER_ARB
Definition glquake.h:583
GLfloat units
Definition glquake.h:723
#define GL_DEBUG_SOURCE_OTHER_ARB
Definition glquake.h:577
const GLvoid * userParam
Definition glquake.h:655
#define GL_DEPTH_ATTACHMENT
Definition glquake.h:354
const GLchar * name
Definition glquake.h:601
#define GL_VERTEX_SHADER
Definition glquake.h:483
#define GL_ELEMENT_ARRAY_BUFFER
Definition glquake.h:287
#define GL_OUT_OF_MEMORY
Definition glquake.h:149
#define GL_TEXTURE_2D
Definition glquake.h:89
#define GL_FRONT
Definition glquake.h:132
#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
Definition glquake.h:568
#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB
Definition glquake.h:574
#define GL_LINK_STATUS
Definition glquake.h:450
#define GL_STENCIL_ATTACHMENT
Definition glquake.h:355
#define GL_DEPTH_BUFFER_BIT
Definition glquake.h:169
#define GL_INVALID_ENUM
Definition glquake.h:145
#define GL_STACK_UNDERFLOW
Definition glquake.h:148
#define GL_FUNC_ADD
Definition glquake.h:278
GLenum GLenum zpass
Definition glquake.h:731
char GLchar
Definition glquake.h:60
#define GL_DEBUG_SEVERITY_MEDIUM_ARB
Definition glquake.h:588
#define GL_READ_ONLY
Definition glquake.h:309
GLenum type
Definition glquake.h:656
cvar_t developer
Definition host.c:48
cvar_t developer_extra
Definition host.c:49
#define VectorLerp(v1, lerp, v2, out)
Definition mathlib.h:120
#define VectorNegate(a, b)
Definition mathlib.h:95
#define BoxesOverlap(a, b, c, d)
Definition mathlib.h:122
#define Vector4Set(vec, r, g, b, a)
Definition mathlib.h:86
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
#define DotProduct(a, b)
Definition mathlib.h:98
#define DotProduct4(a, b)
Definition mathlib.h:81
#define VectorCopy(in, out)
Definition mathlib.h:101
#define VectorScale(in, scale, out)
Definition mathlib.h:111
void Matrix4x4_Concat(matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2)
Definition matrixlib.c:83
void Matrix4x4_Transform(const matrix4x4_t *in, const float v[3], float out[3])
Definition matrixlib.c:1657
void Matrix4x4_Transform4(const matrix4x4_t *in, const float v[4], float out[4])
Definition matrixlib.c:1670
void Matrix4x4_Transform3x3(const matrix4x4_t *in, const float v[3], float out[3])
Definition matrixlib.c:1685
void Matrix4x4_FromArrayFloatGL(matrix4x4_t *out, const float in[16])
Definition matrixlib.c:1204
int Matrix4x4_Invert_Full(matrix4x4_t *out, const matrix4x4_t *in1)
Definition matrixlib.c:145
void Matrix4x4_CreateRotate(matrix4x4_t *out, double angle, double x, double y, double z)
Definition matrixlib.c:623
void Matrix4x4_ConcatRotate(matrix4x4_t *out, double angle, double x, double y, double z)
Definition matrixlib.c:1766
void cmd(string command,...)
string message
Definition progsdefs.qc:205
prvm_eval_t * src
int i
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
vec_t vec4_t[4]
Definition qtypes.h:72
void R_RegisterModule(const char *name, void(*start)(void), void(*shutdown)(void), void(*newmap)(void), void(*devicelost)(void), void(*devicerestored)(void))
Definition r_modules.c:25
@ r_stat_vertexbufferuploadsize
Definition r_stats.h:50
@ r_stat_vertexbufferuploadcount
Definition r_stats.h:49
@ r_stat_draws_vertices
Definition r_stats.h:25
@ r_stat_indexbufferuploadcount
Definition r_stats.h:47
@ r_stat_indexbufferuploadsize
Definition r_stats.h:48
@ r_stat_draws
Definition r_stats.h:24
@ r_stat_draws_elements
Definition r_stats.h:26
#define R_GetTexture(rt)
Definition r_textures.h:214
@ R_BUFFERDATA_VERTEX
Definition render.h:525
@ R_BUFFERDATA_COUNT
uniform buffer
Definition render.h:529
@ R_BUFFERDATA_UNIFORM
index buffer - 32bit (because D3D cares)
Definition render.h:528
@ R_BUFFERDATA_INDEX32
index buffer - 16bit (because D3D cares)
Definition render.h:527
@ R_BUFFERDATA_INDEX16
vertex buffer
Definition render.h:526
@ GLSLATTRIB_TEXCOORD4
Definition render.h:35
@ GLSLATTRIB_TEXCOORD3
Definition render.h:34
@ GLSLATTRIB_TEXCOORD7
Definition render.h:38
@ GLSLATTRIB_COLOR
Definition render.h:30
@ GLSLATTRIB_TEXCOORD6
Definition render.h:37
@ GLSLATTRIB_TEXCOORD1
Definition render.h:32
@ GLSLATTRIB_TEXCOORD5
Definition render.h:36
@ GLSLATTRIB_TEXCOORD0
Definition render.h:31
@ GLSLATTRIB_POSITION
Definition render.h:29
@ GLSLATTRIB_TEXCOORD2
Definition render.h:33
@ R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP
Definition render.h:232
@ R_VIEWPORTTYPE_ORTHO
Definition render.h:230
@ R_VIEWPORTTYPE_PERSPECTIVECUBESIDE
Definition render.h:233
@ R_VIEWPORTTYPE_PERSPECTIVE
Definition render.h:231
dp_FragColor r
dp_FragColor g
precision highp float
Definition shader_glsl.h:53
float f
vec3 y2
vec3 x2
vec3 normal
dp_FragColor b
vec3 x1
ret a
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127
Definition cvar.h:66
int integer
Definition cvar.h:73
int defaultframebufferobject
Definition gl_backend.c:153
int scissortest
Definition gl_backend.c:143
float color4f[4]
Definition gl_backend.c:146
qbool pointer_color_enabled
Definition gl_backend.c:154
memexpandablearray_t meshbufferarray
Definition gl_backend.c:177
int elementbufferobject
Definition gl_backend.c:150
unsigned int defaultvao
Definition gl_backend.c:157
qbool blend
Definition gl_backend.c:135
const r_meshbuffer_t * pointer_color_vertexbuffer
Definition gl_backend.c:170
float depthrange[2]
Definition gl_backend.c:140
size_t pointer_color_stride
Definition gl_backend.c:168
int uniformbufferobject
Definition gl_backend.c:151
int pointer_color_gltype
Definition gl_backend.c:167
int pointer_vertex_gltype
Definition gl_backend.c:160
unsigned int unit
Definition gl_backend.c:144
int cullfaceenable
Definition gl_backend.c:132
void * preparevertices_tempdata
Definition gl_backend.c:173
int lockrange_count
Definition gl_backend.c:148
int preparevertices_numvertices
Definition gl_backend.c:175
int lockrange_first
Definition gl_backend.c:147
size_t preparevertices_tempdatamaxsize
Definition gl_backend.c:174
qbool active
Definition gl_backend.c:179
const void * pointer_vertex_pointer
Definition gl_backend.c:162
GLboolean depthmask
Definition gl_backend.c:136
int pointer_color_components
Definition gl_backend.c:166
qbool alphatocoverage
Definition gl_backend.c:142
gltextureunit_t units[MAX_TEXTUREUNITS]
Definition gl_backend.c:145
const void * pointer_color_pointer
Definition gl_backend.c:169
int vertexbufferobject
Definition gl_backend.c:149
float polygonoffset[2]
Definition gl_backend.c:141
const r_meshbuffer_t * pointer_vertex_vertexbuffer
Definition gl_backend.c:163
size_t pointer_vertex_stride
Definition gl_backend.c:161
int pointer_vertex_components
Definition gl_backend.c:159
size_t pointer_vertex_offset
Definition gl_backend.c:164
int framebufferobject
Definition gl_backend.c:152
size_t pointer_color_offset
Definition gl_backend.c:171
size_t pointer_texcoord_offset
Definition gl_backend.c:121
rtexture_t * texture
Definition gl_backend.c:123
const void * pointer_texcoord_pointer
Definition gl_backend.c:119
int pointer_texcoord_gltype
Definition gl_backend.c:117
size_t pointer_texcoord_stride
Definition gl_backend.c:118
int pointer_texcoord_components
Definition gl_backend.c:116
const r_meshbuffer_t * pointer_texcoord_vertexbuffer
Definition gl_backend.c:120
vec3_t normal
Definition model_brush.h:59
vec_t dist
Definition model_brush.h:60
int draw2dstage
Definition render.h:452
r_refdef_view_t view
Definition render.h:406
int stats[r_stat_count]
Definition render.h:466
vec3_t origin
Definition render.h:267
mplane_t frustum[6]
Definition render.h:273
r_viewport_t viewport
note: if r_viewscale is used, the viewport.width and viewport.height may be less than width and heigh...
Definition render.h:296
int renderbuffernum
Definition r_textures.h:111
int gltexturetypeenum
Definition r_textures.h:114
qbool glisdepthstencil
Definition r_textures.h:113
int width
Definition vid.h:60
int height
Definition vid.h:61
qbool arb_debug_output
Definition vid.h:51
renderpath_t renderpath
Definition vid.h:80
qbool stencil
Definition vid.h:74
viddef_support_t support
Definition vid.h:89
viddef_mode_t mode
currently active video mode
Definition vid.h:73
static vec3_t right
Definition sv_user.c:305
void Sys_Error(const char *error,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
Causes the entire program to exit ASAP.
Definition sys_shared.c:724
@ RENDERPATH_GLES2
Definition vid.h:38
@ RENDERPATH_GL32
Definition vid.h:37
viddef_t vid
global video state
Definition vid_shared.c:64
#define MAX_TEXTUREUNITS
Definition vid.h:33
size_t Mem_ExpandableArray_IndexRange(const memexpandablearray_t *l)
Definition zone.c:763
void Mem_ExpandableArray_NewArray(memexpandablearray_t *l, mempool_t *mempool, size_t recordsize, int numrecordsperarray)
Definition zone.c:675
void Mem_ExpandableArray_FreeRecord(memexpandablearray_t *l, void *record)
Definition zone.c:743
void * Mem_ExpandableArray_AllocRecord(memexpandablearray_t *l)
Definition zone.c:695
void * Mem_ExpandableArray_RecordAtIndex(const memexpandablearray_t *l, size_t index)
Definition zone.c:780
void Mem_ExpandableArray_FreeArray(memexpandablearray_t *l)
Definition zone.c:683
#define Mem_Free(mem)
Definition zone.h:96