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-06-16 06:16:16 Functions: 1.6 % 61 1

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

Generated by: LCOV version 2.0-1