summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnand Balagopalakrishnan2015-12-15 01:24:41 -0600
committerSubhajit Paul2015-12-16 07:05:56 -0600
commitc294541187a91528225a6dd0e9a9c7a20968cd39 (patch)
treeb2d5abcba0ad369dcf2e14e28f756a1f13fa9918
parent1c8a0d26c5b1918432fd94d2ac9894b3dcdb2814 (diff)
downloadkmscube-next.tar.gz
kmscube-next.tar.xz
kmscube-next.zip
multithreaded kmscubenext
Signed-off-by: Anand Balagopalakrishnan <anandb@ti.com>
-rw-r--r--Makefile.am2
-rwxr-xr-x[-rw-r--r--]kmscube.c626
2 files changed, 363 insertions, 265 deletions
diff --git a/Makefile.am b/Makefile.am
index f28269d..62e940c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,7 +33,7 @@ kmscube_LDADD = \
33 $(GLES2_LIBS) 33 $(GLES2_LIBS)
34 34
35kmscube_CFLAGS = \ 35kmscube_CFLAGS = \
36 -O0 -g -lm \ 36 -O0 -g -lm -lrt -lpthread \
37 $(DRM_CFLAGS) \ 37 $(DRM_CFLAGS) \
38 $(GBM_CFLAGS) \ 38 $(GBM_CFLAGS) \
39 $(EGL_CFLAGS) \ 39 $(EGL_CFLAGS) \
diff --git a/kmscube.c b/kmscube.c
index 5a18c32..bd58f89 100644..100755
--- a/kmscube.c
+++ b/kmscube.c
@@ -29,26 +29,35 @@
29#include <sys/stat.h> 29#include <sys/stat.h>
30#include <fcntl.h> 30#include <fcntl.h>
31#include <string.h> 31#include <string.h>
32#include <stdbool.h>
32#include <stdio.h> 33#include <stdio.h>
33#include <stdlib.h> 34#include <stdlib.h>
34#include <unistd.h> 35#include <unistd.h>
35#include <errno.h> 36#include <errno.h>
36#include <signal.h> 37#include <signal.h>
38#include <pthread.h>
37 39
38#include <xf86drm.h> 40#include <xf86drm.h>
39#include <xf86drmMode.h> 41#include <xf86drmMode.h>
40#include <gbm.h> 42#include <gbm.h>
43#include <time.h>
44#include <semaphore.h>
41 45
42#include "esUtil.h" 46#include "esUtil.h"
43 47
44#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 48#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
45 49
50#define printc(fmt, ...) do { struct timespec tp; clock_gettime(CLOCK_MONOTONIC, &tp); printf("%d.%ld"fmt, tp.tv_sec, tp.tv_nsec, ##__VA_ARGS__); } while(0)
51#define printc(fmt, ...)
46#define MAX_DISPLAYS (4) 52#define MAX_DISPLAYS (4)
53#define MAX_PLANES (4)
54#define CONFIG_WIDTH (320)
55#define CONFIG_HEIGHT (240)
47uint8_t DISP_ID = 0; 56uint8_t DISP_ID = 0;
48uint8_t all_display = 0; 57uint8_t all_display = 0;
49int8_t connector_id = -1; 58int8_t connector_id = -1;
50 59
51static struct { 60struct gl {
52 EGLDisplay display; 61 EGLDisplay display;
53 EGLConfig config; 62 EGLConfig config;
54 EGLContext context; 63 EGLContext context;
@@ -58,17 +67,33 @@ static struct {
58 GLuint vbo; 67 GLuint vbo;
59 GLuint positionsoffset, colorsoffset, normalsoffset; 68 GLuint positionsoffset, colorsoffset, normalsoffset;
60 GLuint vertex_shader, fragment_shader; 69 GLuint vertex_shader, fragment_shader;
61} gl; 70
71};
72
73struct gl_params {
74 EGLNativeDisplayType display;
75 EGLNativeWindowType window;
76 uint32_t width;
77 uint32_t height;
78 int32_t frame_count;
79 bool running;
80 sem_t render;
81 sem_t disp;
82};
62 83
63static struct { 84static struct {
64 struct gbm_device *dev; 85 struct gbm_device *dev;
65 struct gbm_surface *surface; 86 struct gbm_surface *surface[8];
87 struct gbm_bo *flip_bo;
88 uint32_t count;
66} gbm; 89} gbm;
67 90
68static struct { 91static struct {
69 int fd; 92 int fd;
70 uint32_t ndisp; 93 uint32_t ndisp;
71 uint32_t crtc_id[MAX_DISPLAYS]; 94 uint32_t crtc_id[MAX_DISPLAYS];
95 uint32_t plane_id[MAX_PLANES];
96 uint32_t num_planes;
72 uint32_t connector_id[MAX_DISPLAYS]; 97 uint32_t connector_id[MAX_DISPLAYS];
73 uint32_t resource_id; 98 uint32_t resource_id;
74 uint32_t encoder[MAX_DISPLAYS]; 99 uint32_t encoder[MAX_DISPLAYS];
@@ -81,122 +106,27 @@ struct drm_fb {
81 uint32_t fb_id; 106 uint32_t fb_id;
82}; 107};
83 108
84static int init_drm(void) 109static void exit_gl(void *arg)
85{ 110{
86 static const char *modules[] = { 111 struct gl *gl = arg;
87 "omapdrm", "i915", "radeon", "nouveau", "vmwgfx", "exynos" 112
88 }; 113 glDeleteProgram(gl->program);
89 drmModeRes *resources; 114 glDeleteBuffers(1, &gl->vbo);
90 drmModeConnector *connector = NULL; 115 glDeleteShader(gl->fragment_shader);
91 drmModeEncoder *encoder = NULL; 116 glDeleteShader(gl->vertex_shader);
92 int i, j; 117 eglDestroySurface(gl->display, gl->surface);
93 uint32_t maxRes, curRes; 118 eglDestroyContext(gl->display, gl->context);
94 119 eglTerminate(gl->display);
95 for (i = 0; i < ARRAY_SIZE(modules); i++) { 120 return;
96 printf("trying to load module %s...", modules[i]);
97 drm.fd = drmOpen(modules[i], NULL);
98 if (drm.fd < 0) {
99 printf("failed.\n");
100 } else {
101 printf("success.\n");
102 break;
103 }
104 }
105
106 if (drm.fd < 0) {
107 printf("could not open drm device\n");
108 return -1;
109 }
110
111 resources = drmModeGetResources(drm.fd);
112 if (!resources) {
113 printf("drmModeGetResources failed: %s\n", strerror(errno));
114 return -1;
115 }
116 drm.resource_id = (uint32_t) resources;
117
118 /* find a connected connector: */
119 for (i = 0; i < resources->count_connectors; i++) {
120 connector = drmModeGetConnector(drm.fd, resources->connectors[i]);
121 if (connector->connection == DRM_MODE_CONNECTED) {
122 /* choose the first supported mode */
123 drm.mode[drm.ndisp] = &connector->modes[0];
124 drm.connector_id[drm.ndisp] = connector->connector_id;
125
126 for (j=0; j<resources->count_encoders; j++) {
127 encoder = drmModeGetEncoder(drm.fd, resources->encoders[j]);
128 if (encoder->encoder_id == connector->encoder_id)
129 break;
130
131 drmModeFreeEncoder(encoder);
132 encoder = NULL;
133 }
134
135 if (!encoder) {
136 printf("no encoder!\n");
137 return -1;
138 }
139
140 drm.encoder[drm.ndisp] = (uint32_t) encoder;
141 drm.crtc_id[drm.ndisp] = encoder->crtc_id;
142 drm.connectors[drm.ndisp] = connector;
143
144 printf("### Display [%d]: CRTC = %d, Connector = %d\n", drm.ndisp, drm.crtc_id[drm.ndisp], drm.connector_id[drm.ndisp]);
145 printf("\tMode chosen [%s] : Clock => %d, Vertical refresh => %d, Type => %d\n", drm.mode[drm.ndisp]->name, drm.mode[drm.ndisp]->clock, drm.mode[drm.ndisp]->vrefresh, drm.mode[drm.ndisp]->type);
146 printf("\tHorizontal => %d, %d, %d, %d, %d\n", drm.mode[drm.ndisp]->hdisplay, drm.mode[drm.ndisp]->hsync_start, drm.mode[drm.ndisp]->hsync_end, drm.mode[drm.ndisp]->htotal, drm.mode[drm.ndisp]->hskew);
147 printf("\tVertical => %d, %d, %d, %d, %d\n", drm.mode[drm.ndisp]->vdisplay, drm.mode[drm.ndisp]->vsync_start, drm.mode[drm.ndisp]->vsync_end, drm.mode[drm.ndisp]->vtotal, drm.mode[drm.ndisp]->vscan);
148
149 /* If a connector_id is specified, use the corresponding display */
150 if ((connector_id != -1) && (connector_id == drm.connector_id[drm.ndisp]))
151 DISP_ID = drm.ndisp;
152
153 /* If all displays are enabled, choose the connector with maximum
154 * resolution as the primary display */
155 if (all_display) {
156 maxRes = drm.mode[DISP_ID]->vdisplay * drm.mode[DISP_ID]->hdisplay;
157 curRes = drm.mode[drm.ndisp]->vdisplay * drm.mode[drm.ndisp]->hdisplay;
158
159 if (curRes > maxRes)
160 DISP_ID = drm.ndisp;
161 }
162
163 drm.ndisp++;
164 } else {
165 drmModeFreeConnector(connector);
166 }
167 }
168
169 if (drm.ndisp == 0) {
170 /* we could be fancy and listen for hotplug events and wait for
171 * a connector..
172 */
173 printf("no connected connector!\n");
174 return -1;
175 }
176
177 return 0;
178}
179
180static int init_gbm(void)
181{
182 gbm.dev = gbm_create_device(drm.fd);
183
184 gbm.surface = gbm_surface_create(gbm.dev,
185 drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay,
186 GBM_FORMAT_XRGB8888,
187 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
188 if (!gbm.surface) {
189 printf("failed to create gbm surface\n");
190 return -1;
191 }
192
193 return 0;
194} 121}
195 122
196static int init_gl(void) 123static void *gl_thread (void *arg)
197{ 124{
198 EGLint major, minor, n; 125 EGLint major, minor, n;
199 GLint ret; 126 GLint ret;
127 struct gl *gl;
128 struct gl_params *params = arg;
129 uint32_t frame_count = params->frame_count;
200 130
201 static const GLfloat vVertices[] = { 131 static const GLfloat vVertices[] = {
202 // front 132 // front
@@ -308,6 +238,7 @@ static int init_gl(void)
308 EGL_GREEN_SIZE, 1, 238 EGL_GREEN_SIZE, 1,
309 EGL_BLUE_SIZE, 1, 239 EGL_BLUE_SIZE, 1,
310 EGL_ALPHA_SIZE, 0, 240 EGL_ALPHA_SIZE, 0,
241 EGL_DEPTH_SIZE, 8,
311 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 242 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
312 EGL_NONE 243 EGL_NONE
313 }; 244 };
@@ -345,160 +276,345 @@ static int init_gl(void)
345 "{ \n" 276 "{ \n"
346 " gl_FragColor = vVaryingColor; \n" 277 " gl_FragColor = vVaryingColor; \n"
347 "} \n"; 278 "} \n";
279 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
280 gl = calloc(1, sizeof(struct gl));
281 if(!gl) {
282 printf("GL memory allocation failed\n");
283 return NULL;
284 }
285
286 pthread_cleanup_push(exit_gl, gl);
287 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
348 288
349 gl.display = eglGetDisplay(gbm.dev); 289 gl->display = eglGetDisplay(params->display);
350 290
351 if (!eglInitialize(gl.display, &major, &minor)) { 291 if (!eglInitialize(gl->display, &major, &minor)) {
352 printf("failed to initialize\n"); 292 printf("failed to initialize\n");
353 return -1; 293 return NULL;
354 } 294 }
355 295
356 printf("Using display %p with EGL version %d.%d\n",
357 gl.display, major, minor);
358
359 printf("EGL Version \"%s\"\n", eglQueryString(gl.display, EGL_VERSION));
360 printf("EGL Vendor \"%s\"\n", eglQueryString(gl.display, EGL_VENDOR));
361 printf("EGL Extensions \"%s\"\n", eglQueryString(gl.display, EGL_EXTENSIONS));
362
363 if (!eglBindAPI(EGL_OPENGL_ES_API)) { 296 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
364 printf("failed to bind api EGL_OPENGL_ES_API\n"); 297 printf("failed to bind api EGL_OPENGL_ES_API\n");
365 return -1; 298 return NULL;
366 } 299 }
367 300
368 if (!eglChooseConfig(gl.display, config_attribs, &gl.config, 1, &n) || n != 1) { 301 if (!eglChooseConfig(gl->display, config_attribs, &gl->config, 1, &n) || n != 1) {
369 printf("failed to choose config: %d\n", n); 302 printf("failed to choose config: %d\n", n);
370 return -1; 303 return NULL;
371 } 304 }
372 305
373 gl.context = eglCreateContext(gl.display, gl.config, 306 gl->context = eglCreateContext(gl->display, gl->config,
374 EGL_NO_CONTEXT, context_attribs); 307 EGL_NO_CONTEXT, context_attribs);
375 if (gl.context == NULL) { 308 if (gl->context == NULL) {
376 printf("failed to create context\n"); 309 printf("failed to create context\n");
377 return -1; 310 return NULL;
378 } 311 }
379 312
380 gl.surface = eglCreateWindowSurface(gl.display, gl.config, gbm.surface, NULL); 313 gl->surface = eglCreateWindowSurface(gl->display, gl->config, params->window, NULL);
381 if (gl.surface == EGL_NO_SURFACE) { 314 if (gl->surface == EGL_NO_SURFACE) {
382 printf("failed to create egl surface\n"); 315 printf("failed to create egl surface\n");
383 return -1; 316 return NULL;
384 } 317 }
385 318
386 /* connect the context to the surface */ 319 /* connect the context to the surface */
387 eglMakeCurrent(gl.display, gl.surface, gl.surface, gl.context); 320 eglMakeCurrent(gl->display, gl->surface, gl->surface, gl->context);
388 321
389 322
390 gl.vertex_shader = glCreateShader(GL_VERTEX_SHADER); 323 gl->vertex_shader = glCreateShader(GL_VERTEX_SHADER);
391 324
392 glShaderSource(gl.vertex_shader, 1, &vertex_shader_source, NULL); 325 glShaderSource(gl->vertex_shader, 1, &vertex_shader_source, NULL);
393 glCompileShader(gl.vertex_shader); 326 glCompileShader(gl->vertex_shader);
394 327
395 glGetShaderiv(gl.vertex_shader, GL_COMPILE_STATUS, &ret); 328 glGetShaderiv(gl->vertex_shader, GL_COMPILE_STATUS, &ret);
396 if (!ret) { 329 if (!ret) {
397 char *log; 330 char *log;
398 331
399 printf("vertex shader compilation failed!:\n"); 332 printf("vertex shader compilation failed!:\n");
400 glGetShaderiv(gl.vertex_shader, GL_INFO_LOG_LENGTH, &ret); 333 glGetShaderiv(gl->vertex_shader, GL_INFO_LOG_LENGTH, &ret);
401 if (ret > 1) { 334 if (ret > 1) {
402 log = malloc(ret); 335 log = malloc(ret);
403 glGetShaderInfoLog(gl.vertex_shader, ret, NULL, log); 336 glGetShaderInfoLog(gl->vertex_shader, ret, NULL, log);
404 printf("%s", log); 337 printf("%s", log);
405 } 338 }
406 339
407 return -1; 340 return NULL;
408 } 341 }
409 342
410 gl.fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 343 gl->fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
411 344
412 glShaderSource(gl.fragment_shader, 1, &fragment_shader_source, NULL); 345 glShaderSource(gl->fragment_shader, 1, &fragment_shader_source, NULL);
413 glCompileShader(gl.fragment_shader); 346 glCompileShader(gl->fragment_shader);
414 347
415 glGetShaderiv(gl.fragment_shader, GL_COMPILE_STATUS, &ret); 348 glGetShaderiv(gl->fragment_shader, GL_COMPILE_STATUS, &ret);
416 if (!ret) { 349 if (!ret) {
417 char *log; 350 char *log;
418 351
419 printf("fragment shader compilation failed!:\n"); 352 printf("fragment shader compilation failed!:\n");
420 glGetShaderiv(gl.fragment_shader, GL_INFO_LOG_LENGTH, &ret); 353 glGetShaderiv(gl->fragment_shader, GL_INFO_LOG_LENGTH, &ret);
421 354
422 if (ret > 1) { 355 if (ret > 1) {
423 log = malloc(ret); 356 log = malloc(ret);
424 glGetShaderInfoLog(gl.fragment_shader, ret, NULL, log); 357 glGetShaderInfoLog(gl->fragment_shader, ret, NULL, log);
425 printf("%s", log); 358 printf("%s", log);
426 } 359 }
427 360
428 return -1; 361 return NULL;
429 } 362 }
430 363
431 gl.program = glCreateProgram(); 364 gl->program = glCreateProgram();
432 365
433 glAttachShader(gl.program, gl.vertex_shader); 366 glAttachShader(gl->program, gl->vertex_shader);
434 glAttachShader(gl.program, gl.fragment_shader); 367 glAttachShader(gl->program, gl->fragment_shader);
435 368
436 glBindAttribLocation(gl.program, 0, "in_position"); 369 glBindAttribLocation(gl->program, 0, "in_position");
437 glBindAttribLocation(gl.program, 1, "in_normal"); 370 glBindAttribLocation(gl->program, 1, "in_normal");
438 glBindAttribLocation(gl.program, 2, "in_color"); 371 glBindAttribLocation(gl->program, 2, "in_color");
439 372
440 glLinkProgram(gl.program); 373 glLinkProgram(gl->program);
441 374
442 glGetProgramiv(gl.program, GL_LINK_STATUS, &ret); 375 glGetProgramiv(gl->program, GL_LINK_STATUS, &ret);
443 if (!ret) { 376 if (!ret) {
444 char *log; 377 char *log;
445 378
446 printf("program linking failed!:\n"); 379 printf("program linking failed!:\n");
447 glGetProgramiv(gl.program, GL_INFO_LOG_LENGTH, &ret); 380 glGetProgramiv(gl->program, GL_INFO_LOG_LENGTH, &ret);
448 381
449 if (ret > 1) { 382 if (ret > 1) {
450 log = malloc(ret); 383 log = malloc(ret);
451 glGetProgramInfoLog(gl.program, ret, NULL, log); 384 glGetProgramInfoLog(gl->program, ret, NULL, log);
452 printf("%s", log); 385 printf("%s", log);
453 } 386 }
454 387
455 return -1; 388 return NULL;
456 } 389 }
457 390
458 glUseProgram(gl.program); 391 glUseProgram(gl->program);
459 392
460 gl.modelviewmatrix = glGetUniformLocation(gl.program, "modelviewMatrix"); 393 gl->modelviewmatrix = glGetUniformLocation(gl->program, "modelviewMatrix");
461 gl.modelviewprojectionmatrix = glGetUniformLocation(gl.program, "modelviewprojectionMatrix"); 394 gl->modelviewprojectionmatrix = glGetUniformLocation(gl->program, "modelviewprojectionMatrix");
462 gl.normalmatrix = glGetUniformLocation(gl.program, "normalMatrix"); 395 gl->normalmatrix = glGetUniformLocation(gl->program, "normalMatrix");
463 396
464 glViewport(0, 0, drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay); 397 glViewport(0, 0, params->width, params->height);
465 glEnable(GL_CULL_FACE); 398 glEnable(GL_CULL_FACE);
466 399
467 gl.positionsoffset = 0; 400 gl->positionsoffset = 0;
468 gl.colorsoffset = sizeof(vVertices); 401 gl->colorsoffset = sizeof(vVertices);
469 gl.normalsoffset = sizeof(vVertices) + sizeof(vColors); 402 gl->normalsoffset = sizeof(vVertices) + sizeof(vColors);
470 glGenBuffers(1, &gl.vbo); 403 glGenBuffers(1, &gl->vbo);
471 glBindBuffer(GL_ARRAY_BUFFER, gl.vbo); 404 glBindBuffer(GL_ARRAY_BUFFER, gl->vbo);
472 glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices) + sizeof(vColors) + sizeof(vNormals), 0, GL_STATIC_DRAW); 405 glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices) + sizeof(vColors) + sizeof(vNormals), 0, GL_STATIC_DRAW);
473 glBufferSubData(GL_ARRAY_BUFFER, gl.positionsoffset, sizeof(vVertices), &vVertices[0]); 406 glBufferSubData(GL_ARRAY_BUFFER, gl->positionsoffset, sizeof(vVertices), &vVertices[0]);
474 glBufferSubData(GL_ARRAY_BUFFER, gl.colorsoffset, sizeof(vColors), &vColors[0]); 407 glBufferSubData(GL_ARRAY_BUFFER, gl->colorsoffset, sizeof(vColors), &vColors[0]);
475 glBufferSubData(GL_ARRAY_BUFFER, gl.normalsoffset, sizeof(vNormals), &vNormals[0]); 408 glBufferSubData(GL_ARRAY_BUFFER, gl->normalsoffset, sizeof(vNormals), &vNormals[0]);
476 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl.positionsoffset); 409 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl->positionsoffset);
477 glEnableVertexAttribArray(0); 410 glEnableVertexAttribArray(0);
478 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl.normalsoffset); 411 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl->normalsoffset);
479 glEnableVertexAttribArray(1); 412 glEnableVertexAttribArray(1);
480 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl.colorsoffset); 413 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl->colorsoffset);
481 glEnableVertexAttribArray(2); 414 glEnableVertexAttribArray(2);
482 415
416 int i = 0;
417 while (frame_count != 0 && params->running == true) {
418 ESMatrix modelview;
419
420 /* clear the color buffer */
421
422 glClearColor(0.5, 0.5, 0.5, 1.0);
423 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
424
425 esMatrixLoadIdentity(&modelview);
426 esTranslate(&modelview, 0.0f, 0.0f, -8.0f);
427 esRotate(&modelview, 45.0f + (0.25f * i), 1.0f, 0.0f, 0.0f);
428 esRotate(&modelview, 45.0f - (0.5f * i), 0.0f, 1.0f, 0.0f);
429 esRotate(&modelview, 10.0f + (0.15f * i), 0.0f, 0.0f, 1.0f);
430
431 GLfloat aspect = (GLfloat)(drm.mode[DISP_ID]->vdisplay) / (GLfloat)(drm.mode[DISP_ID]->hdisplay);
432
433 ESMatrix projection;
434 esMatrixLoadIdentity(&projection);
435 esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f);
436
437 ESMatrix modelviewprojection;
438 esMatrixLoadIdentity(&modelviewprojection);
439 esMatrixMultiply(&modelviewprojection, &modelview, &projection);
440
441 float normal[9];
442 normal[0] = modelview.m[0][0];
443 normal[1] = modelview.m[0][1];
444 normal[2] = modelview.m[0][2];
445 normal[3] = modelview.m[1][0];
446 normal[4] = modelview.m[1][1];
447 normal[5] = modelview.m[1][2];
448 normal[6] = modelview.m[2][0];
449 normal[7] = modelview.m[2][1];
450 normal[8] = modelview.m[2][2];
451
452 glUniformMatrix4fv(gl->modelviewmatrix, 1, GL_FALSE, &modelview.m[0][0]);
453 glUniformMatrix4fv(gl->modelviewprojectionmatrix, 1, GL_FALSE, &modelviewprojection.m[0][0]);
454 glUniformMatrix3fv(gl->normalmatrix, 1, GL_FALSE, normal);
455
456 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
457 glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
458 glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
459 glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
460 glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
461 glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
462
463 eglSwapBuffers(gl->display, gl->surface);
464 printc("#### swap buffers\n");
465
466 sem_post(&params->render);
467
468 i++;
469 frame_count--;
470
471 sem_wait(&params->disp);
472
473 }
474 pthread_cleanup_pop(1);
475
476}
477
478#define THR_CNT (3)
479pthread_t draw_thread[MAX_PLANES];
480uint32_t num_threads;
481
482static int init_drm(void)
483{
484 static const char *modules[] = {
485 "omapdrm", "i915", "radeon", "nouveau", "vmwgfx", "exynos"
486 };
487 drmModeRes *resources;
488 drmModePlaneResPtr planeRes;
489 drmModeConnector *connector = NULL;
490 drmModeEncoder *encoder = NULL;
491 int i, j;
492 uint32_t maxRes, curRes;
493
494 for (i = 0; i < ARRAY_SIZE(modules); i++) {
495 printf("trying to load module %s...", modules[i]);
496 drm.fd = drmOpen(modules[i], NULL);
497 if (drm.fd < 0) {
498 printf("failed.\n");
499 } else {
500 printf("success.\n");
501 break;
502 }
503 }
504
505 if (drm.fd < 0) {
506 printf("could not open drm device\n");
507 return -1;
508 }
509
510 resources = drmModeGetResources(drm.fd);
511 if (!resources) {
512 printf("drmModeGetResources failed: %s\n", strerror(errno));
513 return -1;
514 }
515 drm.resource_id = (uint32_t) resources;
516
517 /* find a connected connector: */
518 for (i = 0; i < resources->count_connectors; i++) {
519 connector = drmModeGetConnector(drm.fd, resources->connectors[i]);
520 if (connector->connection == DRM_MODE_CONNECTED) {
521 /* choose the first supported mode */
522 drm.mode[drm.ndisp] = &connector->modes[0];
523 drm.connector_id[drm.ndisp] = connector->connector_id;
524
525 for (j=0; j<resources->count_encoders; j++) {
526 encoder = drmModeGetEncoder(drm.fd, resources->encoders[j]);
527 if (encoder->encoder_id == connector->encoder_id)
528 break;
529
530 drmModeFreeEncoder(encoder);
531 encoder = NULL;
532 }
533
534 if (!encoder) {
535 printf("no encoder!\n");
536 return -1;
537 }
538
539 drm.encoder[drm.ndisp] = (uint32_t) encoder;
540 drm.crtc_id[drm.ndisp] = encoder->crtc_id;
541 drm.connectors[drm.ndisp] = connector;
542
543 printf("### Display [%d]: CRTC = %d, Connector = %d\n", drm.ndisp, drm.crtc_id[drm.ndisp], drm.connector_id[drm.ndisp]);
544 printf("\tMode chosen [%s] : Clock => %d, Vertical refresh => %d, Type => %d\n", drm.mode[drm.ndisp]->name, drm.mode[drm.ndisp]->clock, drm.mode[drm.ndisp]->vrefresh, drm.mode[drm.ndisp]->type);
545 printf("\tHorizontal => %d, %d, %d, %d, %d\n", drm.mode[drm.ndisp]->hdisplay, drm.mode[drm.ndisp]->hsync_start, drm.mode[drm.ndisp]->hsync_end, drm.mode[drm.ndisp]->htotal, drm.mode[drm.ndisp]->hskew);
546 printf("\tVertical => %d, %d, %d, %d, %d\n", drm.mode[drm.ndisp]->vdisplay, drm.mode[drm.ndisp]->vsync_start, drm.mode[drm.ndisp]->vsync_end, drm.mode[drm.ndisp]->vtotal, drm.mode[drm.ndisp]->vscan);
547
548 /* If a connector_id is specified, use the corresponding display */
549 if ((connector_id != -1) && (connector_id == drm.connector_id[drm.ndisp]))
550 DISP_ID = drm.ndisp;
551
552 /* If all displays are enabled, choose the connector with maximum
553 * resolution as the primary display */
554 if (all_display) {
555 maxRes = drm.mode[DISP_ID]->vdisplay * drm.mode[DISP_ID]->hdisplay;
556 curRes = drm.mode[drm.ndisp]->vdisplay * drm.mode[drm.ndisp]->hdisplay;
557
558 if (curRes > maxRes)
559 DISP_ID = drm.ndisp;
560 }
561
562 drm.ndisp++;
563 } else {
564 drmModeFreeConnector(connector);
565 }
566 }
567
568
569
570 if (drm.ndisp == 0) {
571 /* we could be fancy and listen for hotplug events and wait for
572 * a connector..
573 */
574 printf("no connected connector!\n");
575 return -1;
576 }
577
578 planeRes = drmModeGetPlaneResources (drm.fd);
579 for (i = 0; i < planeRes->count_planes; i++)
580 drm.plane_id[drm.num_planes++] = planeRes->planes[i];
581
483 return 0; 582 return 0;
484} 583}
485 584
486static void exit_gbm(void) 585static int init_gbm(uint32_t surf_count, uint32_t width, uint32_t height)
487{ 586{
488 gbm_surface_destroy(gbm.surface); 587 int count;
489 gbm_device_destroy(gbm.dev); 588
490 return; 589 gbm.dev = gbm_create_device(drm.fd);
590 gbm.flip_bo = gbm_bo_create(gbm.dev,
591 drm.mode[DISP_ID]->hdisplay,
592 drm.mode[DISP_ID]->vdisplay,
593 GBM_FORMAT_XRGB8888,
594 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
595
596 for(count = 0; count < surf_count; count++) {
597 gbm.surface[count] = gbm_surface_create(gbm.dev,
598 width, height,
599 GBM_FORMAT_XRGB8888,
600 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
601 if (!gbm.surface[count]) {
602 printf("failed to create gbm surface\n");
603 return -1;
604 }
605 gbm.count++;
606 }
607
608 return 0;
491} 609}
492 610
493static void exit_gl(void) 611
612static void exit_gbm(void)
494{ 613{
495 glDeleteProgram(gl.program); 614 while(gbm.count--)
496 glDeleteBuffers(1, &gl.vbo); 615 gbm_surface_destroy(gbm.surface[gbm.count]);
497 glDeleteShader(gl.fragment_shader); 616 gbm_bo_destroy(gbm.flip_bo);
498 glDeleteShader(gl.vertex_shader); 617 gbm_device_destroy(gbm.dev);
499 eglDestroySurface(gl.display, gl.surface);
500 eglDestroyContext(gl.display, gl.context);
501 eglTerminate(gl.display);
502 return; 618 return;
503} 619}
504 620
@@ -520,60 +636,16 @@ static void exit_drm(void)
520 636
521void cleanup_kmscube(void) 637void cleanup_kmscube(void)
522{ 638{
523 exit_gl(); 639 while(num_threads--) {
640 pthread_cancel(draw_thread[num_threads]);
641 pthread_join(draw_thread[num_threads], NULL);
642 }
524 exit_gbm(); 643 exit_gbm();
525 exit_drm(); 644 exit_drm();
526 printf("Cleanup of GL, GBM and DRM completed\n"); 645 printf("Cleanup of GL, GBM and DRM completed\n");
527 return; 646 return;
528} 647}
529 648
530static void draw(uint32_t i)
531{
532 ESMatrix modelview;
533
534 /* clear the color buffer */
535 glClearColor(0.5, 0.5, 0.5, 1.0);
536 glClear(GL_COLOR_BUFFER_BIT);
537
538 esMatrixLoadIdentity(&modelview);
539 esTranslate(&modelview, 0.0f, 0.0f, -8.0f);
540 esRotate(&modelview, 45.0f + (0.25f * i), 1.0f, 0.0f, 0.0f);
541 esRotate(&modelview, 45.0f - (0.5f * i), 0.0f, 1.0f, 0.0f);
542 esRotate(&modelview, 10.0f + (0.15f * i), 0.0f, 0.0f, 1.0f);
543
544 GLfloat aspect = (GLfloat)(drm.mode[DISP_ID]->vdisplay) / (GLfloat)(drm.mode[DISP_ID]->hdisplay);
545
546 ESMatrix projection;
547 esMatrixLoadIdentity(&projection);
548 esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f);
549
550 ESMatrix modelviewprojection;
551 esMatrixLoadIdentity(&modelviewprojection);
552 esMatrixMultiply(&modelviewprojection, &modelview, &projection);
553
554 float normal[9];
555 normal[0] = modelview.m[0][0];
556 normal[1] = modelview.m[0][1];
557 normal[2] = modelview.m[0][2];
558 normal[3] = modelview.m[1][0];
559 normal[4] = modelview.m[1][1];
560 normal[5] = modelview.m[1][2];
561 normal[6] = modelview.m[2][0];
562 normal[7] = modelview.m[2][1];
563 normal[8] = modelview.m[2][2];
564
565 glUniformMatrix4fv(gl.modelviewmatrix, 1, GL_FALSE, &modelview.m[0][0]);
566 glUniformMatrix4fv(gl.modelviewprojectionmatrix, 1, GL_FALSE, &modelviewprojection.m[0][0]);
567 glUniformMatrix3fv(gl.normalmatrix, 1, GL_FALSE, normal);
568
569 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
570 glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
571 glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
572 glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
573 glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
574 glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
575}
576
577static void 649static void
578drm_fb_destroy_callback(struct gbm_bo *bo, void *data) 650drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
579{ 651{
@@ -656,12 +728,14 @@ int main(int argc, char *argv[])
656 .version = DRM_EVENT_CONTEXT_VERSION, 728 .version = DRM_EVENT_CONTEXT_VERSION,
657 .page_flip_handler = page_flip_handler, 729 .page_flip_handler = page_flip_handler,
658 }; 730 };
659 struct gbm_bo *bo; 731 struct gbm_bo *bo = NULL;
660 struct drm_fb *fb; 732 struct drm_fb *flip_fb;
733 struct drm_fb *fb[THR_CNT];
661 uint32_t i = 0; 734 uint32_t i = 0;
662 int ret; 735 int ret;
663 int opt; 736 int opt;
664 int frame_count = -1; 737 int frame_count = -1;
738 int count;
665 739
666 signal(SIGINT, kms_signalhandler); 740 signal(SIGINT, kms_signalhandler);
667 signal(SIGTERM, kms_signalhandler); 741 signal(SIGTERM, kms_signalhandler);
@@ -708,29 +782,35 @@ int main(int argc, char *argv[])
708 FD_ZERO(&fds); 782 FD_ZERO(&fds);
709 FD_SET(drm.fd, &fds); 783 FD_SET(drm.fd, &fds);
710 784
711 ret = init_gbm(); 785 ret = init_gbm(THR_CNT, CONFIG_WIDTH, CONFIG_HEIGHT);
712 if (ret) { 786 if (ret) {
713 printf("failed to initialize GBM\n"); 787 printf("failed to initialize GBM\n");
714 return ret; 788 return ret;
715 } 789 }
716 790
717 ret = init_gl(); 791 struct gl_params p[THR_CNT];
718 if (ret) { 792 for(count = 0; count < THR_CNT; count++) {
719 printf("failed to initialize EGL\n"); 793 p[count].display = gbm.dev;
720 return ret; 794 p[count].window = gbm.surface[count];
795 p[count].frame_count = frame_count;
796 p[count].running = true;
797 p[count].width = CONFIG_WIDTH;
798 p[count].height = CONFIG_HEIGHT;
799 sem_init(&p[count].render, 0, 0);
800 sem_init(&p[count].disp, 0, 0);
801 ret = pthread_create(&draw_thread[num_threads++], NULL, gl_thread, &p[count]);
802 if (ret) {
803 printf("failed to initialize EGL\n");
804 return ret;
805 }
721 } 806 }
722 807
723 /* clear the color buffer */
724 glClearColor(0.5, 0.5, 0.5, 1.0);
725 glClear(GL_COLOR_BUFFER_BIT);
726 eglSwapBuffers(gl.display, gl.surface);
727 bo = gbm_surface_lock_front_buffer(gbm.surface);
728 fb = drm_fb_get_from_bo(bo);
729 808
730 /* set mode: */ 809 /* set mode: */
810 flip_fb = drm_fb_get_from_bo(gbm.flip_bo);
731 if (all_display) { 811 if (all_display) {
732 for (i=0; i<drm.ndisp; i++) { 812 for (i=0; i<drm.ndisp; i++) {
733 ret = drmModeSetCrtc(drm.fd, drm.crtc_id[i], fb->fb_id, 0, 0, 813 ret = drmModeSetCrtc(drm.fd, drm.crtc_id[i], flip_fb->fb_id, 0, 0,
734 &drm.connector_id[i], 1, drm.mode[i]); 814 &drm.connector_id[i], 1, drm.mode[i]);
735 if (ret) { 815 if (ret) {
736 printf("display %d failed to set mode: %s\n", i, strerror(errno)); 816 printf("display %d failed to set mode: %s\n", i, strerror(errno));
@@ -738,7 +818,7 @@ int main(int argc, char *argv[])
738 } 818 }
739 } 819 }
740 } else { 820 } else {
741 ret = drmModeSetCrtc(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id, 821 ret = drmModeSetCrtc(drm.fd, drm.crtc_id[DISP_ID], flip_fb->fb_id,
742 0, 0, &drm.connector_id[DISP_ID], 1, drm.mode[DISP_ID]); 822 0, 0, &drm.connector_id[DISP_ID], 1, drm.mode[DISP_ID]);
743 if (ret) { 823 if (ret) {
744 printf("display %d failed to set mode: %s\n", DISP_ID, strerror(errno)); 824 printf("display %d failed to set mode: %s\n", DISP_ID, strerror(errno));
@@ -747,27 +827,34 @@ int main(int argc, char *argv[])
747 } 827 }
748 828
749 while (frame_count != 0) { 829 while (frame_count != 0) {
750 struct gbm_bo *next_bo; 830 struct gbm_bo *next_bo[THR_CNT];
751 int waiting_for_flip = 1; 831 int waiting_for_flip = 1;
752 832
753 draw(i++); 833 for(count = 0; count < THR_CNT; count++) {
754 834 sem_wait(&p[count].render);
755 eglSwapBuffers(gl.display, gl.surface); 835 next_bo[count] = gbm_surface_lock_front_buffer(gbm.surface[count]);
756 next_bo = gbm_surface_lock_front_buffer(gbm.surface); 836 fb[count] = drm_fb_get_from_bo(next_bo[count]);
757 fb = drm_fb_get_from_bo(next_bo); 837
758 838 printc("#### locked %d buffer\n", count);
759 /* 839 if(count < drm.num_planes) {
760 * Here you could also update drm plane layers if you want 840 ret = drmModeSetPlane(drm.fd, drm.plane_id[count], drm.crtc_id[DISP_ID], fb[count]->fb_id, 0, count*CONFIG_WIDTH + count*30, 0, CONFIG_WIDTH, CONFIG_HEIGHT, 0, 0, CONFIG_WIDTH << 16, CONFIG_HEIGHT << 16);
761 * hw composition 841 if (ret) {
762 */ 842 printf("failed to set plane: %s\n", strerror(errno));
843 return -1;
844 }
845 }
846 }
763 847
764 ret = drmModePageFlip(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id, 848 printc("#### set plane completed\n");
849 ret = drmModePageFlip(drm.fd, drm.crtc_id[DISP_ID], flip_fb->fb_id,
765 DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip); 850 DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
766 if (ret) { 851 if (ret) {
767 printf("failed to queue page flip: %s\n", strerror(errno)); 852 printf("failed to queue page flip: %s\n", strerror(errno));
768 return -1; 853 return -1;
769 } 854 }
770 855
856 printc("#### page flip completed\n");
857
771 while (waiting_for_flip) { 858 while (waiting_for_flip) {
772 ret = select(drm.fd + 1, &fds, NULL, NULL, NULL); 859 ret = select(drm.fd + 1, &fds, NULL, NULL, NULL);
773 if (ret < 0) { 860 if (ret < 0) {
@@ -782,14 +869,25 @@ int main(int argc, char *argv[])
782 drmHandleEvent(drm.fd, &evctx); 869 drmHandleEvent(drm.fd, &evctx);
783 } 870 }
784 871
785 /* release last buffer to render on again: */ 872 printc("#### page flip callback completed\n");
786 gbm_surface_release_buffer(gbm.surface, bo); 873
787 bo = next_bo; 874 for (count = 0; count < THR_CNT; count++) {
875 gbm_surface_release_buffer(gbm.surface[count], next_bo[count]);
876 sem_post(&p[count].disp);
877 printc("#### released %d buffer\n", count);
878 }
788 879
789 if(frame_count >= 0) 880 if(frame_count >= 0)
790 frame_count--; 881 frame_count--;
791 } 882 }
792 883
884
885 for(count = 0; count < THR_CNT; count++) {
886 p[count].running = false;
887 pthread_join(draw_thread[count], NULL);
888 }
889
890
793 cleanup_kmscube(); 891 cleanup_kmscube();
794 printf("\n Exiting kmscube \n"); 892 printf("\n Exiting kmscube \n");
795 893