diff options
author | Anand Balagopalakrishnan | 2015-12-15 01:24:41 -0600 |
---|---|---|
committer | Subhajit Paul | 2015-12-16 07:05:56 -0600 |
commit | c294541187a91528225a6dd0e9a9c7a20968cd39 (patch) | |
tree | b2d5abcba0ad369dcf2e14e28f756a1f13fa9918 | |
parent | 1c8a0d26c5b1918432fd94d2ac9894b3dcdb2814 (diff) | |
download | kmscube-next.tar.gz kmscube-next.tar.xz kmscube-next.zip |
multithreaded kmscubenext
Signed-off-by: Anand Balagopalakrishnan <anandb@ti.com>
-rw-r--r-- | Makefile.am | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | kmscube.c | 626 |
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 | ||
35 | kmscube_CFLAGS = \ | 35 | kmscube_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) \ |
@@ -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) | ||
47 | uint8_t DISP_ID = 0; | 56 | uint8_t DISP_ID = 0; |
48 | uint8_t all_display = 0; | 57 | uint8_t all_display = 0; |
49 | int8_t connector_id = -1; | 58 | int8_t connector_id = -1; |
50 | 59 | ||
51 | static struct { | 60 | struct 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 | |||
73 | struct 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 | ||
63 | static struct { | 84 | static 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 | ||
68 | static struct { | 91 | static 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 | ||
84 | static int init_drm(void) | 109 | static 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 | |||
180 | static 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 | ||
196 | static int init_gl(void) | 123 | static 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(¶ms->render); | ||
467 | |||
468 | i++; | ||
469 | frame_count--; | ||
470 | |||
471 | sem_wait(¶ms->disp); | ||
472 | |||
473 | } | ||
474 | pthread_cleanup_pop(1); | ||
475 | |||
476 | } | ||
477 | |||
478 | #define THR_CNT (3) | ||
479 | pthread_t draw_thread[MAX_PLANES]; | ||
480 | uint32_t num_threads; | ||
481 | |||
482 | static 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 | ||
486 | static void exit_gbm(void) | 585 | static 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 | ||
493 | static void exit_gl(void) | 611 | |
612 | static 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 | ||
521 | void cleanup_kmscube(void) | 637 | void 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 | ||
530 | static 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 | |||
577 | static void | 649 | static void |
578 | drm_fb_destroy_callback(struct gbm_bo *bo, void *data) | 650 | drm_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 | ||