ecere/gfx/drivers/OpenGL: Renamed glHelpers.h -> gl123es.h
[sdk] / ecere / src / gfx / drivers / gl3 / immediate.ec
1 // OpenGL Immediate Mode Transition Kit
2 import "glab"
3 import "shading"
4
5 #include "gl123es.h"
6
7 public enum GLIMTKMode
8 {
9    unset          =     -1,
10    points         = 0x0000,
11    lines          = 0x0001,
12    lineLoop       = 0x0002,
13    lineStrip      = 0x0003,
14    triangles      = 0x0004,
15    triangleStrip  = 0x0005,
16    triangleFan    = 0x0006,
17    quads          = 0x0007,
18    quadStrip      = 0x0008,
19    polygon        = 0x0009
20 };
21
22 static int beginCount;
23 static GLIMTKMode beginMode = unset;
24 static bool vertexColorValues = false;
25 static int numCoords = 2;     // Number of coordinates per vertex
26 static int vertexOffset = 2;  // Offset of vertex info
27
28 static struct FloatGLAB : GLAB
29 {
30    uint count;       // Count of vertices
31    uint size;        // Size in vertices
32    int stride;      // Number of floats per vertex
33    float * pointer;
34    uint bufSize;     // Size in bytes of VBO
35
36    static inline float * ensure(uint extraVertices)
37    {
38       if(count + extraVertices >= size)
39       {
40          size = size ? (size + size/2) : Max(count + extraVertices, 6);
41          pointer = renew pointer float[size * stride];
42       }
43       return pointer + count * stride;
44    }
45
46    static inline void upload()
47    {
48       uint bufSize = count * stride * sizeof(float);
49       if(bufSize > this.bufSize)
50       {
51          this.bufSize = bufSize;
52          GLAB::allocate(bufSize, null, dynamicDraw);
53       }
54       GLAB::upload(0, bufSize, verticesBuf.pointer);
55    }
56
57    static inline void free()
58    {
59       bufSize = 0;
60       count = 0;
61       size = 0;
62       delete pointer;
63       GLAB::free();
64    }
65 };
66
67 FloatGLAB verticesBuf { stride = 4 };
68 FloatGLAB normalsBuf { stride = 3 };
69
70 void glimtkTerminate()
71 {
72    verticesBuf.free();
73    normalsBuf.free();
74 }
75
76 public void glimtkRecti(int a, int b, int c, int d)
77 {
78    glimtkBegin(quads);
79    glimtkVertex2i(a, b);
80    glimtkVertex2i(a, d);
81    glimtkVertex2i(c, d);
82    glimtkVertex2i(c, b);
83    glimtkEnd();
84 }
85
86 public void glimtkBegin(GLIMTKMode mode)
87 {
88    beginMode = mode;
89    vertexColorValues = false;
90    beginCount = 0;
91    vertexOffset = 2;
92
93    verticesBuf.count = 0;
94    verticesBuf.stride = 4;
95    numCoords = 2;
96 }
97
98 public void glimtkTexCoord2f(float x, float y)
99 {
100    int stride = verticesBuf.stride;
101    bool quadsAdd = beginMode == quads && !glCaps_quads && ((beginCount % 4) == 3);
102    float * buf = verticesBuf.ensure(quadsAdd ? 3 : 1);
103    buf[0] = x;
104    buf[1] = y;
105    buf += stride;
106    if(quadsAdd)
107    {
108       buf[0] = buf[-4*stride];
109       buf[1] = buf[-4*stride+1];
110       buf += stride;
111       buf[0] = buf[-3*stride];
112       buf[1] = buf[-3*stride+1];
113       buf += stride;
114    }
115 }
116
117 public void glimtkTexCoord2i(int x, int y)       { glimtkTexCoord2f((float)x, (float)y); }
118 public void glimtkTexCoord2d(double x, double y) { glimtkTexCoord2f((float)x, (float)y); }
119 public void glimtkTexCoord2fv(float * a)         { glimtkTexCoord2f(a[0], a[1]); }
120
121 public void glimtkVertex2f(float x, float y)
122 {
123    numCoords = 2;
124    verticesBuf.stride = vertexOffset + numCoords;
125    {
126       int stride = verticesBuf.stride;
127       bool quadsAdd = beginMode == quads && !glCaps_quads && ((beginCount % 4) == 3);
128       float * buf = verticesBuf.ensure(quadsAdd ? 3 : 1) + vertexOffset;
129       buf[0] = x;
130       buf[1] = y;
131       verticesBuf.count++;
132       if(quadsAdd)
133       {
134          buf += stride;
135          buf[0] = buf[-4*stride];
136          buf[1] = buf[-4*stride+1];
137          buf += stride;
138          buf[0] = buf[-3*stride];
139          buf[1] = buf[-3*stride+1];
140          verticesBuf.count+=2;
141       }
142    }
143    beginCount++;
144 }
145 public void glimtkVertex2i(int x, int y)         { glimtkVertex2f((float)x, (float)y); }
146 public void glimtkVertex2d(double x, double y)   { glimtkVertex2f((float)x, (float)y); }
147
148 public void glimtkVertex3f( float x, float y, float z )
149 {
150    numCoords = 3;
151    verticesBuf.stride = vertexOffset + numCoords;
152    {
153       int stride = verticesBuf.stride;
154       bool quadsAdd = beginMode == quads && !glCaps_quads && ((beginCount % 4) == 3);
155       float * buf = verticesBuf.ensure(quadsAdd ? 3 : 1) + vertexOffset;
156       buf[0] = x;
157       buf[1] = y;
158       buf[2] = z;
159       verticesBuf.count++;
160       if(quadsAdd)
161       {
162          buf += stride;
163          buf[0] = buf[-4*stride];
164          buf[1] = buf[-4*stride+1];
165          buf[2] = buf[-4*stride+2];
166          buf += stride;
167          buf[0] = buf[-3*stride];
168          buf[1] = buf[-3*stride+1];
169          buf[2] = buf[-3*stride+2];
170          verticesBuf.count+=2;
171       }
172    }
173    beginCount++;
174 }
175
176 public void glimtkVertex3d( double x, double y, double z )  { glimtkVertex3f((float)x, (float)y, (float)z); }
177 public void glimtkVertex3fv( float* coords )                { glimtkVertex3f(coords[0], coords[1], coords[2]); }
178 public void glimtkVertex3dv( double* coords )               { glimtkVertex3f((float)coords[0], (float)coords[1], (float)coords[2]); }
179
180 public void glimtkColor4f(float r, float g, float b, float a)
181 {
182    if(beginMode != unset)
183    {
184       // Called within glBegin()/glEnd()
185       vertexColorValues = true;
186       vertexOffset = 6;
187       verticesBuf.stride = vertexOffset + numCoords;
188       {
189          int stride = verticesBuf.stride;
190          bool quadsAdd = beginMode == quads && !glCaps_quads && ((beginCount % 4) == 3);
191          float * buf = verticesBuf.ensure(quadsAdd ? 3 : 1) + 2;
192          buf[0] = r, buf[1] = g, buf[2] = b, buf[3] = a;
193
194          if(quadsAdd)
195          {
196             buf += stride;
197             buf[0] = buf[-4*stride];
198             buf[1] = buf[-4*stride+1];
199             buf[2] = buf[-4*stride+2];
200             buf[3] = buf[-4*stride+3];
201             buf += stride;
202             buf[0] = buf[-3*stride];
203             buf[1] = buf[-3*stride+1];
204             buf[2] = buf[-3*stride+2];
205             buf[3] = buf[-3*stride+3];
206          }
207       }
208    }
209    else
210    {
211 #if ENABLE_GL_SHADERS
212       if(glCaps_shaders)
213          shader_color(r, g, b, a);
214 #endif
215
216 #if ENABLE_GL_FFP
217       if(!glCaps_shaders)
218       {
219          glColor4f(r, g, b, a);
220          if(lightingEnabled)
221          {
222             float color[4] = { r, g, b, a };
223             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
224             glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
225          }
226       }
227 #endif
228    }
229 }
230
231 public void glimtkColor3f( float r, float g, float b )      { glimtkColor4f(r, g, b, 1.0f); }
232 public void glimtkColor4ub(byte r, byte g, byte b, byte a)  { glimtkColor4f(r/255.0f, g/255.0f, b/255.0f, a/255.0f); }
233 public void glimtkColor4fv(float * a)                       { glimtkColor4f(a[0], a[1], a[2], a[3]); }
234
235
236 public void glimtkNormal3f(float x, float y, float z)
237 {
238    normalsBuf.count = verticesBuf.count;
239    {
240       int stride = normalsBuf.stride;
241       bool quadsAdd = beginMode == quads && !glCaps_quads && ((beginCount % 4) == 3);
242       float * buf = normalsBuf.ensure(quadsAdd ? 3 : 1) + 2;
243
244       buf[0] = x, buf[1] = y, buf[2] = z;
245       normalsBuf.count++;
246
247       if(quadsAdd)
248       {
249          buf[0] = buf[-4*stride];
250          buf[1] = buf[-4*stride+1];
251          buf[2] = buf[-4*stride+2];
252          buf += stride;
253          buf[0] = buf[-3*stride];
254          buf[1] = buf[-3*stride+1];
255          buf[2] = buf[-3*stride+2];
256          normalsBuf.count += 2;
257       }
258    }
259 }
260 public void glimtkNormal3d(double x, double y, double z)         { glimtkNormal3f((float)x, (float)y, (float)z); }
261 public void glimtkNormal3fv(float * coords)                      { glimtkNormal3f(coords[0], coords[1], coords[2]); }
262 public void glimtkNormal3fd(double * coords)                     { glimtkNormal3f((float)coords[0], (float)coords[1], (float)coords[2]); }
263
264
265 public void glimtkEnd()
266 {
267    GLIMTKMode mode = beginMode;
268    if(!glCaps_quads)
269    {
270       if(mode == quads)        mode = triangles;
271       else if(mode == polygon) mode = triangleFan;
272    }
273
274    GLEnableClientState(TEXCOORDS);
275
276    if(glCaps_vertexBuffer)
277    {
278       verticesBuf.upload();
279       verticesBuf.use(texCoord, 2, GL_FLOAT, verticesBuf.stride * sizeof(float), 0);
280    }
281    else
282       noAB.use(texCoord, 2, GL_FLOAT, verticesBuf.stride * sizeof(float), verticesBuf.pointer);
283
284    if(vertexColorValues)
285    {
286       GLEnableClientState(COLORS);
287       if(glCaps_vertexBuffer)
288          verticesBuf.use(color, 4, GL_FLOAT, verticesBuf.stride * sizeof(float), (void *)(2 * sizeof(float)));
289       else
290          noAB.use(color, 4, GL_FLOAT, verticesBuf.stride * sizeof(float), verticesBuf.pointer + 2);
291
292 #if ENABLE_GL_SHADERS
293       if(glCaps_shaders)
294          shader_setPerVertexColor(true);
295 #endif
296    }
297
298    if(glCaps_vertexBuffer)
299       verticesBuf.use(vertex, numCoords, GL_FLOAT, verticesBuf.stride * sizeof(float), (void *)(vertexOffset * sizeof(float)));
300    else
301       noAB.use(vertex, numCoords, GL_FLOAT, verticesBuf.stride * sizeof(float), verticesBuf.pointer + vertexOffset);
302
303    if(normalsBuf.count && normalsBuf.count == verticesBuf.count)
304    {
305       GLEnableClientState(NORMALS);
306       if(glCaps_vertexBuffer)
307       {
308          normalsBuf.upload();
309          normalsBuf.use(normal, 3, GL_FLOAT, 3*sizeof(float), 0);
310       }
311       else
312          noAB.use(normal, 3, GL_FLOAT, 3*sizeof(float),normalsBuf.pointer);
313    }
314
315    GLFlushMatrices();
316    glDrawArrays(mode, 0, verticesBuf.count);
317
318    if(normalsBuf.count)
319       GLDisableClientState(NORMALS);
320    if(vertexColorValues)
321    {
322       GLDisableClientState(COLORS);
323
324 #if ENABLE_GL_SHADERS
325       if(glCaps_shaders)
326          shader_setPerVertexColor(false);
327 #endif
328
329    }
330    GLDisableClientState(TEXCOORDS);
331
332    normalsBuf.count = 0;
333    vertexColorValues = false;
334    numCoords = 2;
335    beginMode = unset;
336 }