LCOV - code coverage report
Current view: top level - shared - glemu.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 0.3 % 369 1
Test Date: 2026-04-10 06:41:26 Functions: 1.6 % 61 1

            Line data    Source code
       1              : /**
       2              :  * @brief GL immediate mode EMUlation layer (glemu).
       3              :  *
       4              :  * This file replicates some of the functionality of the long since removed glBegin/glEnd
       5              :  * features from extremely outdated versions of OpenGL.
       6              :  */
       7              : 
       8              : #include <cstring>
       9              : #include <algorithm>
      10              : #include <vector>
      11              : #include <string>
      12              : #include <cmath>
      13              : 
      14              : #include <SDL.h>
      15              : 
      16              : #include <GL/glew.h>
      17              : #include <GL/gl.h>
      18              : 
      19              : #include <zlib.h>
      20              : 
      21              : #include "../libprimis-headers/tools.h"
      22              : #include "../libprimis-headers/geom.h"
      23              : 
      24              : #include "glemu.h"
      25              : #include "glexts.h"
      26              : namespace gle
      27              : {
      28              :     struct attribinfo final
      29              :     {
      30              :         int type, size, formatsize, offset;
      31              :         GLenum format;
      32              : 
      33           16 :         attribinfo() : type(0), size(0), formatsize(0), offset(0), format(GL_FALSE) {}
      34              : 
      35              :         bool operator==(const attribinfo &a) const
      36              :         {
      37              :             return type == a.type && size == a.size && format == a.format && offset == a.offset;
      38              :         }
      39            0 :         bool operator!=(const attribinfo &a) const
      40              :         {
      41            0 :             return type != a.type || size != a.size || format != a.format || offset != a.offset;
      42              :         }
      43              :     };
      44              :     ucharbuf attribbuf;
      45              :     static uchar *attribdata;
      46              :     static attribinfo attribdefs[Attribute_NumAttributes], lastattribs[Attribute_NumAttributes];
      47              :     static int enabled = 0;
      48              :     static int numattribs = 0,
      49              :                attribmask = 0,
      50              :                numlastattribs = 0,
      51              :                lastattribmask = 0,
      52              :                vertexsize = 0,
      53              :                lastvertexsize = 0;
      54              :     static GLenum primtype = GL_TRIANGLES;
      55              :     static uchar *lastbuf = nullptr;
      56              :     static bool changedattribs = false;
      57              :     static std::vector<GLint> multidrawstart;
      58              :     static std::vector<GLsizei> multidrawcount;
      59              : 
      60              :     static constexpr int maxquads = (0x10000/4); //65635/4 = 16384
      61              :     static GLuint quadindexes = 0;
      62              :     static bool quadsenabled = false;
      63              : 
      64              :     static constexpr int maxvbosize = (1024*1024*4);
      65              :     static GLuint vbo = 0;
      66              :     static int vbooffset = maxvbosize;
      67              : 
      68              :     static GLuint defaultvao = 0;
      69              : 
      70            0 :     void enablequads()
      71              :     {
      72            0 :         quadsenabled = true;
      73            0 :         if(quadindexes)
      74              :         {
      75            0 :             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadindexes);
      76            0 :             return;
      77              :         }
      78              : 
      79            0 :         glGenBuffers(1, &quadindexes);
      80            0 :         ushort *data = new ushort[maxquads*6],
      81            0 :                *dst = data;
      82            0 :         for(int idx = 0; idx < maxquads*4; idx += 4, dst += 6)
      83              :         {
      84            0 :             dst[0] = idx;
      85            0 :             dst[1] = idx + 1;
      86            0 :             dst[2] = idx + 2;
      87            0 :             dst[3] = idx + 0;
      88            0 :             dst[4] = idx + 2;
      89            0 :             dst[5] = idx + 3;
      90              :         }
      91            0 :         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadindexes);
      92            0 :         glBufferData(GL_ELEMENT_ARRAY_BUFFER, maxquads*6*sizeof(ushort), data, GL_STATIC_DRAW);
      93            0 :         delete[] data;
      94              :     }
      95              : 
      96            0 :     void disablequads()
      97              :     {
      98            0 :         quadsenabled = false;
      99            0 :         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     100            0 :     }
     101              : 
     102            0 :     void drawquads(int offset, int count)
     103              :     {
     104            0 :         if(count <= 0)
     105              :         {
     106            0 :             return;
     107              :         }
     108            0 :         if(offset + count > maxquads)
     109              :         {
     110            0 :             if(offset >= maxquads)
     111              :             {
     112            0 :                 return;
     113              :             }
     114            0 :             count = maxquads - offset;
     115              :         }
     116            0 :         glDrawRangeElements(GL_TRIANGLES, offset*4, (offset + count)*4-1, count*6, GL_UNSIGNED_SHORT, static_cast<ushort *>(nullptr) + offset*6);
     117              :     }
     118              : 
     119            0 :     static void defattrib(int type, int size, int format)
     120              :     {
     121            0 :         if(type == Attribute_Vertex)
     122              :         {
     123            0 :             numattribs = attribmask = 0;
     124            0 :             vertexsize = 0;
     125              :         }
     126            0 :         changedattribs = true;
     127            0 :         attribmask |= 1<<type;
     128            0 :         attribinfo &a = attribdefs[numattribs++];
     129            0 :         a.type = type;
     130            0 :         a.size = size;
     131            0 :         a.format = format;
     132            0 :         switch(format)
     133              :         {
     134            0 :             case 'B':
     135              :             case GL_UNSIGNED_BYTE:
     136              :             {
     137            0 :                 a.formatsize = 1;
     138            0 :                 a.format = GL_UNSIGNED_BYTE;
     139            0 :                 break;
     140              :             }
     141            0 :             case 'b':
     142              :             case GL_BYTE:
     143              :             {
     144            0 :                 a.formatsize = 1;
     145            0 :                 a.format = GL_BYTE;
     146            0 :                 break;
     147              :             }
     148            0 :             case 'S':
     149              :             case GL_UNSIGNED_SHORT:
     150              :             {
     151            0 :                 a.formatsize = 2;
     152            0 :                 a.format = GL_UNSIGNED_SHORT;
     153            0 :                 break;
     154              :             }
     155            0 :             case 's':
     156              :             case GL_SHORT:
     157              :             {
     158            0 :                 a.formatsize = 2;
     159            0 :                 a.format = GL_SHORT;
     160            0 :                 break;
     161              :             }
     162            0 :             case 'I':
     163              :             case GL_UNSIGNED_INT:
     164              :             {
     165            0 :                 a.formatsize = 4;
     166            0 :                 a.format = GL_UNSIGNED_INT;
     167            0 :                 break;
     168              :             }
     169            0 :             case 'i':
     170              :             case GL_INT:
     171              :             {
     172            0 :                 a.formatsize = 4;
     173            0 :                 a.format = GL_INT;
     174            0 :                 break;
     175              :             }
     176            0 :             case 'f':
     177              :             case GL_FLOAT:
     178              :             {
     179            0 :                 a.formatsize = 4;
     180            0 :                 a.format = GL_FLOAT;
     181            0 :                 break;
     182              :             }
     183            0 :             case 'd':
     184              :             case GL_DOUBLE:
     185              :             {
     186            0 :                 a.formatsize = 8;
     187            0 :                 a.format = GL_DOUBLE;
     188            0 :                 break;
     189              :             }
     190            0 :             default:
     191              :             {
     192            0 :                 a.formatsize = 0;
     193            0 :                 a.format = GL_FALSE;
     194            0 :                 break;
     195              :             }
     196              :         }
     197            0 :         a.formatsize *= size;
     198            0 :         a.offset = vertexsize;
     199            0 :         vertexsize += a.formatsize;
     200            0 :     }
     201              : 
     202            0 :     static void setattrib(const attribinfo &a, uchar *buf)
     203              :     {
     204            0 :         switch(a.type)
     205              :         {
     206            0 :             case Attribute_Vertex:
     207              :             case Attribute_TexCoord0:
     208              :             case Attribute_TexCoord1:
     209              :             case Attribute_BoneIndex:
     210              :             {
     211            0 :                 glVertexAttribPointer(a.type, a.size, a.format, GL_FALSE, vertexsize, buf);
     212            0 :                 break;
     213              :             }
     214            0 :             case Attribute_Color:
     215              :             case Attribute_Normal:
     216              :             case Attribute_Tangent:
     217              :             case Attribute_BoneWeight:
     218              :             {
     219            0 :                 glVertexAttribPointer(a.type, a.size, a.format, GL_TRUE, vertexsize, buf);
     220            0 :                 break;
     221              :             }
     222              :         }
     223            0 :         if(!(enabled&(1<<a.type)))
     224              :         {
     225            0 :             glEnableVertexAttribArray(a.type);
     226            0 :             enabled |= 1<<a.type;
     227              :         }
     228            0 :     }
     229              : 
     230            0 :     static void unsetattrib(const attribinfo &a)
     231              :     {
     232            0 :         glDisableVertexAttribArray(a.type);
     233            0 :         enabled &= ~(1<<a.type);
     234            0 :     }
     235              : 
     236            0 :     static void setattribs(uchar *buf)
     237              :     {
     238            0 :         bool forceattribs = numattribs != numlastattribs || vertexsize != lastvertexsize || buf != lastbuf;
     239            0 :         if(forceattribs || changedattribs)
     240              :         {
     241              :             //bitwise AND of attribs
     242            0 :             int diffmask = enabled & lastattribmask & ~attribmask;
     243            0 :             if(diffmask)
     244              :             {
     245            0 :                 for(int i = 0; i < numlastattribs; ++i)
     246              :                 {
     247            0 :                     const attribinfo &a = lastattribs[i];
     248            0 :                     if(diffmask & (1<<a.type))
     249              :                     {
     250            0 :                         unsetattrib(a);
     251              :                     }
     252              :                 }
     253              :             }
     254            0 :             uchar *src = buf;
     255            0 :             for(int i = 0; i < numattribs; ++i)
     256              :             {
     257            0 :                 const attribinfo &a = attribdefs[i];
     258            0 :                 if(forceattribs || a != lastattribs[i])
     259              :                 {
     260            0 :                     setattrib(a, src);
     261            0 :                     lastattribs[i] = a;
     262              :                 }
     263            0 :                 src += a.formatsize;
     264              :             }
     265            0 :             lastbuf = buf;
     266            0 :             numlastattribs = numattribs;
     267            0 :             lastattribmask = attribmask;
     268            0 :             lastvertexsize = vertexsize;
     269            0 :             changedattribs = false;
     270              :         }
     271            0 :     }
     272              : 
     273            0 :     void begin(GLenum mode)
     274              :     {
     275            0 :         primtype = mode;
     276            0 :     }
     277              : 
     278            0 :     void begin(GLenum mode, int numverts)
     279              :     {
     280            0 :         primtype = mode;
     281            0 :         int len = numverts * vertexsize;
     282            0 :         if(vbooffset + len >= maxvbosize)
     283              :         {
     284            0 :             len = std::min<int>(len, maxvbosize);
     285            0 :             if(!vbo)
     286              :             {
     287            0 :                 glGenBuffers(1, &vbo);
     288              :             }
     289            0 :             glBindBuffer(GL_ARRAY_BUFFER, vbo);
     290            0 :             glBufferData(GL_ARRAY_BUFFER, maxvbosize, nullptr, GL_STREAM_DRAW);
     291            0 :             vbooffset = 0;
     292              :         }
     293            0 :         else if(!lastvertexsize)
     294              :         {
     295            0 :             glBindBuffer(GL_ARRAY_BUFFER, vbo);
     296              :         }
     297            0 :         void *buf = glMapBufferRange(GL_ARRAY_BUFFER, vbooffset, len, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
     298            0 :         if(buf)
     299              :         {
     300            0 :             attribbuf.reset(static_cast<uchar *>(buf), len);
     301              :         }
     302            0 :     }
     303              : 
     304            0 :     void multidraw()
     305              :     {
     306            0 :         int start = multidrawstart.size() ? multidrawstart.back() + multidrawcount.back() : 0,
     307            0 :             count = attribbuf.length()/vertexsize - start;
     308            0 :         if(count > 0)
     309              :         {
     310            0 :             multidrawstart.push_back(start);
     311            0 :             multidrawcount.push_back(count);
     312              :         }
     313            0 :     }
     314              : 
     315            0 :     int end()
     316              :     {
     317            0 :         uchar *buf = attribbuf.getbuf();
     318            0 :         if(attribbuf.empty())
     319              :         {
     320            0 :             if(buf != attribdata)
     321              :             {
     322            0 :                 glUnmapBuffer(GL_ARRAY_BUFFER);
     323            0 :                 attribbuf.reset(attribdata, maxvbosize);
     324              :             }
     325            0 :             return 0;
     326              :         }
     327            0 :         int start = 0;
     328            0 :         if(buf == attribdata)
     329              :         {
     330            0 :             if(vbooffset + attribbuf.length() >= maxvbosize)
     331              :             {
     332            0 :                 if(!vbo)
     333              :                 {
     334            0 :                     glGenBuffers(1, &vbo);
     335              :                 }
     336            0 :                 glBindBuffer(GL_ARRAY_BUFFER, vbo);
     337            0 :                 glBufferData(GL_ARRAY_BUFFER, maxvbosize, nullptr, GL_STREAM_DRAW);
     338            0 :                 vbooffset = 0;
     339              :             }
     340            0 :             else if(!lastvertexsize)
     341              :             {
     342            0 :                 glBindBuffer(GL_ARRAY_BUFFER, vbo);
     343              :             }
     344              :             //void pointer warning!
     345            0 :             void *dst = glMapBufferRange(GL_ARRAY_BUFFER, vbooffset, attribbuf.length(), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_RANGE_BIT|GL_MAP_UNSYNCHRONIZED_BIT);
     346            0 :             std::memcpy(dst, attribbuf.getbuf(), attribbuf.length());
     347            0 :             glUnmapBuffer(GL_ARRAY_BUFFER);
     348              :         }
     349              :         else
     350              :         {
     351            0 :             glUnmapBuffer(GL_ARRAY_BUFFER);
     352              :         }
     353            0 :         buf = static_cast<uchar *>(nullptr) + vbooffset;
     354            0 :         if(vertexsize == lastvertexsize && buf >= lastbuf)
     355              :         {
     356            0 :             start = static_cast<int>(buf - lastbuf)/vertexsize;
     357            0 :             buf = lastbuf;
     358              :         }
     359            0 :         vbooffset += attribbuf.length();
     360            0 :         setattribs(buf);
     361            0 :         int numvertexes = attribbuf.length()/vertexsize;
     362            0 :         if(multidrawstart.size())
     363              :         {
     364            0 :             multidraw();
     365            0 :             if(start)
     366              :             {
     367              :                 //offset the buffer indices by start point
     368            0 :                 for(GLint &i : multidrawstart)
     369              :                 {
     370            0 :                     i += start;
     371              :                 }
     372              :             }
     373            0 :             glMultiDrawArrays(primtype, multidrawstart.data(), multidrawcount.data(), multidrawstart.size());
     374            0 :             multidrawstart.clear();
     375            0 :             multidrawcount.clear();
     376              :         }
     377              :         else
     378              :         {
     379            0 :             glDrawArrays(primtype, start, numvertexes);
     380              :         }
     381            0 :         attribbuf.reset(attribdata, maxvbosize);
     382            0 :         return numvertexes;
     383              :     }
     384              : 
     385            0 :     static void forcedisable()
     386              :     {
     387            0 :         for(int i = 0; enabled; i++)
     388              :         {
     389            0 :             if(enabled&(1<<i))
     390              :             {
     391            0 :                 glDisableVertexAttribArray(i);
     392            0 :                 enabled &= ~(1<<i);
     393              :             }
     394              :         }
     395            0 :         numlastattribs = lastattribmask = lastvertexsize = 0;
     396            0 :         lastbuf = nullptr;
     397            0 :         if(quadsenabled)
     398              :         {
     399            0 :             disablequads();
     400              :         }
     401            0 :         glBindBuffer(GL_ARRAY_BUFFER, 0);
     402            0 :     }
     403              : 
     404            0 :     void disable()
     405              :     {
     406            0 :         if(enabled)
     407              :         {
     408            0 :             forcedisable();
     409              :         }
     410            0 :     }
     411              : 
     412            0 :     void setup()
     413              :     {
     414            0 :         if(!defaultvao)
     415              :         {
     416            0 :             glGenVertexArrays(1, &defaultvao);
     417              :         }
     418            0 :         glBindVertexArray(defaultvao);
     419            0 :         attribdata = new uchar[maxvbosize];
     420            0 :         attribbuf.reset(attribdata, maxvbosize);
     421            0 :     }
     422              : 
     423            0 :     void cleanup()
     424              :     {
     425            0 :         disable();
     426            0 :         if(quadindexes)
     427              :         {
     428            0 :             glDeleteBuffers(1, &quadindexes);
     429            0 :             quadindexes = 0;
     430              :         }
     431            0 :         if(vbo)
     432              :         {
     433            0 :             glDeleteBuffers(1, &vbo);
     434            0 :             vbo = 0;
     435              :         }
     436            0 :         vbooffset = maxvbosize;
     437            0 :         if(defaultvao)
     438              :         {
     439            0 :             glDeleteVertexArrays(1, &defaultvao);
     440            0 :             defaultvao = 0;
     441              :         }
     442            0 :     }
     443              : 
     444            0 :     void defvertex(int size, int format)
     445              :     {
     446            0 :         defattrib(Attribute_Vertex, size, format);
     447            0 :     }
     448              : 
     449            0 :     void defcolor(int size, int format)
     450              :     {
     451            0 :         defattrib(Attribute_Color, size, format);
     452            0 :     }
     453              : 
     454            0 :     void deftexcoord0(int size, int format)
     455              :     {
     456            0 :         defattrib(Attribute_TexCoord0, size, format);
     457            0 :     }
     458              : 
     459            0 :     void defnormal(int size, int format)
     460              :     {
     461            0 :         defattrib(Attribute_Normal, size, format);
     462            0 :     }
     463              : 
     464            0 :     void colorf(float x, float y, float z, float w)
     465              :     {
     466            0 :         if(w != 0.0f)
     467              :         {
     468            0 :             glVertexAttrib4f(Attribute_Color, x, y, z, w);
     469              :         }
     470              :         else
     471              :         {
     472            0 :             glVertexAttrib3f(Attribute_Color, x, y, z);
     473              :         }
     474            0 :     }
     475              : 
     476            0 :     void color(const vec &v)
     477              :     {
     478            0 :         glVertexAttrib3fv(Attribute_Color, v.data());
     479            0 :     }
     480              : 
     481            0 :     void color(const vec &v, float w)
     482              :     {
     483            0 :         glVertexAttrib4f(Attribute_Color, v.x, v.y, v.z, w);
     484            0 :     }
     485              : 
     486            0 :     void colorub(uchar x, uchar y, uchar z, uchar w)
     487              :     {
     488            0 :         glVertexAttrib4Nub(Attribute_Color, x, y, z, w);
     489            0 :     }
     490              : 
     491            0 :     void color(const bvec &v, uchar alpha)
     492              :     {
     493            0 :         glVertexAttrib4Nub(Attribute_Color, v.x, v.y, v.z, alpha);
     494            0 :     }
     495              : 
     496            0 :     void enablevertex()
     497              :     {
     498            0 :         disable();
     499            0 :         glEnableVertexAttribArray(Attribute_Vertex);
     500            0 :     }
     501              : 
     502            0 :     void disablevertex()
     503              :     {
     504            0 :         glDisableVertexAttribArray(Attribute_Vertex);
     505            0 :     }
     506            0 :     void vertexpointer(int stride, const void *data, GLenum type, int size, GLenum normalized)
     507              :     {
     508            0 :         disable();
     509            0 :         glVertexAttribPointer(Attribute_Vertex, size, type, normalized, stride, data);
     510            0 :     }
     511            0 :     void enablecolor()
     512              :     {
     513            0 :         glEnableVertexAttribArray(Attribute_Color);
     514            0 :     }
     515            0 :     void disablecolor()
     516              :     {
     517            0 :         glDisableVertexAttribArray(Attribute_Color);
     518            0 :     }
     519            0 :     void colorpointer(int stride, const void *data, GLenum type, int size, GLenum normalized)
     520              :     {
     521            0 :         glVertexAttribPointer(Attribute_Color, size, type, normalized, stride, data);
     522            0 :     }
     523              : 
     524            0 :     void enabletexcoord0()
     525              :     {
     526            0 :         glEnableVertexAttribArray(Attribute_TexCoord0);
     527            0 :     }
     528              : 
     529            0 :     void disabletexcoord0()
     530              :     {
     531            0 :         glDisableVertexAttribArray(Attribute_TexCoord0);
     532            0 :     }
     533              : 
     534            0 :     void texcoord0pointer(int stride, const void *data, GLenum type, int size, GLenum normalized)
     535              :     {
     536            0 :         glVertexAttribPointer(Attribute_TexCoord0, size, type, normalized, stride, data);
     537            0 :     }
     538              : 
     539            0 :     void enablenormal()
     540              :     {
     541            0 :         glEnableVertexAttribArray(Attribute_Normal);
     542            0 :     }
     543              : 
     544            0 :     void disablenormal()
     545              :     {
     546            0 :         glDisableVertexAttribArray(Attribute_Normal);
     547            0 :     }
     548              : 
     549            0 :     void normalpointer(int stride, const void *data, GLenum type, int size, GLenum normalized)
     550              :     {
     551            0 :         glVertexAttribPointer(Attribute_Normal, size, type, normalized, stride, data);
     552            0 :     }
     553              : 
     554            0 :     void enabletangent()
     555              :     {
     556            0 :         glEnableVertexAttribArray(Attribute_Tangent);
     557            0 :     }
     558              : 
     559            0 :     void disabletangent()
     560              :     {
     561            0 :         glDisableVertexAttribArray(Attribute_Tangent);
     562            0 :     }
     563              : 
     564            0 :     void tangentpointer(int stride, const void *data, GLenum type, int size, GLenum normalized)
     565              :     {
     566            0 :         glVertexAttribPointer(Attribute_Tangent, size, type, normalized, stride, data);
     567            0 :     }
     568              : 
     569            0 :     void enableboneweight()
     570              :     {
     571            0 :         glEnableVertexAttribArray(Attribute_BoneWeight);
     572            0 :     }
     573              : 
     574            0 :     void disableboneweight()
     575              :     {
     576            0 :         glDisableVertexAttribArray(Attribute_BoneWeight);
     577            0 :     }
     578              : 
     579            0 :     void boneweightpointer(int stride, const void *data, GLenum type, int size, GLenum normalized)
     580              :     {
     581            0 :         glVertexAttribPointer(Attribute_BoneWeight, size, type, normalized, stride, data);
     582            0 :     }
     583              : 
     584            0 :     void enableboneindex()
     585              :     {
     586            0 :         glEnableVertexAttribArray(Attribute_BoneIndex);
     587            0 :     }
     588              : 
     589            0 :     void disableboneindex()
     590              :     {
     591            0 :         glDisableVertexAttribArray(Attribute_BoneIndex);
     592            0 :     }
     593              : 
     594            0 :     void boneindexpointer(int stride, const void *data, GLenum type, int size, GLenum normalized)
     595              :     {
     596            0 :         glVertexAttribPointer(Attribute_BoneIndex, size, type, normalized, stride, data);
     597            0 :     }
     598              : 
     599            0 :     void bindebo(GLuint ebo)
     600              :     {
     601            0 :         disable();
     602            0 :         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
     603            0 :     }
     604              : 
     605            0 :     void clearebo()
     606              :     {
     607            0 :         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     608            0 :     }
     609              : 
     610            0 :     void bindvbo(GLuint bindvbo)
     611              :     {
     612            0 :         disable();
     613            0 :         glBindBuffer(GL_ARRAY_BUFFER, bindvbo);
     614            0 :     }
     615              : 
     616            0 :     void clearvbo()
     617              :     {
     618            0 :         glBindBuffer(GL_ARRAY_BUFFER, 0);
     619            0 :     }
     620              : 
     621              :     template<class T>
     622            0 :     void attrib(T x, T y)
     623              :     {
     624            0 :         if(attribbuf.check(2*sizeof(T)))
     625              :         {
     626            0 :             T *buf = reinterpret_cast<T *>(attribbuf.pad(2*sizeof(T)));
     627            0 :             buf[0] = x;
     628            0 :             buf[1] = y;
     629              :         }
     630            0 :     }
     631              : 
     632              :     template<class T>
     633            0 :     void attrib(T x, T y, T z)
     634              :     {
     635            0 :         if(attribbuf.check(3*sizeof(T)))
     636              :         {
     637            0 :             T *buf = reinterpret_cast<T *>(attribbuf.pad(3*sizeof(T)));
     638            0 :             buf[0] = x;
     639            0 :             buf[1] = y;
     640            0 :             buf[2] = z;
     641              :         }
     642            0 :     }
     643              : 
     644              :     template<class T>
     645            0 :     void attrib(T x, T y, T z, T w)
     646              :     {
     647            0 :         if(attribbuf.check(4*sizeof(T)))
     648              :         {
     649            0 :             T *buf = reinterpret_cast<T *>(attribbuf.pad(4*sizeof(T)));
     650            0 :             buf[0] = x;
     651            0 :             buf[1] = y;
     652            0 :             buf[2] = z;
     653            0 :             buf[3] = w;
     654              :         }
     655            0 :     }
     656              : 
     657            0 :     void attribf(float x, float y)
     658              :     {
     659            0 :         attrib<float>(x, y);
     660            0 :     }
     661              : 
     662            0 :     void attribf(float x, float y, float z)
     663              :     {
     664            0 :         attrib<float>(x, y, z);
     665            0 :     }
     666              : 
     667            0 :     void attribub(uchar x, uchar y, uchar z, uchar w)
     668              :     {
     669            0 :         attrib<uchar>(x, y, z, w);
     670            0 :     }
     671              : 
     672            0 :     void attrib(const vec &v)
     673              :     {
     674            0 :         attrib<float>(v.x, v.y, v.z);
     675            0 :     }
     676              : 
     677            0 :     void attrib(const vec &v, float w)
     678              :     {
     679            0 :         attrib<float>(v.x, v.y, v.z, w);
     680            0 :     }
     681              : 
     682            0 :     void attrib(const vec2 &v)
     683              :     {
     684            0 :         attrib<float>(v.x, v.y);
     685            0 :     }
     686              : }
     687              : 
        

Generated by: LCOV version 2.0-1