Esempio n. 1
1
static int drm_egl_init(struct MPGLContext *ctx, int flags)
{
    struct priv *p = ctx->priv;
    p->kms = NULL;
    p->old_crtc = NULL;
    p->gbm.surface = NULL;
    p->gbm.device = NULL;
    p->active = false;
    p->waiting_for_flip = false;
    p->ev.version = DRM_EVENT_CONTEXT_VERSION;
    p->ev.page_flip_handler = page_flipped;

    p->vt_switcher_active = vt_switcher_init(&p->vt_switcher, ctx->vo->log);
    if (p->vt_switcher_active) {
        vt_switcher_acquire(&p->vt_switcher, acquire_vt, ctx);
        vt_switcher_release(&p->vt_switcher, release_vt, ctx);
    } else {
        MP_WARN(ctx->vo, "Failed to set up VT switcher. Terminal switching will be unavailable.\n");
    }

    MP_VERBOSE(ctx->vo, "Initializing KMS\n");
    p->kms = kms_create(ctx->vo->log);
    if (!p->kms) {
        MP_ERR(ctx->vo, "Failed to create KMS.\n");
        return -1;
    }

    // TODO: arguments should be configurable
    if (!kms_setup(p->kms, "/dev/dri/card0", -1, 0)) {
        MP_ERR(ctx->vo, "Failed to configure KMS.\n");
        return -1;
    }

    if (!init_gbm(ctx)) {
        MP_ERR(ctx->vo, "Failed to setup GBM.\n");
        return -1;
    }

    if (!init_egl(ctx, flags & VOFLAG_GLES)) {
        MP_ERR(ctx->vo, "Failed to setup EGL.\n");
        return -1;
    }

    if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface, p->egl.context)) {
        MP_ERR(ctx->vo, "Failed to make context current.\n");
        return -1;
    }

    const char *egl_exts = eglQueryString(p->egl.display, EGL_EXTENSIONS);
    void *(*gpa)(const GLubyte*) = (void *(*)(const GLubyte*))eglGetProcAddress;
    mpgl_load_functions(ctx->gl, gpa, egl_exts, ctx->vo->log);

    // required by gbm_surface_lock_front_buffer
    eglSwapBuffers(p->egl.display, p->egl.surface);

    MP_VERBOSE(ctx->vo, "Preparing framebuffer\n");
    p->gbm.bo = gbm_surface_lock_front_buffer(p->gbm.surface);
    if (!p->gbm.bo) {
        MP_ERR(ctx->vo, "Failed to lock GBM surface.\n");
        return -1;
    }
    update_framebuffer_from_bo(ctx, p->gbm.bo);
    if (!p->fb.id) {
        MP_ERR(ctx->vo, "Failed to create framebuffer.\n");
        return -1;
    }

    if (!crtc_setup(ctx)) {
        MP_ERR(
               ctx->vo,
               "Failed to set CRTC for connector %u: %s\n",
               p->kms->connector->connector_id,
               mp_strerror(errno));
        return -1;
    }

    return 0;
}
Esempio n. 2
0
bool
NativeStateDRM::init()
{
    fd_ = open("/dev/dri/card0", O_RDWR);

    if (fd_ < 0) {
        Log::error("Failed to find a suitable DRM device\n");
        return false;
    }

    resources_ = drmModeGetResources(fd_);
    if (!resources_) {
        Log::error("drmModeGetResources failed\n");
        return false;
    }

    // Find a connected connector
    for (int c = 0; c < resources_->count_connectors; c++) {
        connector_ = drmModeGetConnector(fd_, resources_->connectors[c]);
        if (DRM_MODE_CONNECTED == connector_->connection) {
            break;
        }
        drmModeFreeConnector(connector_);
        connector_ = 0;
    }

    if (!connector_) {
        Log::error("Failed to find a suitable connector\n");
        return false;
    }

    // Find the best resolution (we will always operate full-screen).
    unsigned int bestArea(0);
    for (int m = 0; m < connector_->count_modes; m++) {
        drmModeModeInfo* curMode = &connector_->modes[m];
        unsigned int curArea = curMode->hdisplay * curMode->vdisplay;
        if (curArea > bestArea) {
            mode_ = curMode;
            bestArea = curArea;
        }
    }

    if (!mode_) {
        Log::error("Failed to find a suitable mode\n");
        return false;
    }

    // Find a suitable encoder
    for (int e = 0; e < resources_->count_encoders; e++) {
        encoder_ = drmModeGetEncoder(fd_, resources_->encoders[e]);
        if (encoder_ && encoder_->encoder_id == connector_->encoder_id) {
            break;
        }
        drmModeFreeEncoder(encoder_);
        encoder_ = 0;
    }

    if (!encoder_) {
        Log::error("Failed to find a suitable encoder\n");
        return false;
    }

    if (!init_gbm()) {
        return false;
    }

    crtc_ = drmModeGetCrtc(fd_, encoder_->crtc_id);
    if (!crtc_) {
        Log::error("Failed to get current CRTC\n");
        return false;
    }

    signal(SIGINT, &NativeStateDRM::quit_handler);

    return true;
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
	const char *device = "/dev/dri/card0";
	const char *video = NULL;
	enum mode mode = SMOOTH;
	uint64_t modifier = DRM_FORMAT_MOD_LINEAR;
	unsigned int num_modifiers = 0;
	uint64_t *modifiers = NULL;
	int samples = 0;
	int atomic = 0;
	int opt;

#ifdef HAVE_GST
	gst_init(&argc, &argv);
	GST_DEBUG_CATEGORY_INIT(kmscube_debug, "kmscube", 0, "kmscube video pipeline");
#endif

	while ((opt = getopt_long_only(argc, argv, shortopts, longopts, NULL)) != -1) {
		switch (opt) {
		case 'A':
			atomic = 1;
			break;
		case 'D':
			device = optarg;
			break;
		case 'M':
			if (strcmp(optarg, "smooth") == 0) {
				mode = SMOOTH;
			} else if (strcmp(optarg, "rgba") == 0) {
				mode = RGBA;
			} else if (strcmp(optarg, "nv12-2img") == 0) {
				mode = NV12_2IMG;
			} else if (strcmp(optarg, "nv12-1img") == 0) {
				mode = NV12_1IMG;
			} else {
				printf("invalid mode: %s\n", optarg);
				usage(argv[0]);
				return -1;
			}
			break;
		case 'm':
			modifier = strtoull(optarg, NULL, 0);
			modifiers = &modifier;
			num_modifiers = 1;
			break;
		case 's':
			samples = strtoul(optarg, NULL, 0);
			break;
		case 'V':
			mode = VIDEO;
			video = optarg;
			break;
		default:
			usage(argv[0]);
			return -1;
		}
	}

	if (atomic)
		drm = init_drm_atomic(device, modifiers, num_modifiers);
	else
		drm = init_drm_legacy(device);
	if (!drm) {
		printf("failed to initialize %s DRM\n", atomic ? "atomic" : "legacy");
		return -1;
	}

	gbm = init_gbm(drm);
	if (!gbm) {
		printf("failed to initialize GBM\n");
		return -1;
	}

	if (mode == SMOOTH)
		egl = init_cube_smooth(gbm, samples);
	else if (mode == VIDEO)
		egl = init_cube_video(gbm, video, samples);
	else
		egl = init_cube_tex(gbm, mode, samples);

	if (!egl) {
		printf("failed to initialize EGL\n");
		return -1;
	}

	/* clear the color buffer */
	glClearColor(0.5, 0.5, 0.5, 1.0);
	glClear(GL_COLOR_BUFFER_BIT);

	return drm->run(gbm, egl);
}
Esempio n. 4
0
static int drm_egl_init(struct MPGLContext *ctx, int flags)
{
    if (ctx->vo->probing) {
        MP_VERBOSE(ctx->vo, "DRM EGL backend can be activated only manually.\n");
        return -1;
    }
    struct priv *p = ctx->priv;
    p->kms = NULL;
    p->old_crtc = NULL;
    p->gbm.surface = NULL;
    p->gbm.device = NULL;
    p->active = false;
    p->waiting_for_flip = false;
    p->ev.version = DRM_EVENT_CONTEXT_VERSION;
    p->ev.page_flip_handler = page_flipped;

    p->vt_switcher_active = vt_switcher_init(&p->vt_switcher, ctx->vo->log);
    if (p->vt_switcher_active) {
        vt_switcher_acquire(&p->vt_switcher, acquire_vt, ctx);
        vt_switcher_release(&p->vt_switcher, release_vt, ctx);
    } else {
        MP_WARN(ctx->vo, "Failed to set up VT switcher. Terminal switching will be unavailable.\n");
    }

    MP_VERBOSE(ctx->vo, "Initializing KMS\n");
    p->kms = kms_create(ctx->vo->log, ctx->vo->opts->drm_connector_spec,
                        ctx->vo->opts->drm_mode_id);
    if (!p->kms) {
        MP_ERR(ctx->vo, "Failed to create KMS.\n");
        return -1;
    }

    if (!init_gbm(ctx)) {
        MP_ERR(ctx->vo, "Failed to setup GBM.\n");
        return -1;
    }

    if (!init_egl(ctx, flags)) {
        MP_ERR(ctx->vo, "Failed to setup EGL.\n");
        return -1;
    }

    if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface,
                        p->egl.context)) {
        MP_ERR(ctx->vo, "Failed to make context current.\n");
        return -1;
    }

    const char *egl_exts = eglQueryString(p->egl.display, EGL_EXTENSIONS);
    void *(*gpa)(const GLubyte*) = (void *(*)(const GLubyte*))eglGetProcAddress;
    mpgl_load_functions(ctx->gl, gpa, egl_exts, ctx->vo->log);

    ctx->native_display_type = "drm";
    ctx->native_display = (void *)(intptr_t)p->kms->fd;

    // required by gbm_surface_lock_front_buffer
    eglSwapBuffers(p->egl.display, p->egl.surface);

    MP_VERBOSE(ctx->vo, "Preparing framebuffer\n");
    p->gbm.bo = gbm_surface_lock_front_buffer(p->gbm.surface);
    if (!p->gbm.bo) {
        MP_ERR(ctx->vo, "Failed to lock GBM surface.\n");
        return -1;
    }
    update_framebuffer_from_bo(ctx, p->gbm.bo);
    if (!p->fb.id) {
        MP_ERR(ctx->vo, "Failed to create framebuffer.\n");
        return -1;
    }

    if (!crtc_setup(ctx)) {
        MP_ERR(ctx->vo, "Failed to set CRTC for connector %u: %s\n",
               p->kms->connector->connector_id, mp_strerror(errno));
        return -1;
    }

    return 0;
}
Esempio n. 5
0
int init_egl_drm()
{
        fd_set fds;
        drmEventContext evctx = {
                        .version = DRM_EVENT_CONTEXT_VERSION,
                        .vblank_handler = 0,
                        .page_flip_handler = page_flip_handler,
        };
        struct gbm_bo *bo;
        struct drm_fb *fb;
        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(drm.fd, &fds);

        ret = init_gbm();
        if (ret) {
                printf("failed to initialize GBM\n");
                return ret;
        }

	//Initialise egl regularly here
}

void egl_drm_draw_flip()
{
        /* set mode: */
        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;
                }
        }
	//Draw call here
	//Swapping is involved
                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
                 */

                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));
                        return -1;
                }

                while (waiting_for_flip) {
                        ret = select(drm.fd + 1, &fds, NULL, NULL, NULL);
                        if (ret < 0) {
                                printf("select err: %s\n", strerror(errno));
                                return ret;
                        } else if (ret == 0) {
                                printf("select timeout!\n");
                                return -1;
                        } else if (FD_ISSET(0, &fds)) {
                                continue;
                        }
                        drmHandleEvent(drm.fd, &evctx);
                }
                /* release last buffer to render on again: */
                gbm_surface_release_buffer(gbm.surface, bo);
                bo = next_bo;
}
Esempio n. 6
0
int main(int argc, char *argv[])
{
	struct opt_data opts; optproc(argc, argv, &opts);
	if(audio_init(&opts) < 0) exit(1);
	if(opts.w < 0 && opts.h < 0) opts.w = opts.h = 512;
	else if(opts.w < 0) opts.w = opts.h;
	else if(opts.h < 0) opts.h = opts.w;
	
	int ret;

	ret = init_drm(&opts, 512);
	if (ret) {
		printf("failed to initialize DRM\n");
		return ret;
	}

	ret = init_gbm();
	if (ret) {
		printf("failed to initialize GBM\n");
		return ret;
	}

	ret = init_egl();
	if (ret) {
		printf("failed to initialize EGL\n");
		return ret;
	}
	
	// call init_gl
	//init_gl(&opts, drm.mode->hdisplay, drm.mode->vdisplay);
	init_gl(&opts, opts.w, opts.h); //TODO: better dealing with our great big screen
	
	eglSwapBuffers(gl.display, gl.surface);
	struct gbm_bo *bo = gbm_surface_lock_front_buffer(gbm.surface);
	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;
	}
	
	// turn off line buffering on input and echoing of characters
	struct termios term;
	tcgetattr(STDIN_FILENO, &save_term);
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag &= ~(ICANON|ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
    
    atexit(shutdown_cleanup);
	
	drmVBlank vbl;
	/* Get current count first hopefully also sync up with blank too*/
	vbl.request.type = DRM_VBLANK_RELATIVE;
	vbl.request.sequence = 1;
	ret = drmWaitVBlank(drm.fd, &vbl);
	if (ret != 0) {
		printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret);
		return -1;
	}
	printf("starting msc: %d\n", vbl.request.sequence);
	
	/* Queue an event for frame + 1 */
	vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
	vbl.request.sequence = 1;
	vbl.request.signal = NULL;
	ret = drmWaitVBlank(drm.fd, &vbl);
	if (ret != 0) {
		printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret);
		return -1;
	}
	
	struct pollfd pfds[] = {
		{drm.fd, POLLIN | POLLPRI, 0 },
		{STDIN_FILENO, POLLIN, 0 },
	};

	int debug_maxsrc = 0, debug_pal = 0, show_mandel = 0, show_fps_hist = 0;
	bool done = false;
	while (!done) {

		render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist);

		while (waiting_for_flip) { // TODO: input handling			
			ret = poll(pfds, 2, -1);
			if (ret < 0) {
				printf("poll err: %s\n", strerror(errno));
				return ret;
			} else if (ret == 0) {
				printf("poll timeout!\n");
				done = true;
				break;
			} 
			
			if (pfds[1].revents) {
				char buf[128];
				int cnt = read(STDIN_FILENO, buf, sizeof(buf));
				if(buf[0] == 27) done = true;
				else if(buf[0] == '1') debug_maxsrc = !debug_maxsrc;
				else if(buf[0] == '2') debug_pal = !debug_pal;
				else if(buf[0] == '3') show_mandel = !show_mandel;
				else if(buf[0] == '4') show_fps_hist = !show_fps_hist;
				//continue;
			}
			
			if(pfds[0].revents)
				drmHandleEvent(drm.fd, &evctx);
		}

		/* release last buffer to render on again: */
		gbm_surface_release_buffer(gbm.surface, bo);
		bo = next_bo;
	}
	
	audio_shutdown();

	return ret;
}