first steps towards opengl in kernel
[cilux] / src / drivers / mid / mid.c
1
2
3 /* -------------------------------------------------------------------------- */
4
5 #include <kernelapi.h>
6 #include <ni.h>
7
8 /* -------------------------------------------------------------------------- */
9
10 #include <math.h>
11
12 #include <EGL/egl.h>
13 #include <GLES2/gl2.h>
14
15 #define WINDOW_WIDTH  640
16 #define WINDOW_HEIGHT 480
17
18 #define POS_ARRAY      0
19 #define NORMAL_ARRAY   1
20 #define TEXCOORD_ARRAY 2
21
22 #define TEX_SIZE 128
23
24 /* -------------------------------------------------------------------------- */
25
26 EGLNativeDisplayType eglX11Display;
27 EGLNativeWindowType  eglX11Window;
28 EGLDisplay           eglDisplay = 0;
29 EGLConfig            eglConfig  = 0;
30 EGLSurface           eglSurface = 0;
31 EGLContext           eglContext = 0;
32
33 /* -------------------------------------------------------------------------- */
34
35 #define GLfloat float
36 static GLfloat   xco=   0;
37 static GLfloat   yco=   1;
38 static GLfloat   zco= -35;
39 static GLfloat   view_rotx=0.0, view_roty=0.0, view_rotz=0.0;
40 static int       shift=0;
41
42 /* -------------------------------------------------------------------------- */
43
44 static int  handles_resource(char* name);
45 static void sync_resource(ni_resource* res);
46 static void init_gl(void);
47 static void reshape(int width, int height);
48 static void draw(void);
49 static void key(unsigned char k, int down);
50
51 static void destroyEGL();
52 static int  getX11Display(int windowwidth, int windowheight);
53 static int  setUpEGL();
54 static int  useTheProgram();
55 static int  setUpTnL();
56 static int  drawStuff(int width, int height);
57
58 /* -------------------------------------------------------------------------- */
59
60 EXPORT int mid_module_loaded(void)
61 {
62     ni_register_driver("mid", handles_resource, sync_resource);
63
64     init_gl();
65
66     k_gl_register_reshape(reshape);
67     k_gl_register_draw(draw);
68     k_gl_register_key(key);
69
70     k_log_out("MID Driver initialised");
71
72     return 1;
73 }
74
75 EXPORT int mid_module_event(void* data)
76 {
77     k_log_out("MID got event: %p", data);
78     ni_event* evt=data;
79     ni_event_delete(evt);
80     return 1;
81 }
82
83 /* -------------------------------------------------------------------------- */
84
85 int handles_resource(char* name)
86 {
87     return 0;
88 }
89
90 void sync_resource(ni_resource* res)
91 {
92 }
93
94 /* -------------------------------------------------------------------------- */
95
96 void init_gl(void)
97 {
98     if(!getX11Display(WINDOW_WIDTH, WINDOW_HEIGHT)) destroyEGL();
99     if(!setUpEGL())                                 destroyEGL();
100     if(!useTheProgram())                            destroyEGL();
101     if(!setUpTnL())                                 destroyEGL();
102 }
103
104 void reshape(int width, int height)
105 {
106 }
107
108 void draw(void)
109 {
110     if(!drawStuff(WINDOW_WIDTH, WINDOW_HEIGHT)) destroyEGL();
111 }
112
113 #define SHIFT 0
114 void key(unsigned char k, int down)
115 {
116 /*
117     if(event.xkey.keycode == 113) viewAngle += 0.1;
118     if(event.xkey.keycode == 114) viewAngle -= 0.1;
119 */
120     if(k==SHIFT &&  down){ shift=1; return; }
121     if(k==SHIFT && !down){ shift=0; return; }
122     if(!down) return;
123
124     if(shift) k-=('a'-'A');
125
126     float speed=0.25;
127     switch (k) {
128     case 'H':
129         xco-=speed*(float)sin((view_roty-90)*3.14/180);
130         zco+=speed*(float)cos((view_roty-90)*3.14/180);
131         if(xco< -35) xco= -35;
132         if(xco>  35) xco=  35;
133         if(zco< -35) zco= -35;
134         if(zco>  35) zco=  35;
135     break;
136     case 'L':
137         xco+=speed*(float)sin((view_roty-90)*3.14/180);
138         zco-=speed*(float)cos((view_roty-90)*3.14/180);
139         if(xco< -35) xco= -35;
140         if(xco>  35) xco=  35;
141         if(zco< -35) zco= -35;
142         if(zco>  35) zco=  35;
143     break;
144     case 'i':
145         xco-=speed*(float)sin(view_roty*3.14/180);
146         zco+=speed*(float)cos(view_roty*3.14/180);
147         if(xco< -35) xco= -35;
148         if(xco>  35) xco=  35;
149         if(zco< -35) zco= -35;
150         if(zco>  35) zco=  35;
151     break;
152     case 'o':
153         xco+=speed*(float)sin(view_roty*3.14/180);
154         zco-=speed*(float)cos(view_roty*3.14/180);
155         if(xco< -35) xco= -35;
156         if(xco>  35) xco=  35;
157         if(zco< -35) zco= -35;
158         if(zco>  35) zco=  35;
159     break;
160     case 'j':
161         yco-=speed;
162         if(yco< 0.2) yco= 0.2;
163     break;
164     case 'k':
165         yco+=speed;
166     break;
167     case 'l':
168         view_roty += speed*20;
169     break;
170     case 'h':
171         view_roty -= speed*20;
172     break;
173     case 'J':
174         view_rotx += 2.0;
175     break;
176     case 'K':
177         view_rotx -= 2.0;
178     break;
179     case 'z':
180         view_rotz += 2.0;
181     break;
182     case 'Z':
183         view_rotz -= 2.0;
184     break;
185     default:
186     return;
187     }
188     draw();
189 }
190
191 /* -------------------------------------------------------------------------- */
192
193 /* need a callback to call this */
194 void destroyEGL()
195 {
196     eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
197     eglTerminate(eglDisplay);
198 }
199
200 /* ------------------------------------------------------------- */
201
202 int isEGLError(char* where)
203 {
204     EGLint err = eglGetError();
205     if(err != EGL_SUCCESS) {
206         printf("EGL failed at %s (%d).\n", where, err);
207         return 1;
208     }
209     return 0;
210 }
211
212 int setUpEGL()
213 {
214     eglDisplay = eglGetDisplay(eglX11Display);
215
216     EGLint iMajorVersion, iMinorVersion;
217     if(!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion)) {
218         printf("Error: eglInitialize() failed.\n");
219         return 0;
220     }
221
222     EGLint pi32ConfigAttribs[5];
223     pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
224     pi32ConfigAttribs[1] = EGL_WINDOW_BIT;
225     pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
226     pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT;    
227     pi32ConfigAttribs[4] = EGL_NONE;
228
229     EGLint pi32ContextAttribs[3];
230     pi32ContextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION;
231     pi32ContextAttribs[1] = 2;
232     pi32ContextAttribs[2] = EGL_NONE;
233
234     int iConfigs;
235     if(!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) {
236         printf("Error: eglChooseConfig() failed.\n");
237         return 0;
238     }
239
240     eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, eglX11Window, NULL);
241     if(isEGLError("eglCreateWindowSurface")) return 0;
242
243     eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, pi32ContextAttribs);
244     if(isEGLError("eglCreateContext")) return 0;
245
246     eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
247     if(isEGLError("eglMakeCurrent")) return 0;
248
249     return 1;
250 }
251
252 /* ------------------------------------------------------------- */
253
254 GLuint isShaderError(GLuint thing)
255 {
256     GLint isShader = glIsShader(thing);
257
258     GLint ok;
259     if(isShader){
260         glGetShaderiv(thing, GL_COMPILE_STATUS, &ok);
261     }else{
262         glGetProgramiv(thing, GL_LINK_STATUS, &ok);
263     }
264     if(ok) return 0;
265
266     GLint infoLen=0;
267     if(isShader){
268         glGetShaderiv(thing, GL_INFO_LOG_LENGTH, &infoLen);
269     }else{
270         glGetProgramiv(thing, GL_INFO_LOG_LENGTH, &infoLen);
271     }
272     if(infoLen){
273          char* infoLog = malloc(sizeof(char)*infoLen);
274          if(isShader){
275               glGetShaderInfoLog(thing, infoLen, NULL, infoLog);
276          }else{
277               glGetProgramInfoLog(thing, infoLen, NULL, infoLog);
278          }
279          printf("%s: %s\n", isShader? "Shader compile": "Program link", infoLog);
280          free(infoLog);
281     }
282     return 1;
283 }
284
285 char* file2string(const char *path)
286 {
287     FILE *fd;
288     long len, r;
289     char *str;
290  
291     if(!(fd=fopen(path, "r"))) {
292         fprintf(stderr, "Can't open file '%s' for reading\n", path);
293         return NULL;
294     }
295  
296     fseek(fd, 0, SEEK_END);
297     len = ftell(fd);
298     fseek(fd, 0, SEEK_SET);
299  
300     if(!(str=malloc(len*sizeof(char)))) {
301         fprintf(stderr, "Can't malloc space for '%s'\n", path);
302         return NULL;
303     }
304  
305     r = fread(str, sizeof(char), len, fd);
306  
307     str[r-1] = '\0';
308  
309     fclose(fd);
310  
311     return str;
312 }
313
314 /* ------------------------------------------------------------- */
315
316 GLuint       program;
317 GLuint       texture;
318 GLuint       vbo;
319 unsigned int numberOfVertices;
320 unsigned int posStep;
321 unsigned int normStep;
322 unsigned int tcStep;
323 unsigned int stride;
324 float        angle=0.0;
325 float        viewAngle = 0.0;
326
327 int useTheProgram()
328 {
329     const char *vsSource = file2string("tnl.vert");
330     const char *fsSource = file2string("tnl.frag");
331
332     GLuint vs = glCreateShader(GL_VERTEX_SHADER);
333     glShaderSource(vs, 1, &vsSource, NULL);
334     glCompileShader(vs);
335     if(isShaderError(vs)) return 0;
336  
337     GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
338     glShaderSource(fs, 1, &fsSource, NULL);
339     glCompileShader(fs);
340     if(isShaderError(fs)) return 0;
341  
342     free((void*)vsSource);
343     free((void*)fsSource);
344  
345     program = glCreateProgram();
346     glAttachShader(program, vs);
347     glAttachShader(program, fs);
348
349     glBindAttribLocation(program, POS_ARRAY,      "vertPos");
350     glBindAttribLocation(program, NORMAL_ARRAY,   "vertNormal");
351     /* vertNormal and vertTexCoord don't need to be bound here.. ? */
352     glBindAttribLocation(program, TEXCOORD_ARRAY, "vertTexCoord");
353
354     glLinkProgram(program);
355     if(isShaderError(program)) return 0;
356
357     glUseProgram(program);
358
359     glUniform3f(glGetUniformLocation(program, "frameLightDirection"), 1.0, 0.0, 1.0);
360     glUniform1i(glGetUniformLocation(program, "texture"), 0); /* 0 ?? */
361
362     return 1;
363 }
364
365 int setUpTnL()
366 {
367     glClearColor(1.0f, 1.0f, 0.0f, 0.0f);
368
369     glGenTextures(1, &texture);
370     glBindTexture(GL_TEXTURE_2D, texture);
371
372     GLuint* td = malloc(sizeof(GLuint)*TEX_SIZE*TEX_SIZE);
373     int i,j;
374     for(i=0; i<TEX_SIZE; i++)
375     for(j=0; j<TEX_SIZE; j++) {
376         GLuint col = (255L<<24) + ((255L-j*2)<<16) + ((255L-i)<<8) + (255L-i*2);
377         if ( ((i*j)/8) % 2 ) col = (GLuint) (255L<<24) + (255L<<16) + (0L<<8) + (255L);
378         td[j*TEX_SIZE+i] = col;
379     }
380     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, td);
381     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
382     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
383     free(td);
384
385     GLfloat trivertices[] = {
386                              -0.4f,-0.4f,0.4f,  // Pos
387                               0.0f,0.0f,1.0f,   // Normal
388                               0.0f,0.0f,        // TexCoord
389
390                               0.4f,-0.0f,0.0f,  // Pos
391                               0.0f,0.0f,1.0f,   // Normal
392                               1.0f,0.0f,        // TexCoord
393
394                               0.0f,0.4f,0.4f,   // Pos
395                               0.5f,0.5f,0.5f,   // Normal
396                               0.5f,1.0f,        // TexCoord
397
398                               0.4f,0.0f,0.4f,   // Pos
399                               0.5f,0.5f,0.5f,   // Normal
400                               0.5f,0.0f,        // TexCoord
401
402                               0.4f,0.4f,0.4f,   // Pos
403                               0.0f,0.0f,1.0f,   // Normal
404                               0.0f,0.0f,        // TexCoord
405
406     };
407
408     numberOfVertices = 4;
409     posStep  = 3 * sizeof(GLfloat);
410     normStep = 3 * sizeof(GLfloat);
411     tcStep   = 2 * sizeof(GLfloat);
412     stride = posStep + normStep + tcStep;
413
414     glGenBuffers(1, &vbo);
415     glBindBuffer(GL_ARRAY_BUFFER, vbo);
416     glBufferData(GL_ARRAY_BUFFER, numberOfVertices * stride, trivertices, GL_STATIC_DRAW);
417     glBindBuffer(GL_ARRAY_BUFFER, 0);
418
419     return 1;
420 }
421
422 int drawStuff(int width, int height)
423 {
424     glViewport(0, 0, width, height);
425     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
426
427     float TransRotScaleVerticeMatrix[] = {
428         cos(angle),  0, sin(angle), 0,
429         0,           1, 0,          0,
430         -sin(angle), 0, cos(angle), 0,
431         0,           0, 0,          1
432     };
433
434     float ModelViewProjectionMatrix[] = {
435         cos(viewAngle),  0, sin(viewAngle), 0,
436         0,               1, 0,              0,
437         -sin(viewAngle), 0, cos(viewAngle), 0,
438         0,               0, 0,              1
439     };
440
441     float TransRotScaleNormalMatrix[] = {
442         cos(angle),   0,   sin(angle),
443         0,            1,   0,
444         -sin(angle),  0,   cos(angle)
445     };
446
447     glUniformMatrix4fv(glGetUniformLocation(program, "frameTRSV"), 1, GL_FALSE, TransRotScaleVerticeMatrix);
448     glUniformMatrix4fv(glGetUniformLocation(program, "frameMVP"),  1, GL_FALSE, ModelViewProjectionMatrix);
449     glUniformMatrix3fv(glGetUniformLocation(program, "frameTRSN"), 1, GL_FALSE, TransRotScaleNormalMatrix);
450
451
452     glBindBuffer(GL_ARRAY_BUFFER, vbo);
453
454     glEnableVertexAttribArray(POS_ARRAY);
455     glVertexAttribPointer(POS_ARRAY, 3, GL_FLOAT, GL_FALSE, stride, 0);
456
457     glEnableVertexAttribArray(NORMAL_ARRAY);
458     glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, stride, (void*)posStep  );
459
460     glEnableVertexAttribArray(TEXCOORD_ARRAY);
461     glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, stride, (void*)(posStep + normStep) );
462
463     glDrawArrays(GL_TRIANGLE_STRIP, 0, numberOfVertices);
464
465     glBindBuffer(GL_ARRAY_BUFFER, 0);
466
467     eglSwapBuffers(eglDisplay, eglSurface);
468
469     angle += .001f;
470
471     return !isEGLError("drawStuff");
472 }
473
474 void deleteStuff(){
475     glDeleteTextures(1, &texture);
476     glDeleteBuffers(1, &vbo);
477     glDeleteProgram(program);
478 /*  glDeleteShader();
479     glDeleteShader();*/
480 }
481  
482 /* ------------------------------------------------------------- */
483
484 #include "X11/Xutil.h"
485
486 Window        x11Window   = 0;
487 Display*      x11Display  = 0;
488 long          x11Screen   = 0;
489 XVisualInfo*  x11Visual   = 0;
490 Colormap      x11Colormap = 0;
491  
492 int getX11Display(int windowwidth, int windowheight)
493 {
494     x11Display = XOpenDisplay(0);
495
496     if(!x11Display) {
497         printf("Error: Unable to open X display\n");
498         return 0;
499     }
500
501     x11Screen = XDefaultScreen(x11Display);
502     Window rootWindow = RootWindow(x11Display, x11Screen);
503     int depth = DefaultDepth(x11Display, x11Screen);
504     x11Visual = malloc(sizeof(XVisualInfo));
505     XMatchVisualInfo(x11Display, x11Screen, depth, TrueColor, x11Visual);
506
507     if(!x11Visual) {
508         printf("Error: Unable to acquire visual\n");
509         return 0;
510     }
511
512     x11Colormap = XCreateColormap(x11Display, rootWindow, x11Visual->visual, AllocNone);
513     XSetWindowAttributes XSWA;
514     XSWA.colormap = x11Colormap;
515     XSWA.event_mask = StructureNotifyMask | ExposureMask |
516                       ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;
517     unsigned int cwmask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
518
519     x11Window = XCreateWindow(x11Display, RootWindow(x11Display, x11Screen), 0, 0, windowwidth, windowheight,
520                               0, CopyFromParent, InputOutput, CopyFromParent, cwmask, &XSWA);
521     XMapWindow(x11Display, x11Window);
522     XFlush(x11Display);
523
524     eglX11Display = (EGLNativeDisplayType)x11Display;
525     eglX11Window  = (EGLNativeWindowType) x11Window;
526
527     return 1;
528 }
529
530 void cleanupX11()
531 {
532     if(x11Window)   XDestroyWindow(x11Display, x11Window);
533     if(x11Colormap) XFreeColormap( x11Display, x11Colormap);
534     if(x11Display)  XCloseDisplay( x11Display);
535 }
536
537 void forKernel()
538 {
539         int nm = XPending(x11Display);
540         int m;
541         for(m=0; m< nm; m++) {
542             XEvent event;
543             XNextEvent(x11Display, &event);
544             switch(event.type){
545                 case ButtonPress:
546                 break;
547                 case KeyPress:
548                 break;
549                 default:
550                 break;
551             }
552         }
553 }
554
555 /* ------------------------------------------------------------- */
556
557
558