summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 1c8a0d2)
raw | patch | inline | side by side (parent: 1c8a0d2)
author | Anand Balagopalakrishnan <anandb@ti.com> | |
Tue, 15 Dec 2015 07:24:41 +0000 (12:54 +0530) | ||
committer | Subhajit Paul <a0132170@ti.com> | |
Wed, 16 Dec 2015 13:05:56 +0000 (18:35 +0530) |
Signed-off-by: Anand Balagopalakrishnan <anandb@ti.com>
Makefile.am | patch | blob | history | |
kmscube.c | [changed mode: 0644->0755] | patch | blob | history |
diff --git a/Makefile.am b/Makefile.am
index f28269dcd154811c52ed9012598baa13c755ce6f..62e940c20c6006f1fc8663d404e1adfface8f6a5 100644 (file)
--- a/Makefile.am
+++ b/Makefile.am
$(GLES2_LIBS)
kmscube_CFLAGS = \
- -O0 -g -lm \
+ -O0 -g -lm -lrt -lpthread \
$(DRM_CFLAGS) \
$(GBM_CFLAGS) \
$(EGL_CFLAGS) \
diff --git a/kmscube.c b/kmscube.c
--- a/kmscube.c
+++ b/kmscube.c
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
+#include <pthread.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <gbm.h>
+#include <time.h>
+#include <semaphore.h>
#include "esUtil.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#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)
+#define printc(fmt, ...)
#define MAX_DISPLAYS (4)
+#define MAX_PLANES (4)
+#define CONFIG_WIDTH (320)
+#define CONFIG_HEIGHT (240)
uint8_t DISP_ID = 0;
uint8_t all_display = 0;
int8_t connector_id = -1;
-static struct {
+struct gl {
EGLDisplay display;
EGLConfig config;
EGLContext context;
GLuint vbo;
GLuint positionsoffset, colorsoffset, normalsoffset;
GLuint vertex_shader, fragment_shader;
-} gl;
+
+};
+
+struct gl_params {
+ EGLNativeDisplayType display;
+ EGLNativeWindowType window;
+ uint32_t width;
+ uint32_t height;
+ int32_t frame_count;
+ bool running;
+ sem_t render;
+ sem_t disp;
+};
static struct {
struct gbm_device *dev;
- struct gbm_surface *surface;
+ struct gbm_surface *surface[8];
+ struct gbm_bo *flip_bo;
+ uint32_t count;
} gbm;
static struct {
int fd;
uint32_t ndisp;
uint32_t crtc_id[MAX_DISPLAYS];
+ uint32_t plane_id[MAX_PLANES];
+ uint32_t num_planes;
uint32_t connector_id[MAX_DISPLAYS];
uint32_t resource_id;
uint32_t encoder[MAX_DISPLAYS];
uint32_t fb_id;
};
-static int init_drm(void)
+static void exit_gl(void *arg)
{
- static const char *modules[] = {
- "omapdrm", "i915", "radeon", "nouveau", "vmwgfx", "exynos"
- };
- drmModeRes *resources;
- drmModeConnector *connector = NULL;
- drmModeEncoder *encoder = NULL;
- int i, j;
- uint32_t maxRes, curRes;
-
- for (i = 0; i < ARRAY_SIZE(modules); i++) {
- printf("trying to load module %s...", modules[i]);
- drm.fd = drmOpen(modules[i], NULL);
- if (drm.fd < 0) {
- printf("failed.\n");
- } else {
- printf("success.\n");
- break;
- }
- }
-
- if (drm.fd < 0) {
- printf("could not open drm device\n");
- return -1;
- }
-
- resources = drmModeGetResources(drm.fd);
- if (!resources) {
- printf("drmModeGetResources failed: %s\n", strerror(errno));
- return -1;
- }
- drm.resource_id = (uint32_t) resources;
-
- /* find a connected connector: */
- for (i = 0; i < resources->count_connectors; i++) {
- connector = drmModeGetConnector(drm.fd, resources->connectors[i]);
- if (connector->connection == DRM_MODE_CONNECTED) {
- /* choose the first supported mode */
- drm.mode[drm.ndisp] = &connector->modes[0];
- drm.connector_id[drm.ndisp] = connector->connector_id;
-
- for (j=0; j<resources->count_encoders; j++) {
- encoder = drmModeGetEncoder(drm.fd, resources->encoders[j]);
- if (encoder->encoder_id == connector->encoder_id)
- break;
-
- drmModeFreeEncoder(encoder);
- encoder = NULL;
- }
-
- if (!encoder) {
- printf("no encoder!\n");
- return -1;
- }
-
- drm.encoder[drm.ndisp] = (uint32_t) encoder;
- drm.crtc_id[drm.ndisp] = encoder->crtc_id;
- drm.connectors[drm.ndisp] = connector;
-
- printf("### Display [%d]: CRTC = %d, Connector = %d\n", drm.ndisp, drm.crtc_id[drm.ndisp], drm.connector_id[drm.ndisp]);
- 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);
- 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);
- 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);
-
- /* If a connector_id is specified, use the corresponding display */
- if ((connector_id != -1) && (connector_id == drm.connector_id[drm.ndisp]))
- DISP_ID = drm.ndisp;
-
- /* If all displays are enabled, choose the connector with maximum
- * resolution as the primary display */
- if (all_display) {
- maxRes = drm.mode[DISP_ID]->vdisplay * drm.mode[DISP_ID]->hdisplay;
- curRes = drm.mode[drm.ndisp]->vdisplay * drm.mode[drm.ndisp]->hdisplay;
-
- if (curRes > maxRes)
- DISP_ID = drm.ndisp;
- }
-
- drm.ndisp++;
- } else {
- drmModeFreeConnector(connector);
- }
- }
-
- if (drm.ndisp == 0) {
- /* we could be fancy and listen for hotplug events and wait for
- * a connector..
- */
- printf("no connected connector!\n");
- return -1;
- }
-
- return 0;
-}
-
-static int init_gbm(void)
-{
- gbm.dev = gbm_create_device(drm.fd);
-
- gbm.surface = gbm_surface_create(gbm.dev,
- drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay,
- GBM_FORMAT_XRGB8888,
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
- if (!gbm.surface) {
- printf("failed to create gbm surface\n");
- return -1;
- }
-
- return 0;
+ struct gl *gl = arg;
+
+ glDeleteProgram(gl->program);
+ glDeleteBuffers(1, &gl->vbo);
+ glDeleteShader(gl->fragment_shader);
+ glDeleteShader(gl->vertex_shader);
+ eglDestroySurface(gl->display, gl->surface);
+ eglDestroyContext(gl->display, gl->context);
+ eglTerminate(gl->display);
+ return;
}
-static int init_gl(void)
+static void *gl_thread (void *arg)
{
EGLint major, minor, n;
GLint ret;
+ struct gl *gl;
+ struct gl_params *params = arg;
+ uint32_t frame_count = params->frame_count;
static const GLfloat vVertices[] = {
// front
EGL_GREEN_SIZE, 1,
EGL_BLUE_SIZE, 1,
EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
"{ \n"
" gl_FragColor = vVaryingColor; \n"
"} \n";
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ gl = calloc(1, sizeof(struct gl));
+ if(!gl) {
+ printf("GL memory allocation failed\n");
+ return NULL;
+ }
+
+ pthread_cleanup_push(exit_gl, gl);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- gl.display = eglGetDisplay(gbm.dev);
+ gl->display = eglGetDisplay(params->display);
- if (!eglInitialize(gl.display, &major, &minor)) {
+ if (!eglInitialize(gl->display, &major, &minor)) {
printf("failed to initialize\n");
- return -1;
+ return NULL;
}
- printf("Using display %p with EGL version %d.%d\n",
- gl.display, major, minor);
-
- printf("EGL Version \"%s\"\n", eglQueryString(gl.display, EGL_VERSION));
- printf("EGL Vendor \"%s\"\n", eglQueryString(gl.display, EGL_VENDOR));
- printf("EGL Extensions \"%s\"\n", eglQueryString(gl.display, EGL_EXTENSIONS));
-
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
printf("failed to bind api EGL_OPENGL_ES_API\n");
- return -1;
+ return NULL;
}
- if (!eglChooseConfig(gl.display, config_attribs, &gl.config, 1, &n) || n != 1) {
+ if (!eglChooseConfig(gl->display, config_attribs, &gl->config, 1, &n) || n != 1) {
printf("failed to choose config: %d\n", n);
- return -1;
+ return NULL;
}
- gl.context = eglCreateContext(gl.display, gl.config,
+ gl->context = eglCreateContext(gl->display, gl->config,
EGL_NO_CONTEXT, context_attribs);
- if (gl.context == NULL) {
+ if (gl->context == NULL) {
printf("failed to create context\n");
- return -1;
+ return NULL;
}
- gl.surface = eglCreateWindowSurface(gl.display, gl.config, gbm.surface, NULL);
- if (gl.surface == EGL_NO_SURFACE) {
+ gl->surface = eglCreateWindowSurface(gl->display, gl->config, params->window, NULL);
+ if (gl->surface == EGL_NO_SURFACE) {
printf("failed to create egl surface\n");
- return -1;
+ return NULL;
}
/* connect the context to the surface */
- eglMakeCurrent(gl.display, gl.surface, gl.surface, gl.context);
+ eglMakeCurrent(gl->display, gl->surface, gl->surface, gl->context);
- gl.vertex_shader = glCreateShader(GL_VERTEX_SHADER);
+ gl->vertex_shader = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(gl.vertex_shader, 1, &vertex_shader_source, NULL);
- glCompileShader(gl.vertex_shader);
+ glShaderSource(gl->vertex_shader, 1, &vertex_shader_source, NULL);
+ glCompileShader(gl->vertex_shader);
- glGetShaderiv(gl.vertex_shader, GL_COMPILE_STATUS, &ret);
+ glGetShaderiv(gl->vertex_shader, GL_COMPILE_STATUS, &ret);
if (!ret) {
char *log;
printf("vertex shader compilation failed!:\n");
- glGetShaderiv(gl.vertex_shader, GL_INFO_LOG_LENGTH, &ret);
+ glGetShaderiv(gl->vertex_shader, GL_INFO_LOG_LENGTH, &ret);
if (ret > 1) {
log = malloc(ret);
- glGetShaderInfoLog(gl.vertex_shader, ret, NULL, log);
+ glGetShaderInfoLog(gl->vertex_shader, ret, NULL, log);
printf("%s", log);
}
- return -1;
+ return NULL;
}
- gl.fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
+ gl->fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(gl.fragment_shader, 1, &fragment_shader_source, NULL);
- glCompileShader(gl.fragment_shader);
+ glShaderSource(gl->fragment_shader, 1, &fragment_shader_source, NULL);
+ glCompileShader(gl->fragment_shader);
- glGetShaderiv(gl.fragment_shader, GL_COMPILE_STATUS, &ret);
+ glGetShaderiv(gl->fragment_shader, GL_COMPILE_STATUS, &ret);
if (!ret) {
char *log;
printf("fragment shader compilation failed!:\n");
- glGetShaderiv(gl.fragment_shader, GL_INFO_LOG_LENGTH, &ret);
+ glGetShaderiv(gl->fragment_shader, GL_INFO_LOG_LENGTH, &ret);
if (ret > 1) {
log = malloc(ret);
- glGetShaderInfoLog(gl.fragment_shader, ret, NULL, log);
+ glGetShaderInfoLog(gl->fragment_shader, ret, NULL, log);
printf("%s", log);
}
- return -1;
+ return NULL;
}
- gl.program = glCreateProgram();
+ gl->program = glCreateProgram();
- glAttachShader(gl.program, gl.vertex_shader);
- glAttachShader(gl.program, gl.fragment_shader);
+ glAttachShader(gl->program, gl->vertex_shader);
+ glAttachShader(gl->program, gl->fragment_shader);
- glBindAttribLocation(gl.program, 0, "in_position");
- glBindAttribLocation(gl.program, 1, "in_normal");
- glBindAttribLocation(gl.program, 2, "in_color");
+ glBindAttribLocation(gl->program, 0, "in_position");
+ glBindAttribLocation(gl->program, 1, "in_normal");
+ glBindAttribLocation(gl->program, 2, "in_color");
- glLinkProgram(gl.program);
+ glLinkProgram(gl->program);
- glGetProgramiv(gl.program, GL_LINK_STATUS, &ret);
+ glGetProgramiv(gl->program, GL_LINK_STATUS, &ret);
if (!ret) {
char *log;
printf("program linking failed!:\n");
- glGetProgramiv(gl.program, GL_INFO_LOG_LENGTH, &ret);
+ glGetProgramiv(gl->program, GL_INFO_LOG_LENGTH, &ret);
if (ret > 1) {
log = malloc(ret);
- glGetProgramInfoLog(gl.program, ret, NULL, log);
+ glGetProgramInfoLog(gl->program, ret, NULL, log);
printf("%s", log);
}
- return -1;
+ return NULL;
}
- glUseProgram(gl.program);
+ glUseProgram(gl->program);
- gl.modelviewmatrix = glGetUniformLocation(gl.program, "modelviewMatrix");
- gl.modelviewprojectionmatrix = glGetUniformLocation(gl.program, "modelviewprojectionMatrix");
- gl.normalmatrix = glGetUniformLocation(gl.program, "normalMatrix");
+ gl->modelviewmatrix = glGetUniformLocation(gl->program, "modelviewMatrix");
+ gl->modelviewprojectionmatrix = glGetUniformLocation(gl->program, "modelviewprojectionMatrix");
+ gl->normalmatrix = glGetUniformLocation(gl->program, "normalMatrix");
- glViewport(0, 0, drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay);
+ glViewport(0, 0, params->width, params->height);
glEnable(GL_CULL_FACE);
- gl.positionsoffset = 0;
- gl.colorsoffset = sizeof(vVertices);
- gl.normalsoffset = sizeof(vVertices) + sizeof(vColors);
- glGenBuffers(1, &gl.vbo);
- glBindBuffer(GL_ARRAY_BUFFER, gl.vbo);
+ gl->positionsoffset = 0;
+ gl->colorsoffset = sizeof(vVertices);
+ gl->normalsoffset = sizeof(vVertices) + sizeof(vColors);
+ glGenBuffers(1, &gl->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, gl->vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices) + sizeof(vColors) + sizeof(vNormals), 0, GL_STATIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, gl.positionsoffset, sizeof(vVertices), &vVertices[0]);
- glBufferSubData(GL_ARRAY_BUFFER, gl.colorsoffset, sizeof(vColors), &vColors[0]);
- glBufferSubData(GL_ARRAY_BUFFER, gl.normalsoffset, sizeof(vNormals), &vNormals[0]);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl.positionsoffset);
+ glBufferSubData(GL_ARRAY_BUFFER, gl->positionsoffset, sizeof(vVertices), &vVertices[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, gl->colorsoffset, sizeof(vColors), &vColors[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, gl->normalsoffset, sizeof(vNormals), &vNormals[0]);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl->positionsoffset);
glEnableVertexAttribArray(0);
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl.normalsoffset);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl->normalsoffset);
glEnableVertexAttribArray(1);
- glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl.colorsoffset);
+ glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)gl->colorsoffset);
glEnableVertexAttribArray(2);
+ int i = 0;
+ while (frame_count != 0 && params->running == true) {
+ ESMatrix modelview;
+
+ /* clear the color buffer */
+
+ glClearColor(0.5, 0.5, 0.5, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ esMatrixLoadIdentity(&modelview);
+ esTranslate(&modelview, 0.0f, 0.0f, -8.0f);
+ esRotate(&modelview, 45.0f + (0.25f * i), 1.0f, 0.0f, 0.0f);
+ esRotate(&modelview, 45.0f - (0.5f * i), 0.0f, 1.0f, 0.0f);
+ esRotate(&modelview, 10.0f + (0.15f * i), 0.0f, 0.0f, 1.0f);
+
+ GLfloat aspect = (GLfloat)(drm.mode[DISP_ID]->vdisplay) / (GLfloat)(drm.mode[DISP_ID]->hdisplay);
+
+ ESMatrix projection;
+ esMatrixLoadIdentity(&projection);
+ esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f);
+
+ ESMatrix modelviewprojection;
+ esMatrixLoadIdentity(&modelviewprojection);
+ esMatrixMultiply(&modelviewprojection, &modelview, &projection);
+
+ float normal[9];
+ normal[0] = modelview.m[0][0];
+ normal[1] = modelview.m[0][1];
+ normal[2] = modelview.m[0][2];
+ normal[3] = modelview.m[1][0];
+ normal[4] = modelview.m[1][1];
+ normal[5] = modelview.m[1][2];
+ normal[6] = modelview.m[2][0];
+ normal[7] = modelview.m[2][1];
+ normal[8] = modelview.m[2][2];
+
+ glUniformMatrix4fv(gl->modelviewmatrix, 1, GL_FALSE, &modelview.m[0][0]);
+ glUniformMatrix4fv(gl->modelviewprojectionmatrix, 1, GL_FALSE, &modelviewprojection.m[0][0]);
+ glUniformMatrix3fv(gl->normalmatrix, 1, GL_FALSE, normal);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
+
+ eglSwapBuffers(gl->display, gl->surface);
+ printc("#### swap buffers\n");
+
+ sem_post(¶ms->render);
+
+ i++;
+ frame_count--;
+
+ sem_wait(¶ms->disp);
+
+ }
+ pthread_cleanup_pop(1);
+
+}
+
+#define THR_CNT (3)
+pthread_t draw_thread[MAX_PLANES];
+uint32_t num_threads;
+
+static int init_drm(void)
+{
+ static const char *modules[] = {
+ "omapdrm", "i915", "radeon", "nouveau", "vmwgfx", "exynos"
+ };
+ drmModeRes *resources;
+ drmModePlaneResPtr planeRes;
+ drmModeConnector *connector = NULL;
+ drmModeEncoder *encoder = NULL;
+ int i, j;
+ uint32_t maxRes, curRes;
+
+ for (i = 0; i < ARRAY_SIZE(modules); i++) {
+ printf("trying to load module %s...", modules[i]);
+ drm.fd = drmOpen(modules[i], NULL);
+ if (drm.fd < 0) {
+ printf("failed.\n");
+ } else {
+ printf("success.\n");
+ break;
+ }
+ }
+
+ if (drm.fd < 0) {
+ printf("could not open drm device\n");
+ return -1;
+ }
+
+ resources = drmModeGetResources(drm.fd);
+ if (!resources) {
+ printf("drmModeGetResources failed: %s\n", strerror(errno));
+ return -1;
+ }
+ drm.resource_id = (uint32_t) resources;
+
+ /* find a connected connector: */
+ for (i = 0; i < resources->count_connectors; i++) {
+ connector = drmModeGetConnector(drm.fd, resources->connectors[i]);
+ if (connector->connection == DRM_MODE_CONNECTED) {
+ /* choose the first supported mode */
+ drm.mode[drm.ndisp] = &connector->modes[0];
+ drm.connector_id[drm.ndisp] = connector->connector_id;
+
+ for (j=0; j<resources->count_encoders; j++) {
+ encoder = drmModeGetEncoder(drm.fd, resources->encoders[j]);
+ if (encoder->encoder_id == connector->encoder_id)
+ break;
+
+ drmModeFreeEncoder(encoder);
+ encoder = NULL;
+ }
+
+ if (!encoder) {
+ printf("no encoder!\n");
+ return -1;
+ }
+
+ drm.encoder[drm.ndisp] = (uint32_t) encoder;
+ drm.crtc_id[drm.ndisp] = encoder->crtc_id;
+ drm.connectors[drm.ndisp] = connector;
+
+ printf("### Display [%d]: CRTC = %d, Connector = %d\n", drm.ndisp, drm.crtc_id[drm.ndisp], drm.connector_id[drm.ndisp]);
+ 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);
+ 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);
+ 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);
+
+ /* If a connector_id is specified, use the corresponding display */
+ if ((connector_id != -1) && (connector_id == drm.connector_id[drm.ndisp]))
+ DISP_ID = drm.ndisp;
+
+ /* If all displays are enabled, choose the connector with maximum
+ * resolution as the primary display */
+ if (all_display) {
+ maxRes = drm.mode[DISP_ID]->vdisplay * drm.mode[DISP_ID]->hdisplay;
+ curRes = drm.mode[drm.ndisp]->vdisplay * drm.mode[drm.ndisp]->hdisplay;
+
+ if (curRes > maxRes)
+ DISP_ID = drm.ndisp;
+ }
+
+ drm.ndisp++;
+ } else {
+ drmModeFreeConnector(connector);
+ }
+ }
+
+
+
+ if (drm.ndisp == 0) {
+ /* we could be fancy and listen for hotplug events and wait for
+ * a connector..
+ */
+ printf("no connected connector!\n");
+ return -1;
+ }
+
+ planeRes = drmModeGetPlaneResources (drm.fd);
+ for (i = 0; i < planeRes->count_planes; i++)
+ drm.plane_id[drm.num_planes++] = planeRes->planes[i];
+
return 0;
}
-static void exit_gbm(void)
+static int init_gbm(uint32_t surf_count, uint32_t width, uint32_t height)
{
- gbm_surface_destroy(gbm.surface);
- gbm_device_destroy(gbm.dev);
- return;
+ int count;
+
+ gbm.dev = gbm_create_device(drm.fd);
+ gbm.flip_bo = gbm_bo_create(gbm.dev,
+ drm.mode[DISP_ID]->hdisplay,
+ drm.mode[DISP_ID]->vdisplay,
+ GBM_FORMAT_XRGB8888,
+ GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+
+ for(count = 0; count < surf_count; count++) {
+ gbm.surface[count] = gbm_surface_create(gbm.dev,
+ width, height,
+ GBM_FORMAT_XRGB8888,
+ GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+ if (!gbm.surface[count]) {
+ printf("failed to create gbm surface\n");
+ return -1;
+ }
+ gbm.count++;
+ }
+
+ return 0;
}
-static void exit_gl(void)
+
+static void exit_gbm(void)
{
- glDeleteProgram(gl.program);
- glDeleteBuffers(1, &gl.vbo);
- glDeleteShader(gl.fragment_shader);
- glDeleteShader(gl.vertex_shader);
- eglDestroySurface(gl.display, gl.surface);
- eglDestroyContext(gl.display, gl.context);
- eglTerminate(gl.display);
+ while(gbm.count--)
+ gbm_surface_destroy(gbm.surface[gbm.count]);
+ gbm_bo_destroy(gbm.flip_bo);
+ gbm_device_destroy(gbm.dev);
return;
}
void cleanup_kmscube(void)
{
- exit_gl();
+ while(num_threads--) {
+ pthread_cancel(draw_thread[num_threads]);
+ pthread_join(draw_thread[num_threads], NULL);
+ }
exit_gbm();
exit_drm();
printf("Cleanup of GL, GBM and DRM completed\n");
return;
}
-static void draw(uint32_t i)
-{
- ESMatrix modelview;
-
- /* clear the color buffer */
- glClearColor(0.5, 0.5, 0.5, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- esMatrixLoadIdentity(&modelview);
- esTranslate(&modelview, 0.0f, 0.0f, -8.0f);
- esRotate(&modelview, 45.0f + (0.25f * i), 1.0f, 0.0f, 0.0f);
- esRotate(&modelview, 45.0f - (0.5f * i), 0.0f, 1.0f, 0.0f);
- esRotate(&modelview, 10.0f + (0.15f * i), 0.0f, 0.0f, 1.0f);
-
- GLfloat aspect = (GLfloat)(drm.mode[DISP_ID]->vdisplay) / (GLfloat)(drm.mode[DISP_ID]->hdisplay);
-
- ESMatrix projection;
- esMatrixLoadIdentity(&projection);
- esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f);
-
- ESMatrix modelviewprojection;
- esMatrixLoadIdentity(&modelviewprojection);
- esMatrixMultiply(&modelviewprojection, &modelview, &projection);
-
- float normal[9];
- normal[0] = modelview.m[0][0];
- normal[1] = modelview.m[0][1];
- normal[2] = modelview.m[0][2];
- normal[3] = modelview.m[1][0];
- normal[4] = modelview.m[1][1];
- normal[5] = modelview.m[1][2];
- normal[6] = modelview.m[2][0];
- normal[7] = modelview.m[2][1];
- normal[8] = modelview.m[2][2];
-
- glUniformMatrix4fv(gl.modelviewmatrix, 1, GL_FALSE, &modelview.m[0][0]);
- glUniformMatrix4fv(gl.modelviewprojectionmatrix, 1, GL_FALSE, &modelviewprojection.m[0][0]);
- glUniformMatrix3fv(gl.normalmatrix, 1, GL_FALSE, normal);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
-}
-
static void
drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
{
.version = DRM_EVENT_CONTEXT_VERSION,
.page_flip_handler = page_flip_handler,
};
- struct gbm_bo *bo;
- struct drm_fb *fb;
+ struct gbm_bo *bo = NULL;
+ struct drm_fb *flip_fb;
+ struct drm_fb *fb[THR_CNT];
uint32_t i = 0;
int ret;
int opt;
int frame_count = -1;
+ int count;
signal(SIGINT, kms_signalhandler);
signal(SIGTERM, kms_signalhandler);
FD_ZERO(&fds);
FD_SET(drm.fd, &fds);
- ret = init_gbm();
+ ret = init_gbm(THR_CNT, CONFIG_WIDTH, CONFIG_HEIGHT);
if (ret) {
printf("failed to initialize GBM\n");
return ret;
}
- ret = init_gl();
- if (ret) {
- printf("failed to initialize EGL\n");
- return ret;
+ struct gl_params p[THR_CNT];
+ for(count = 0; count < THR_CNT; count++) {
+ p[count].display = gbm.dev;
+ p[count].window = gbm.surface[count];
+ p[count].frame_count = frame_count;
+ p[count].running = true;
+ p[count].width = CONFIG_WIDTH;
+ p[count].height = CONFIG_HEIGHT;
+ sem_init(&p[count].render, 0, 0);
+ sem_init(&p[count].disp, 0, 0);
+ ret = pthread_create(&draw_thread[num_threads++], NULL, gl_thread, &p[count]);
+ if (ret) {
+ printf("failed to initialize EGL\n");
+ return ret;
+ }
}
- /* clear the color buffer */
- glClearColor(0.5, 0.5, 0.5, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
- eglSwapBuffers(gl.display, gl.surface);
- bo = gbm_surface_lock_front_buffer(gbm.surface);
- fb = drm_fb_get_from_bo(bo);
/* set mode: */
+ flip_fb = drm_fb_get_from_bo(gbm.flip_bo);
if (all_display) {
for (i=0; i<drm.ndisp; i++) {
- ret = drmModeSetCrtc(drm.fd, drm.crtc_id[i], fb->fb_id, 0, 0,
+ ret = drmModeSetCrtc(drm.fd, drm.crtc_id[i], flip_fb->fb_id, 0, 0,
&drm.connector_id[i], 1, drm.mode[i]);
if (ret) {
printf("display %d failed to set mode: %s\n", i, strerror(errno));
}
}
} else {
- ret = drmModeSetCrtc(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id,
+ ret = drmModeSetCrtc(drm.fd, drm.crtc_id[DISP_ID], flip_fb->fb_id,
0, 0, &drm.connector_id[DISP_ID], 1, drm.mode[DISP_ID]);
if (ret) {
printf("display %d failed to set mode: %s\n", DISP_ID, strerror(errno));
}
while (frame_count != 0) {
- struct gbm_bo *next_bo;
+ struct gbm_bo *next_bo[THR_CNT];
int waiting_for_flip = 1;
- draw(i++);
-
- eglSwapBuffers(gl.display, gl.surface);
- next_bo = gbm_surface_lock_front_buffer(gbm.surface);
- fb = drm_fb_get_from_bo(next_bo);
-
- /*
- * Here you could also update drm plane layers if you want
- * hw composition
- */
+ for(count = 0; count < THR_CNT; count++) {
+ sem_wait(&p[count].render);
+ next_bo[count] = gbm_surface_lock_front_buffer(gbm.surface[count]);
+ fb[count] = drm_fb_get_from_bo(next_bo[count]);
+
+ printc("#### locked %d buffer\n", count);
+ if(count < drm.num_planes) {
+ 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);
+ if (ret) {
+ printf("failed to set plane: %s\n", strerror(errno));
+ return -1;
+ }
+ }
+ }
- ret = drmModePageFlip(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id,
+ printc("#### set plane completed\n");
+ ret = drmModePageFlip(drm.fd, drm.crtc_id[DISP_ID], flip_fb->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
if (ret) {
printf("failed to queue page flip: %s\n", strerror(errno));
return -1;
}
+ printc("#### page flip completed\n");
+
while (waiting_for_flip) {
ret = select(drm.fd + 1, &fds, NULL, NULL, NULL);
if (ret < 0) {
drmHandleEvent(drm.fd, &evctx);
}
- /* release last buffer to render on again: */
- gbm_surface_release_buffer(gbm.surface, bo);
- bo = next_bo;
+ printc("#### page flip callback completed\n");
+
+ for (count = 0; count < THR_CNT; count++) {
+ gbm_surface_release_buffer(gbm.surface[count], next_bo[count]);
+ sem_post(&p[count].disp);
+ printc("#### released %d buffer\n", count);
+ }
if(frame_count >= 0)
frame_count--;
}
+
+ for(count = 0; count < THR_CNT; count++) {
+ p[count].running = false;
+ pthread_join(draw_thread[count], NULL);
+ }
+
+
cleanup_kmscube();
printf("\n Exiting kmscube \n");