~nch/phwip

cd0a5b17d2e0b172963d07efa81c7208b3cdcfba — nc 4 years ago 0931de2 master
cleanup for blog post
2 files changed, 182 insertions(+), 179 deletions(-)

M makefile
M phwip.c
M makefile => makefile +1 -1
@@ 1,2 1,2 @@
phwip: phwip.c
	gcc -o phwip phwip.c -ldrm -lgbm -lEGL -lGLESv2 -I/usr/include/libdrm
	gcc -g -o phwip phwip.c -ldrm -lgbm -lEGL -lGLESv2 -I/usr/include/libdrm

M phwip.c => phwip.c +181 -178
@@ 19,33 19,10 @@

#include <time.h>

#define EXIT(msg) { fputs (msg, stderr); exit (EXIT_FAILURE); }
#define EXIT(msg) { fputs(msg, stderr); exit(EXIT_FAILURE); }

static int device;

static drmModeConnector *find_connector (drmModeRes *resources) {
	// iterate the connectors
	int i;
	for (i=0; i<resources->count_connectors; i++) {
		drmModeConnector *connector = drmModeGetConnector (device, resources->connectors[i]);
		// pick the first connected connector
		if (connector->connection == DRM_MODE_CONNECTED) {
			return connector;
		}
		drmModeFreeConnector (connector);
	}
	// no connector found
	return NULL;
}

static drmModeEncoder *find_encoder (drmModeRes *resources, drmModeConnector *connector) {
	if (connector->encoder_id) {
		return drmModeGetEncoder (device, connector->encoder_id);
	}
	// no encoder found
	return NULL;
}

static uint32_t connector_id;
static drmModeModeInfo mode_info;
static drmModeCrtc *crtc;


@@ 64,172 41,198 @@ const uint16_t HEIGHT = 1440;

int px, py;

static void swap_buffers () {
	eglSwapBuffers (display, egl_surface);
	struct gbm_bo *bo = gbm_surface_lock_front_buffer (gbm_surface);
	uint32_t handle = gbm_bo_get_handle (bo).u32;
	uint32_t pitch = gbm_bo_get_stride (bo);
	uint32_t fb;
	drmModeAddFB (device, mode_info.hdisplay, mode_info.vdisplay, 24, 32, pitch, handle, &fb);
	drmModeSetCrtc (device, crtc->crtc_id, fb, 0, 0, &connector_id, 1, &mode_info);

	if (previous_bo) {
		drmModeRmFB (device, previous_fb);
		gbm_surface_release_buffer (gbm_surface, previous_bo);
	}
	previous_bo = bo;
	previous_fb = fb;
static void swap_buffers()
{
    eglSwapBuffers(display, egl_surface);
    struct gbm_bo *bo = gbm_surface_lock_front_buffer(gbm_surface);
    uint32_t handle = gbm_bo_get_handle(bo).u32;
    uint32_t pitch = gbm_bo_get_stride(bo);
    uint32_t fb;
    drmModeAddFB(device, mode_info.hdisplay, mode_info.vdisplay, 24, 32, pitch, handle, &fb);
    drmModeSetCrtc(device, crtc->crtc_id, fb, 0, 0, &connector_id, 1, &mode_info);

    if (previous_bo) {
        drmModeRmFB(device, previous_fb);
        gbm_surface_release_buffer(gbm_surface, previous_bo);
    }
    previous_bo = bo;
    previous_fb = fb;
}

static void draw (float progress) {
	glClearColor (1.0f-progress, progress, 0.0, 1.0);
	glClear (GL_COLOR_BUFFER_BIT);
static void draw(float progress)
{
    glClearColor(1.0f - progress, progress, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

	float x = 2 * ((float) px / WIDTH) - 0.5;
	float y = -2 * ((float) py / HEIGHT) + 0.5;
    float x = 2 * ((float)px / WIDTH) - 0.5;
    float y = -2 * ((float)py / HEIGHT) + 0.5;

	GLfloat verts[] = {x+0.0f, y+0.5f, 0.0f,
			   x-0.5f, y-0.5f, 0.0f,
		           x+0.5f, y-0.5f,  0.0f};
    GLfloat verts[] = { x + 0.0f, y + 0.5f, 0.0f,
        x - 0.5f, y - 0.5f, 0.0f,
        x + 0.5f, y - 0.5f, 0.0f
    };

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
	glEnableVertexAttribArray(0);
	glDrawArrays(GL_TRIANGLES, 0, 3);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
    glEnableVertexAttribArray(0);
    glDrawArrays(GL_TRIANGLES, 0, 3);

	swap_buffers ();
    swap_buffers();
}


void *handle_touch(void *path) {
	px = py = 0;
	int tsfd;
	tsfd = open((char *) path, O_RDONLY);
	if (tsfd == -1) {
		fprintf(stderr,"problem opening touchscreen device.\n");
		return NULL;
	} else {
		fprintf(stderr, "opened touchscreen device %s ok\n", (char *) path);
	}

	int rs = 0;

	struct input_event ev;
	while ((rs = read(tsfd, &ev, sizeof(struct input_event))) != -1) {
		//fprintf(stderr,"type=%d code=%d value=%d\n", ev.type, ev.code, ev.value);
		if (ev.type == EV_ABS) {
			if (ev.code == ABS_X) {
				//printf("x=%d\n", ev.value);
				px = ev.value;
			}
			if (ev.code == ABS_Y) {
				//printf("y=%d\n", ev.value);
				py = ev.value;
			}
		}
		if (ev.code == ABS_PRESSURE)
		{
			fprintf(stderr,"touch end\n");
		}
	}

	close(tsfd);
	return NULL;
void *handle_touch(void *path)
{
    px = py = 0;
    int tsfd;
    tsfd = open((char *)path, O_RDONLY);
    if (tsfd == -1) {
        fprintf(stderr, "problem opening touchscreen device.\n");
        return NULL;
    } else {
        fprintf(stderr, "opened touchscreen device %s ok\n", (char *)path);
    }

    int rs = 0;

    struct input_event ev;
    while ((rs = read(tsfd, &ev, sizeof(struct input_event))) != -1) {
        //fprintf(stderr,"type=%d code=%d value=%d\n", ev.type, ev.code, ev.value);
        if (ev.type == EV_ABS) {
            if (ev.code == ABS_X) {
                //printf("x=%d\n", ev.value);
                px = ev.value;
            }
            if (ev.code == ABS_Y) {
                //printf("y=%d\n", ev.value);
                py = ev.value;
            }
        }
        if (ev.code == ABS_PRESSURE) {
            fprintf(stderr, "touch end\n");
        }
    }

    close(tsfd);
    return NULL;
}

long get_ms() {
	struct timespec spec;
	clock_gettime(CLOCK_REALTIME, &spec);
	return ((long) spec.tv_sec * 1000) + spec.tv_nsec / 1.0e6;
long get_ms()
{
    struct timespec spec;
    clock_gettime(CLOCK_REALTIME, &spec);
    return ((long)spec.tv_sec * 1000) + spec.tv_nsec / 1.0e6;
}

int main () {
	pthread_t touch_thread;
	if(pthread_create(&touch_thread, NULL, handle_touch, "/dev/input/event1")) EXIT("Failed to create thread");

	device = open ("/dev/dri/card1", O_RDWR|O_CLOEXEC);

	{ // setup display
		drmModeRes *resources = drmModeGetResources (device);
		if(!resources) EXIT("failed on drmModeGetResources()\n");
		// find a connector
		drmModeConnector *connector = find_connector (resources);
		if (!connector) EXIT ("no connector found\n");
		// save the connector_id
		connector_id = connector->connector_id;
		// save the first mode
		mode_info = connector->modes[0];
		printf ("resolution: %ix%i\n", mode_info.hdisplay, mode_info.vdisplay);
		// find an encoder
		drmModeEncoder *encoder = find_encoder (resources, connector);
		if (!encoder) EXIT ("no encoder found\n");
		// find a CRTC
		if (encoder->crtc_id) {
			crtc = drmModeGetCrtc (device, encoder->crtc_id);
		}
		drmModeFreeEncoder (encoder);
		drmModeFreeConnector (connector);
		drmModeFreeResources (resources);
	}

	{ // setup EGL
		gbm_device = gbm_create_device (device);
		display = eglGetDisplay (gbm_device);
		eglInitialize (display, NULL, NULL);

		// create an OpenGL context
		eglBindAPI (EGL_OPENGL_API);
		EGLint attributes[] = {
			EGL_RED_SIZE, 8,
			EGL_GREEN_SIZE, 8,
			EGL_BLUE_SIZE, 8,
			EGL_NONE};
		EGLConfig config;
		EGLint num_config;
		eglChooseConfig (display, attributes, &config, 1, &num_config);
		context = eglCreateContext (display, config, EGL_NO_CONTEXT, NULL);

		// create the GBM and EGL surface
		gbm_surface = gbm_surface_create (gbm_device, mode_info.hdisplay, mode_info.vdisplay, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT|GBM_BO_USE_RENDERING);
		egl_surface = eglCreateWindowSurface (display, config, gbm_surface, NULL);
		eglMakeCurrent (display, egl_surface, egl_surface, context);
	}

	printf("GL_VERSION  : %s\n", glGetString(GL_VERSION) );
	printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) );

	int i;
	int frames = 0;
	long begin = get_ms();

	for (i = 0; i < 600; i++) {
		draw (i / 600.0f);
		frames++;
		if(frames == 120) {
			printf("%f\n", ((float) frames) / ((float) (get_ms() - begin) / 1000));
			frames = 0;
			begin = get_ms();
		}
	}

	{ // cleanup
		// set the previous crtc
		drmModeSetCrtc (device, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, &connector_id, 1, &crtc->mode);
		drmModeFreeCrtc (crtc);

		if (previous_bo) {
			drmModeRmFB (device, previous_fb);
			gbm_surface_release_buffer (gbm_surface, previous_bo);
		}

		eglDestroySurface (display, egl_surface);
		gbm_surface_destroy (gbm_surface);
		eglDestroyContext (display, context);
		eglTerminate (display);
		gbm_device_destroy (gbm_device);

		close (device);
	}
	return 0;
int main()
{
    pthread_t touch_thread;
    if (pthread_create(&touch_thread, NULL, handle_touch, "/dev/input/event1"))
        EXIT("Failed to create thread");

    device = open("/dev/dri/card1", O_RDWR | O_CLOEXEC);

    { // setup display
        drmModeRes *resources = drmModeGetResources(device);
        if (!resources)
            EXIT("failed on drmModeGetResources()\n");

        // find a connector
        drmModeConnector *connector = NULL;
        for (int i = 0; i < resources->count_connectors; i++) {
            drmModeConnector *c = drmModeGetConnector(device, resources->connectors[i]);
            // pick the first connected connector
            if (c->connection == DRM_MODE_CONNECTED) {
                connector = c;
                break;
            }
            drmModeFreeConnector(c);
        }
        if (!connector)
            EXIT("no connector found\n");

        connector_id = connector->connector_id;
        mode_info = connector->modes[0];

        printf("resolution: %ix%i\n", mode_info.hdisplay, mode_info.vdisplay);

        // find an encoder
        drmModeEncoder *encoder = NULL;
        if (connector->encoder_id) {
            encoder = drmModeGetEncoder(device, connector->encoder_id);
        }
        if (!encoder)
            EXIT("no encoder found\n");

        // find a CRTC
        if (encoder->crtc_id) {
            crtc = drmModeGetCrtc(device, encoder->crtc_id);
        }
        drmModeFreeEncoder(encoder);
        drmModeFreeConnector(connector);
        drmModeFreeResources(resources);
    }

    { // setup EGL
        gbm_device = gbm_create_device(device);
        display = eglGetDisplay(gbm_device);
        eglInitialize(display, NULL, NULL);

        // create an OpenGL context
        eglBindAPI(EGL_OPENGL_API);
        EGLint attributes[] = {
            EGL_RED_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE, 8,
            EGL_NONE
        };
        EGLConfig config;
        EGLint num_config;
        eglChooseConfig(display, attributes, &config, 1, &num_config);
        context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);

        // create the GBM and EGL surface
        gbm_surface =
            gbm_surface_create(gbm_device, mode_info.hdisplay, mode_info.vdisplay, GBM_BO_FORMAT_XRGB8888,
                               GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
        egl_surface = eglCreateWindowSurface(display, config, gbm_surface, NULL);
        eglMakeCurrent(display, egl_surface, egl_surface, context);
    }

    printf("GL_VERSION  : %s\n", glGetString(GL_VERSION));
    printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER));

    int i;
    int frames = 0;
    long begin = get_ms();

    for (i = 0; i < 600; i++) {
        draw(i / 600.0f);
        frames++;
        if (frames == 120) {
            printf("%f\n", ((float)frames) / ((float)(get_ms() - begin) / 1000));
            frames = 0;
            begin = get_ms();
        }
    }

    { // cleanup
        // set the previous crtc
        drmModeSetCrtc(device, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, &connector_id, 1, &crtc->mode);
        drmModeFreeCrtc(crtc);

        if (previous_bo) {
            drmModeRmFB(device, previous_fb);
            gbm_surface_release_buffer(gbm_surface, previous_bo);
        }

        eglDestroySurface(display, egl_surface);
        gbm_surface_destroy(gbm_surface);
        eglDestroyContext(display, context);
        eglTerminate(display);
        gbm_device_destroy(gbm_device);

        close(device);
    }
    return 0;
}

// starting source taken from: https://github.com/eyelash/tutorials/blob/master/drm-gbm.c