first cut of Object Notification API and tests
[cilux] / src / drivers / nt / mid / mid.c
1
2 /* -------------------------------------------------------------------------- */
3
4 #include <kernelapi.h>
5 #include <ni.h>
6
7 /* -------------------------------------------------------------------------- */
8
9 #define WINDOW_WIDTH  640
10 #define WINDOW_HEIGHT 480
11
12 #define POS_ARRAY      0
13 #define NORMAL_ARRAY   1
14 #define TEXCOORD_ARRAY 2
15
16 #define TEX_SIZE 128
17
18 /* -------------------------------------------------------------------------- */
19
20 static GLfloat xco=   0;
21 static GLfloat yco=   1;
22 static GLfloat zco= -35;
23 static GLfloat view_rotx=0.0, view_roty=0.0, view_rotz=0.0;
24 static int     shift=0;
25
26 GLuint       program;
27 GLuint       texture;
28 GLuint       vbo;
29 unsigned int numberOfVertices;
30 unsigned int posStep;
31 unsigned int normStep;
32 unsigned int tcStep;
33 unsigned int stride;
34 float        angle=0.0;
35 float        viewAngle = 0.0;
36
37 /* -------------------------------------------------------------------------- */
38
39 static int  handles_resource(char* name);
40 static void sync_resource(ni_resource* res);
41 static void init_gl(void);
42 static void reshape(int width, int height);
43 static void draw(void);
44 static void key(unsigned char k, int down);
45
46 static int  useTheProgram();
47 static int  setUpTnL();
48 static int  drawStuff(int width, int height);
49
50 /* -------------------------------------------------------------------------- */
51
52 EXPORT int mid_module_loaded(void)
53 {
54     ni_register_driver("mid", handles_resource, sync_resource);
55
56     init_gl();
57
58     k_gl_register_reshape(reshape);
59     k_gl_register_draw(draw);
60     k_gl_register_key(key);
61
62     k_log_out("MID Driver initialised");
63
64     return 1;
65 }
66
67 EXPORT int mid_module_event(void* data)
68 {
69     k_log_out("MID got event: %p", data);
70     ni_event* evt=data;
71     ni_event_delete(evt);
72     return 1;
73 }
74
75 EXPORT int mid_module_tick(void)
76 {
77     if(!drawStuff(WINDOW_WIDTH, WINDOW_HEIGHT)) k_gl_end();
78     return 1;
79 }
80
81 /* -------------------------------------------------------------------------- */
82
83 int handles_resource(char* name)
84 {
85     return 0;
86 }
87
88 void sync_resource(ni_resource* res)
89 {
90 }
91
92 /* -------------------------------------------------------------------------- */
93
94 void init_gl(void)
95 {
96     if(!useTheProgram()) k_gl_end();
97     if(!setUpTnL())      k_gl_end();
98 }
99
100 void reshape(int width, int height)
101 {
102 }
103
104 void draw(void)
105 {
106     if(!drawStuff(WINDOW_WIDTH, WINDOW_HEIGHT)) k_gl_end();
107 }
108
109 #define SHIFT 0
110 void key(unsigned char k, int down)
111 {
112     if(k == 113) viewAngle += 0.1;
113     if(k == 114) viewAngle -= 0.1;
114
115     if(k==SHIFT &&  down){ shift=1; return; }
116     if(k==SHIFT && !down){ shift=0; return; }
117     if(!down) return;
118
119     if(shift) k-=('a'-'A');
120
121     float speed=0.25;
122     switch (k) {
123     case 'H':
124         xco-=speed*(float)sin((view_roty-90)*3.14/180);
125         zco+=speed*(float)cos((view_roty-90)*3.14/180);
126         if(xco< -35) xco= -35;
127         if(xco>  35) xco=  35;
128         if(zco< -35) zco= -35;
129         if(zco>  35) zco=  35;
130     break;
131     case 'L':
132         xco+=speed*(float)sin((view_roty-90)*3.14/180);
133         zco-=speed*(float)cos((view_roty-90)*3.14/180);
134         if(xco< -35) xco= -35;
135         if(xco>  35) xco=  35;
136         if(zco< -35) zco= -35;
137         if(zco>  35) zco=  35;
138     break;
139     case 'i':
140         xco-=speed*(float)sin(view_roty*3.14/180);
141         zco+=speed*(float)cos(view_roty*3.14/180);
142         if(xco< -35) xco= -35;
143         if(xco>  35) xco=  35;
144         if(zco< -35) zco= -35;
145         if(zco>  35) zco=  35;
146     break;
147     case 'o':
148         xco+=speed*(float)sin(view_roty*3.14/180);
149         zco-=speed*(float)cos(view_roty*3.14/180);
150         if(xco< -35) xco= -35;
151         if(xco>  35) xco=  35;
152         if(zco< -35) zco= -35;
153         if(zco>  35) zco=  35;
154     break;
155     case 'j':
156         yco-=speed;
157         if(yco< 0.2) yco= 0.2;
158     break;
159     case 'k':
160         yco+=speed;
161     break;
162     case 'l':
163         view_roty += speed*20;
164     break;
165     case 'h':
166         view_roty -= speed*20;
167     break;
168     case 'J':
169         view_rotx += 2.0;
170     break;
171     case 'K':
172         view_rotx -= 2.0;
173     break;
174     case 'z':
175         view_rotz += 2.0;
176     break;
177     case 'Z':
178         view_rotz -= 2.0;
179     break;
180     default:
181     return;
182     }
183     draw();
184 }
185
186 /* ------------------------------------------------------------- */
187
188 GLuint isShaderError(GLuint thing)
189 {
190     GLint isShader = glIsShader(thing);
191
192     GLint ok;
193     if(isShader){
194         glGetShaderiv(thing, GL_COMPILE_STATUS, &ok);
195     }else{
196         glGetProgramiv(thing, GL_LINK_STATUS, &ok);
197     }
198     if(ok) return 0;
199
200     GLint infoLen=0;
201     if(isShader){
202         glGetShaderiv(thing, GL_INFO_LOG_LENGTH, &infoLen);
203     }else{
204         glGetProgramiv(thing, GL_INFO_LOG_LENGTH, &infoLen);
205     }
206     if(infoLen){
207          char* infoLog = malloc(sizeof(char)*infoLen);
208          if(isShader){
209               glGetShaderInfoLog(thing, infoLen, NULL, infoLog);
210          }else{
211               glGetProgramInfoLog(thing, infoLen, NULL, infoLog);
212          }
213          printf("%s: %s\n", isShader? "Shader compile": "Program link", infoLog);
214          free(infoLog);
215     }
216     return 1;
217 }
218
219 char* file2string(const char *path)
220 {
221     FILE *fd;
222     long len, r;
223     char *str;
224  
225     if(!(fd=fopen(path, "r"))) {
226         fprintf(stderr, "Can't open file '%s' for reading\n", path);
227         return NULL;
228     }
229  
230     fseek(fd, 0, SEEK_END);
231     len = ftell(fd);
232     fseek(fd, 0, SEEK_SET);
233  
234     if(!(str=malloc(len*sizeof(char)))) {
235         fprintf(stderr, "Can't malloc space for '%s'\n", path);
236         return NULL;
237     }
238  
239     r = fread(str, sizeof(char), len, fd);
240  
241     str[r-1] = '\0';
242  
243     fclose(fd);
244  
245     return str;
246 }
247
248 /* ------------------------------------------------------------- */
249
250 int useTheProgram()
251 {
252     const char *vsSource = file2string("tnl.vert");
253     const char *fsSource = file2string("tnl.frag");
254
255     GLuint vs = glCreateShader(GL_VERTEX_SHADER);
256     glShaderSource(vs, 1, &vsSource, NULL);
257     glCompileShader(vs);
258     if(isShaderError(vs)) return 0;
259  
260     GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
261     glShaderSource(fs, 1, &fsSource, NULL);
262     glCompileShader(fs);
263     if(isShaderError(fs)) return 0;
264  
265     free((void*)vsSource);
266     free((void*)fsSource);
267  
268     program = glCreateProgram();
269     glAttachShader(program, vs);
270     glAttachShader(program, fs);
271
272     glBindAttribLocation(program, POS_ARRAY,      "vertPos");
273     glBindAttribLocation(program, NORMAL_ARRAY,   "vertNormal");
274     /* vertNormal and vertTexCoord don't need to be bound here.. ? */
275     glBindAttribLocation(program, TEXCOORD_ARRAY, "vertTexCoord");
276
277     glLinkProgram(program);
278     if(isShaderError(program)) return 0;
279
280     glUseProgram(program);
281
282     glUniform3f(glGetUniformLocation(program, "frameLightDirection"), 1.0, 0.0, 1.0);
283     glUniform1i(glGetUniformLocation(program, "texture"), 0); /* 0 ?? */
284
285     return 1;
286 }
287
288 int setUpTnL()
289 {
290     glClearColor(1.0f, 1.0f, 0.0f, 0.0f);
291
292     glGenTextures(1, &texture);
293     glBindTexture(GL_TEXTURE_2D, texture);
294
295     GLuint* td = malloc(sizeof(GLuint)*TEX_SIZE*TEX_SIZE);
296     int i,j;
297     for(i=0; i<TEX_SIZE; i++)
298     for(j=0; j<TEX_SIZE; j++) {
299         GLuint col = (255L<<24) + ((255L-j*2)<<16) + ((255L-i)<<8) + (255L-i*2);
300         if ( ((i*j)/8) % 2 ) col = (GLuint) (255L<<24) + (255L<<16) + (0L<<8) + (255L);
301         td[j*TEX_SIZE+i] = col;
302     }
303     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, td);
304     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
305     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
306     free(td);
307
308     GLfloat trivertices[] = {
309                              -0.4f,-0.4f,0.4f,  // Pos
310                               0.0f,0.0f,1.0f,   // Normal
311                               0.0f,0.0f,        // TexCoord
312
313                               0.4f,-0.0f,0.0f,  // Pos
314                               0.0f,0.0f,1.0f,   // Normal
315                               1.0f,0.0f,        // TexCoord
316
317                               0.0f,0.4f,0.4f,   // Pos
318                               0.5f,0.5f,0.5f,   // Normal
319                               0.5f,1.0f,        // TexCoord
320
321                               0.4f,0.0f,0.4f,   // Pos
322                               0.5f,0.5f,0.5f,   // Normal
323                               0.5f,0.0f,        // TexCoord
324
325                               0.4f,0.4f,0.4f,   // Pos
326                               0.0f,0.0f,1.0f,   // Normal
327                               0.0f,0.0f,        // TexCoord
328
329     };
330
331     numberOfVertices = 4;
332     posStep  = 3 * sizeof(GLfloat);
333     normStep = 3 * sizeof(GLfloat);
334     tcStep   = 2 * sizeof(GLfloat);
335     stride = posStep + normStep + tcStep;
336
337     glGenBuffers(1, &vbo);
338     glBindBuffer(GL_ARRAY_BUFFER, vbo);
339     glBufferData(GL_ARRAY_BUFFER, numberOfVertices * stride, trivertices, GL_STATIC_DRAW);
340     glBindBuffer(GL_ARRAY_BUFFER, 0);
341
342     return 1;
343 }
344
345 int drawStuff(int width, int height)
346 {
347     glViewport(0, 0, width, height);
348     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
349
350     float TransRotScaleVerticeMatrix[] = {
351         cos(angle),  0, sin(angle), 0,
352         0,           1, 0,          0,
353         -sin(angle), 0, cos(angle), 0,
354         0,           0, 0,          1
355     };
356
357     float ModelViewProjectionMatrix[] = {
358         cos(viewAngle),  0, sin(viewAngle), 0,
359         0,               1, 0,              0,
360         -sin(viewAngle), 0, cos(viewAngle), 0,
361         0,               0, 0,              1
362     };
363
364     float TransRotScaleNormalMatrix[] = {
365         cos(angle),   0,   sin(angle),
366         0,            1,   0,
367         -sin(angle),  0,   cos(angle)
368     };
369
370     glUniformMatrix4fv(glGetUniformLocation(program, "frameTRSV"), 1, GL_FALSE, TransRotScaleVerticeMatrix);
371     glUniformMatrix4fv(glGetUniformLocation(program, "frameMVP"),  1, GL_FALSE, ModelViewProjectionMatrix);
372     glUniformMatrix3fv(glGetUniformLocation(program, "frameTRSN"), 1, GL_FALSE, TransRotScaleNormalMatrix);
373
374
375     glBindBuffer(GL_ARRAY_BUFFER, vbo);
376
377     glEnableVertexAttribArray(POS_ARRAY);
378     glVertexAttribPointer(POS_ARRAY, 3, GL_FLOAT, GL_FALSE, stride, 0);
379
380     glEnableVertexAttribArray(NORMAL_ARRAY);
381     glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, stride, (void*)posStep  );
382
383     glEnableVertexAttribArray(TEXCOORD_ARRAY);
384     glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, stride, (void*)(posStep + normStep) );
385
386     glDrawArrays(GL_TRIANGLE_STRIP, 0, numberOfVertices);
387
388     glBindBuffer(GL_ARRAY_BUFFER, 0);
389
390     k_gl_swap_buffers();
391
392     angle += .007f;
393
394     return 1;
395 }
396
397 void deleteStuff(){
398     glDeleteTextures(1, &texture);
399     glDeleteBuffers(1, &vbo);
400     glDeleteProgram(program);
401 /*  glDeleteShader();
402     glDeleteShader();*/
403 }
404  
405 /* ------------------------------------------------------------- */
406
407
408