diff --git a/kmscube.c b/kmscube.c
index 5ae2b2eb47535e10b879b725289fbb1b5b4f66fb..919b3e7e90f3a37fc251cf0d1a24100c3133f4e5 100644 (file)
--- a/kmscube.c
+++ b/kmscube.c
/*
+ * Copyright (c) 2012 Arvin Schnell <arvin.schnell@gmail.com>
* Copyright (c) 2012 Rob Clark <rob@ti.com>
+ * Copyright (c) 2013 Anand Balagopalakrishnan <anandb@ti.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* DEALINGS IN THE SOFTWARE.
*/
+/* Based on a egl cube test app originally written by Arvin Schnell */
+
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
+#include <signal.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "esUtil.h"
-
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#define MAX_DISPLAYS (4)
+uint8_t DISP_ID = 0;
+uint8_t all_display = 0;
+int8_t connector_id = -1;
static struct {
EGLDisplay display;
EGLSurface surface;
GLuint program;
GLint modelviewmatrix, modelviewprojectionmatrix, normalmatrix;
+ GLuint vbo;
+ GLuint positionsoffset, colorsoffset, normalsoffset;
+ GLuint vertex_shader, fragment_shader;
} gl;
static struct {
static struct {
int fd;
- drmModeModeInfo *mode;
- uint32_t crtc_id;
- uint32_t connector_id;
+ uint32_t ndisp;
+ uint32_t crtc_id[MAX_DISPLAYS];
+ uint32_t connector_id[MAX_DISPLAYS];
+ uint32_t resource_id;
+ uint32_t encoder[MAX_DISPLAYS];
+ drmModeModeInfo *mode[MAX_DISPLAYS];
+ drmModeConnector *connectors[MAX_DISPLAYS];
} drm;
struct drm_fb {
static int init_drm(void)
{
static const char *modules[] = {
- "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos"
+ "omapdrm", "tilcdc", "i915", "radeon", "nouveau", "vmwgfx", "exynos"
};
drmModeRes *resources;
drmModeConnector *connector = NULL;
drmModeEncoder *encoder = NULL;
- int i, area;
+ int i, j;
+ uint32_t maxRes, curRes;
for (i = 0; i < ARRAY_SIZE(modules); i++) {
printf("trying to load module %s...", modules[i]);
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) {
- /* it's connected, let's use this! */
- break;
+ /* 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);
}
- drmModeFreeConnector(connector);
- connector = NULL;
}
- if (!connector) {
+ if (drm.ndisp == 0) {
/* we could be fancy and listen for hotplug events and wait for
* a connector..
*/
return -1;
}
- /* find highest resolution mode: */
- for (i = 0, area = 0; i < connector->count_modes; i++) {
- drmModeModeInfo *current_mode = &connector->modes[i];
- int current_area = current_mode->hdisplay * current_mode->vdisplay;
- if (current_area > area) {
- drm.mode = current_mode;
- area = current_area;
- }
- }
-
- if (!drm.mode) {
- printf("could not find mode!\n");
- return -1;
- }
-
- /* find encoder: */
- for (i = 0; i < resources->count_encoders; i++) {
- encoder = drmModeGetEncoder(drm.fd, resources->encoders[i]);
- if (encoder->encoder_id == connector->encoder_id)
- break;
- drmModeFreeEncoder(encoder);
- encoder = NULL;
- }
-
- if (!encoder) {
- printf("no encoder!\n");
- return -1;
- }
-
- drm.crtc_id = encoder->crtc_id;
- drm.connector_id = connector->connector_id;
-
return 0;
}
gbm.dev = gbm_create_device(drm.fd);
gbm.surface = gbm_surface_create(gbm.dev,
- drm.mode->hdisplay, drm.mode->vdisplay,
+ drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay,
GBM_FORMAT_XRGB8888,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!gbm.surface) {
static int init_gl(void)
{
EGLint major, minor, n;
- GLuint vertex_shader, fragment_shader;
GLint ret;
+ static const GLfloat vVertices[] = {
+ // front
+ -1.0f, -1.0f, +1.0f, // point blue
+ +1.0f, -1.0f, +1.0f, // point magenta
+ -1.0f, +1.0f, +1.0f, // point cyan
+ +1.0f, +1.0f, +1.0f, // point white
+ // back
+ +1.0f, -1.0f, -1.0f, // point red
+ -1.0f, -1.0f, -1.0f, // point black
+ +1.0f, +1.0f, -1.0f, // point yellow
+ -1.0f, +1.0f, -1.0f, // point green
+ // right
+ +1.0f, -1.0f, +1.0f, // point magenta
+ +1.0f, -1.0f, -1.0f, // point red
+ +1.0f, +1.0f, +1.0f, // point white
+ +1.0f, +1.0f, -1.0f, // point yellow
+ // left
+ -1.0f, -1.0f, -1.0f, // point black
+ -1.0f, -1.0f, +1.0f, // point blue
+ -1.0f, +1.0f, -1.0f, // point green
+ -1.0f, +1.0f, +1.0f, // point cyan
+ // top
+ -1.0f, +1.0f, +1.0f, // point cyan
+ +1.0f, +1.0f, +1.0f, // point white
+ -1.0f, +1.0f, -1.0f, // point green
+ +1.0f, +1.0f, -1.0f, // point yellow
+ // bottom
+ -1.0f, -1.0f, -1.0f, // point black
+ +1.0f, -1.0f, -1.0f, // point red
+ -1.0f, -1.0f, +1.0f, // point blue
+ +1.0f, -1.0f, +1.0f // point magenta
+ };
+
+ static const GLfloat vColors[] = {
+ // front
+ 0.0f, 0.0f, 1.0f, // blue
+ 1.0f, 0.0f, 1.0f, // magenta
+ 0.0f, 1.0f, 1.0f, // cyan
+ 1.0f, 1.0f, 1.0f, // white
+ // back
+ 1.0f, 0.0f, 0.0f, // red
+ 0.0f, 0.0f, 0.0f, // black
+ 1.0f, 1.0f, 0.0f, // yellow
+ 0.0f, 1.0f, 0.0f, // green
+ // right
+ 1.0f, 0.0f, 1.0f, // magenta
+ 1.0f, 0.0f, 0.0f, // red
+ 1.0f, 1.0f, 1.0f, // white
+ 1.0f, 1.0f, 0.0f, // yellow
+ // left
+ 0.0f, 0.0f, 0.0f, // black
+ 0.0f, 0.0f, 1.0f, // blue
+ 0.0f, 1.0f, 0.0f, // green
+ 0.0f, 1.0f, 1.0f, // cyan
+ // top
+ 0.0f, 1.0f, 1.0f, // cyan
+ 1.0f, 1.0f, 1.0f, // white
+ 0.0f, 1.0f, 0.0f, // green
+ 1.0f, 1.0f, 0.0f, // yellow
+ // bottom
+ 0.0f, 0.0f, 0.0f, // black
+ 1.0f, 0.0f, 0.0f, // red
+ 0.0f, 0.0f, 1.0f, // blue
+ 1.0f, 0.0f, 1.0f // magenta
+ };
+
+ static const GLfloat vNormals[] = {
+ // front
+ +0.0f, +0.0f, +1.0f, // forward
+ +0.0f, +0.0f, +1.0f, // forward
+ +0.0f, +0.0f, +1.0f, // forward
+ +0.0f, +0.0f, +1.0f, // forward
+ // back
+ +0.0f, +0.0f, -1.0f, // backbard
+ +0.0f, +0.0f, -1.0f, // backbard
+ +0.0f, +0.0f, -1.0f, // backbard
+ +0.0f, +0.0f, -1.0f, // backbard
+ // right
+ +1.0f, +0.0f, +0.0f, // right
+ +1.0f, +0.0f, +0.0f, // right
+ +1.0f, +0.0f, +0.0f, // right
+ +1.0f, +0.0f, +0.0f, // right
+ // left
+ -1.0f, +0.0f, +0.0f, // left
+ -1.0f, +0.0f, +0.0f, // left
+ -1.0f, +0.0f, +0.0f, // left
+ -1.0f, +0.0f, +0.0f, // left
+ // top
+ +0.0f, +1.0f, +0.0f, // up
+ +0.0f, +1.0f, +0.0f, // up
+ +0.0f, +1.0f, +0.0f, // up
+ +0.0f, +1.0f, +0.0f, // up
+ // bottom
+ +0.0f, -1.0f, +0.0f, // down
+ +0.0f, -1.0f, +0.0f, // down
+ +0.0f, -1.0f, +0.0f, // down
+ +0.0f, -1.0f, +0.0f // down
+ };
+
static const EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
eglMakeCurrent(gl.display, gl.surface, gl.surface, gl.context);
- vertex_shader = glCreateShader(GL_VERTEX_SHADER);
+ gl.vertex_shader = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
- glCompileShader(vertex_shader);
+ glShaderSource(gl.vertex_shader, 1, &vertex_shader_source, NULL);
+ glCompileShader(gl.vertex_shader);
- glGetShaderiv(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(vertex_shader, GL_INFO_LOG_LENGTH, &ret);
+ glGetShaderiv(gl.vertex_shader, GL_INFO_LOG_LENGTH, &ret);
if (ret > 1) {
log = malloc(ret);
- glGetShaderInfoLog(vertex_shader, ret, NULL, log);
+ glGetShaderInfoLog(gl.vertex_shader, ret, NULL, log);
printf("%s", log);
}
return -1;
}
- fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
+ gl.fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
- glCompileShader(fragment_shader);
+ glShaderSource(gl.fragment_shader, 1, &fragment_shader_source, NULL);
+ glCompileShader(gl.fragment_shader);
- glGetShaderiv(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(fragment_shader, GL_INFO_LOG_LENGTH, &ret);
+ glGetShaderiv(gl.fragment_shader, GL_INFO_LOG_LENGTH, &ret);
if (ret > 1) {
log = malloc(ret);
- glGetShaderInfoLog(fragment_shader, ret, NULL, log);
+ glGetShaderInfoLog(gl.fragment_shader, ret, NULL, log);
printf("%s", log);
}
gl.program = glCreateProgram();
- glAttachShader(gl.program, vertex_shader);
- glAttachShader(gl.program, 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");
gl.modelviewprojectionmatrix = glGetUniformLocation(gl.program, "modelviewprojectionMatrix");
gl.normalmatrix = glGetUniformLocation(gl.program, "normalMatrix");
- glViewport(0, 0, drm.mode->hdisplay, drm.mode->vdisplay);
+ glViewport(0, 0, drm.mode[DISP_ID]->hdisplay, drm.mode[DISP_ID]->vdisplay);
+ 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);
+ 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);
+ glEnableVertexAttribArray(0);
+ 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);
+ glEnableVertexAttribArray(2);
return 0;
}
-static void draw(uint32_t i)
+static void exit_gbm(void)
{
- ESMatrix modelview;
- static const GLfloat vVertices[] = {
- // front
- -1.0f, -1.0f, +1.0f, // point blue
- +1.0f, -1.0f, +1.0f, // point magenta
- -1.0f, +1.0f, +1.0f, // point cyan
- +1.0f, +1.0f, +1.0f, // point white
- // back
- +1.0f, -1.0f, -1.0f, // point red
- -1.0f, -1.0f, -1.0f, // point black
- +1.0f, +1.0f, -1.0f, // point yellow
- -1.0f, +1.0f, -1.0f, // point green
- // right
- +1.0f, -1.0f, +1.0f, // point magenta
- +1.0f, -1.0f, -1.0f, // point red
- +1.0f, +1.0f, +1.0f, // point white
- +1.0f, +1.0f, -1.0f, // point yellow
- // left
- -1.0f, -1.0f, -1.0f, // point black
- -1.0f, -1.0f, +1.0f, // point blue
- -1.0f, +1.0f, -1.0f, // point green
- -1.0f, +1.0f, +1.0f, // point cyan
- // top
- -1.0f, +1.0f, +1.0f, // point cyan
- +1.0f, +1.0f, +1.0f, // point white
- -1.0f, +1.0f, -1.0f, // point green
- +1.0f, +1.0f, -1.0f, // point yellow
- // bottom
- -1.0f, -1.0f, -1.0f, // point black
- +1.0f, -1.0f, -1.0f, // point red
- -1.0f, -1.0f, +1.0f, // point blue
- +1.0f, -1.0f, +1.0f // point magenta
- };
+ gbm_surface_destroy(gbm.surface);
+ gbm_device_destroy(gbm.dev);
+ return;
+}
- static const GLfloat vColors[] = {
- // front
- 0.0f, 0.0f, 1.0f, // blue
- 1.0f, 0.0f, 1.0f, // magenta
- 0.0f, 1.0f, 1.0f, // cyan
- 1.0f, 1.0f, 1.0f, // white
- // back
- 1.0f, 0.0f, 0.0f, // red
- 0.0f, 0.0f, 0.0f, // black
- 1.0f, 1.0f, 0.0f, // yellow
- 0.0f, 1.0f, 0.0f, // green
- // right
- 1.0f, 0.0f, 1.0f, // magenta
- 1.0f, 0.0f, 0.0f, // red
- 1.0f, 1.0f, 1.0f, // white
- 1.0f, 1.0f, 0.0f, // yellow
- // left
- 0.0f, 0.0f, 0.0f, // black
- 0.0f, 0.0f, 1.0f, // blue
- 0.0f, 1.0f, 0.0f, // green
- 0.0f, 1.0f, 1.0f, // cyan
- // top
- 0.0f, 1.0f, 1.0f, // cyan
- 1.0f, 1.0f, 1.0f, // white
- 0.0f, 1.0f, 0.0f, // green
- 1.0f, 1.0f, 0.0f, // yellow
- // bottom
- 0.0f, 0.0f, 0.0f, // black
- 1.0f, 0.0f, 0.0f, // red
- 0.0f, 0.0f, 1.0f, // blue
- 1.0f, 0.0f, 1.0f // magenta
- };
+static void exit_gl(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);
+ return;
+}
- static const GLfloat vNormals[] = {
- // front
- +0.0f, +0.0f, +1.0f, // forward
- +0.0f, +0.0f, +1.0f, // forward
- +0.0f, +0.0f, +1.0f, // forward
- +0.0f, +0.0f, +1.0f, // forward
- // back
- +0.0f, +0.0f, -1.0f, // backbard
- +0.0f, +0.0f, -1.0f, // backbard
- +0.0f, +0.0f, -1.0f, // backbard
- +0.0f, +0.0f, -1.0f, // backbard
- // right
- +1.0f, +0.0f, +0.0f, // right
- +1.0f, +0.0f, +0.0f, // right
- +1.0f, +0.0f, +0.0f, // right
- +1.0f, +0.0f, +0.0f, // right
- // left
- -1.0f, +0.0f, +0.0f, // left
- -1.0f, +0.0f, +0.0f, // left
- -1.0f, +0.0f, +0.0f, // left
- -1.0f, +0.0f, +0.0f, // left
- // top
- +0.0f, +1.0f, +0.0f, // up
- +0.0f, +1.0f, +0.0f, // up
- +0.0f, +1.0f, +0.0f, // up
- +0.0f, +1.0f, +0.0f, // up
- // bottom
- +0.0f, -1.0f, +0.0f, // down
- +0.0f, -1.0f, +0.0f, // down
- +0.0f, -1.0f, +0.0f, // down
- +0.0f, -1.0f, +0.0f // down
- };
+static void exit_drm(void)
+{
- /* clear the color buffer */
- glClearColor(0.5, 0.5, 0.5, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ drmModeRes *resources;
+ int i;
+
+ resources = (drmModeRes *)drm.resource_id;
+ for (i = 0; i < resources->count_connectors; i++) {
+ drmModeFreeEncoder(drm.encoder[i]);
+ drmModeFreeConnector(drm.connectors[i]);
+ }
+ drmModeFreeResources(drm.resource_id);
+ drmClose(drm.fd);
+ return;
+}
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
- glEnableVertexAttribArray(0);
+void cleanup_kmscube(void)
+{
+ exit_gl();
+ exit_gbm();
+ exit_drm();
+ printf("Cleanup of GL, GBM and DRM completed\n");
+ return;
+}
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, vNormals);
- glEnableVertexAttribArray(1);
+static void draw(uint32_t i)
+{
+ ESMatrix modelview;
- glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, vColors);
- glEnableVertexAttribArray(2);
+ /* 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.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->vdisplay) / (GLfloat)(drm.mode->hdisplay);
+ GLfloat aspect = (GLfloat)(drm.mode[DISP_ID]->vdisplay) / (GLfloat)(drm.mode[DISP_ID]->hdisplay);
ESMatrix projection;
esMatrixLoadIdentity(&projection);
glUniformMatrix4fv(gl.modelviewprojectionmatrix, 1, GL_FALSE, &modelviewprojection.m[0][0]);
glUniformMatrix3fv(gl.normalmatrix, 1, GL_FALSE, normal);
- glEnable(GL_CULL_FACE);
-
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
*waiting_for_flip = 0;
}
+void print_usage()
+{
+ printf("Usage : kmscube <options>\n");
+ printf("\t-h : Help\n");
+ printf("\t-a : Enable all displays\n");
+ printf("\t-c <id> : Display using connector_id [if not specified, use the first connected connector]\n");
+ printf("\t-n <number> (optional): Number of frames to render\n");
+}
+
+int kms_signalhandler(int signum)
+{
+ switch(signum) {
+ case SIGINT:
+ case SIGTERM:
+ /* Allow the pending page flip requests to be completed before
+ * the teardown sequence */
+ sleep(1);
+ printf("Handling signal number = %d\n", signum);
+ cleanup_kmscube();
+ break;
+ default:
+ printf("Unknown signal\n");
+ break;
+ }
+ exit(1);
+}
+
int main(int argc, char *argv[])
{
fd_set fds;
struct drm_fb *fb;
uint32_t i = 0;
int ret;
+ int opt;
+ int frame_count = -1;
+
+ signal(SIGINT, kms_signalhandler);
+ signal(SIGTERM, kms_signalhandler);
+
+ while ((opt = getopt(argc, argv, "ahc:n:")) != -1) {
+ switch(opt) {
+ case 'a':
+ all_display = 1;
+ break;
+
+ case 'h':
+ print_usage();
+ return 0;
+
+ case 'c':
+ connector_id = atoi(optarg);
+ break;
+ case 'n':
+ frame_count = atoi(optarg);
+ break;
+
+
+ default:
+ printf("Undefined option %s\n", argv[optind]);
+ print_usage();
+ return -1;
+ }
+ }
+
+ if (all_display) {
+ printf("### Enabling all displays\n");
+ connector_id = -1;
+ }
ret = init_drm();
if (ret) {
printf("failed to initialize DRM\n");
return ret;
}
+ printf("### Primary display => ConnectorId = %d, Resolution = %dx%d\n",
+ drm.connector_id[DISP_ID], drm.mode[DISP_ID]->hdisplay,
+ drm.mode[DISP_ID]->vdisplay);
FD_ZERO(&fds);
- FD_SET(0, &fds);
FD_SET(drm.fd, &fds);
ret = init_gbm();
fb = drm_fb_get_from_bo(bo);
/* set mode: */
- ret = drmModeSetCrtc(drm.fd, drm.crtc_id, fb->fb_id, 0, 0,
- &drm.connector_id, 1, drm.mode);
- if (ret) {
- printf("failed to set mode: %s\n", strerror(errno));
- return ret;
+ if (all_display) {
+ for (i=0; i<drm.ndisp; i++) {
+ ret = drmModeSetCrtc(drm.fd, drm.crtc_id[i], 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));
+ return ret;
+ }
+ }
+ } else {
+ ret = drmModeSetCrtc(drm.fd, drm.crtc_id[DISP_ID], 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));
+ return ret;
+ }
}
- while (1) {
+ while (frame_count != 0) {
struct gbm_bo *next_bo;
int waiting_for_flip = 1;
* hw composition
*/
- ret = drmModePageFlip(drm.fd, drm.crtc_id, fb->fb_id,
+ ret = drmModePageFlip(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
if (ret) {
printf("failed to queue page flip: %s\n", strerror(errno));
printf("select timeout!\n");
return -1;
} else if (FD_ISSET(0, &fds)) {
- printf("user interrupted!\n");
- break;
+ continue;
}
drmHandleEvent(drm.fd, &evctx);
}
/* release last buffer to render on again: */
gbm_surface_release_buffer(gbm.surface, bo);
bo = next_bo;
+
+ if(frame_count >= 0)
+ frame_count--;
}
+ cleanup_kmscube();
+ printf("\n Exiting kmscube \n");
+
return ret;
}