Example #1
0
SHL_EXPORT
int uterm_display_fake_blend(struct uterm_display *disp,
			     const struct uterm_video_buffer *buf,
			     unsigned int x, unsigned int y,
			     uint8_t fr, uint8_t fg, uint8_t fb,
			     uint8_t br, uint8_t bg, uint8_t bb)
{
	struct uterm_video_blend_req req;

	if (!disp || !display_is_online(disp) || !video_is_awake(disp->video))
		return -EINVAL;

	memset(&req, 0, sizeof(req));
	req.buf = buf;
	req.x = x;
	req.y = y;
	req.fr = fr;
	req.fg = fg;
	req.fb = fb;
	req.br = br;
	req.bg = bg;
	req.bb = bb;

	return VIDEO_CALL(disp->ops->fake_blendv, -EOPNOTSUPP, disp, &req, 1);
}
Example #2
0
static int display_swap(struct uterm_display *disp)
{
	struct fb_var_screeninfo *vinfo;
	int ret;

	if (!disp->video || !video_is_awake(disp->video))
		return -EINVAL;
	if (!(disp->flags & DISPLAY_ONLINE))
		return -EINVAL;

	if (!(disp->flags & DISPLAY_DBUF))
		return 0;

	vinfo = &disp->fbdev.vinfo;
	vinfo->activate = FB_ACTIVATE_VBL;

	if (!disp->fbdev.bufid)
		vinfo->yoffset = disp->fbdev.yres;
	else
		vinfo->yoffset = 0;

	ret = ioctl(disp->fbdev.fd, FBIOPUT_VSCREENINFO, vinfo);
	if (ret) {
		log_warning("cannot swap buffers on %s (%d): %m",
			    disp->fbdev.node, errno);
		return -EFAULT;
	}

	disp->fbdev.bufid ^= 1;
	return 0;
}
Example #3
0
SHL_EXPORT
int uterm_display_swap(struct uterm_display *disp, bool immediate)
{
	if (!disp || !display_is_online(disp) || !video_is_awake(disp->video))
		return -EINVAL;

	return VIDEO_CALL(disp->ops->swap, 0, disp, immediate);
}
Example #4
0
SHL_EXPORT
int uterm_display_set_dpms(struct uterm_display *disp, int state)
{
	if (!disp || !display_is_online(disp) || !video_is_awake(disp->video))
		return -EINVAL;

	return VIDEO_CALL(disp->ops->set_dpms, 0, disp, state);
}
Example #5
0
static void video_sleep(struct uterm_video *video)
{
	if (!video_is_awake(video))
		return;

	drmDropMaster(video->dumb.fd);
	video->flags &= ~VIDEO_AWAKE;
}
Example #6
0
void uterm_video_sleep(struct uterm_video *video)
{
	if (!video || !video_is_awake(video))
		return;

	VIDEO_CB(video, NULL, UTERM_SLEEP);
	VIDEO_CALL(video->ops->sleep, 0, video);
}
Example #7
0
SHL_EXPORT
int uterm_display_fake_blendv(struct uterm_display *disp,
			      const struct uterm_video_blend_req *req,
			      size_t num)
{
	if (!disp || !display_is_online(disp) || !video_is_awake(disp->video))
		return -EINVAL;

	return VIDEO_CALL(disp->ops->fake_blendv, -EOPNOTSUPP, disp, req, num);
}
Example #8
0
SHL_EXPORT
int uterm_display_blit(struct uterm_display *disp,
		       const struct uterm_video_buffer *buf,
		       unsigned int x, unsigned int y)
{
	if (!disp || !display_is_online(disp) || !video_is_awake(disp->video))
		return -EINVAL;

	return VIDEO_CALL(disp->ops->blit, -EOPNOTSUPP, disp, buf, x, y);
}
Example #9
0
SHL_EXPORT
void uterm_video_sleep(struct uterm_video *video)
{
	if (!video || !video_is_awake(video))
		return;

	log_debug("go asleep");

	VIDEO_CB(video, NULL, UTERM_SLEEP);
	video->flags &= ~VIDEO_AWAKE;
	VIDEO_CALL(video->ops->sleep, 0, video);
}
Example #10
0
SHL_EXPORT
int uterm_display_fill(struct uterm_display *disp,
		       uint8_t r, uint8_t g, uint8_t b,
		       unsigned int x, unsigned int y,
		       unsigned int width, unsigned int height)
{
	if (!disp || !display_is_online(disp) || !video_is_awake(disp->video))
		return -EINVAL;

	return VIDEO_CALL(disp->ops->fill, -EOPNOTSUPP, disp, r, g, b, x, y,
			  width, height);
}
Example #11
0
SHL_EXPORT
int uterm_display_activate(struct uterm_display *disp, struct uterm_mode *mode)
{
	if (!disp || !disp->video || display_is_online(disp) ||
	    !video_is_awake(disp->video))
		return -EINVAL;

	if (!mode)
		mode = disp->default_mode;

	return VIDEO_CALL(disp->ops->activate, 0, disp, mode);
}
Example #12
0
static int display_blit(struct uterm_display *disp,
			const struct uterm_video_buffer *buf,
			unsigned int x, unsigned int y)
{
	unsigned int tmp;
	uint8_t *dst, *src;
	struct dumb_rb *rb;
	unsigned int width, height;
	unsigned int sw, sh;

	if (!disp->video || !display_is_online(disp))
		return -EINVAL;
	if (!buf || !video_is_awake(disp->video))
		return -EINVAL;
	if (buf->format != UTERM_FORMAT_XRGB32)
		return -EINVAL;

	rb = &disp->dumb.rb[disp->dumb.current_rb ^ 1];
	sw = disp->current_mode->dumb.info.hdisplay;
	sh = disp->current_mode->dumb.info.vdisplay;

	tmp = x + buf->width;
	if (tmp < x || x >= sw)
		return -EINVAL;
	if (tmp > sw)
		width = sw - x;
	else
		width = buf->width;

	tmp = y + buf->height;
	if (tmp < y || y >= sh)
		return -EINVAL;
	if (tmp > sh)
		height = sh - y;
	else
		height = buf->height;

	dst = rb->map;
	dst = &dst[y * rb->stride + x * 4];
	src = buf->data;

	while (height--) {
		memcpy(dst, src, 4 * width);
		dst += rb->stride;
		src += buf->stride;
	}

	return 0;
}
Example #13
0
int uterm_video_wake_up(struct uterm_video *video)
{
	int ret;

	if (!video)
		return -EINVAL;
	if (video_is_awake(video))
		return 0;

	ret = VIDEO_CALL(video->ops->wake_up, 0, video);
	if (ret)
		return ret;

	VIDEO_CB(video, NULL, UTERM_WAKE_UP);
	return 0;
}
Example #14
0
static int display_blit(struct uterm_display *disp,
			const struct uterm_video_buffer *buf,
			unsigned int x, unsigned int y)
{
	unsigned int tmp;
	uint8_t *dst, *src;
	unsigned int width, height;

	if (!disp->video || !(disp->flags & DISPLAY_ONLINE))
		return -EINVAL;
	if (!buf || !video_is_awake(disp->video))
		return -EINVAL;
	if (buf->format != UTERM_FORMAT_XRGB32)
		return -EINVAL;

	tmp = x + buf->width;
	if (tmp < x || x >= disp->fbdev.xres)
		return -EINVAL;
	if (tmp > disp->fbdev.xres)
		width = disp->fbdev.xres - x;
	else
		width = buf->width;

	tmp = y + buf->height;
	if (tmp < y || y >= disp->fbdev.yres)
		return -EINVAL;
	if (tmp > disp->fbdev.yres)
		height = disp->fbdev.yres - y;
	else
		height = buf->height;

	if (!(disp->flags & DISPLAY_DBUF) || disp->fbdev.bufid)
		dst = disp->fbdev.map;
	else
		dst = &disp->fbdev.map[disp->fbdev.yres * disp->fbdev.stride];
	dst = &dst[y * disp->fbdev.stride + x * disp->fbdev.bpp];
	src = buf->data;

	while (height--) {
		memcpy(dst, src, 4 * width);
		dst += disp->fbdev.stride;
		src += buf->stride;
	}

	return 0;
}
Example #15
0
static int display_fill(struct uterm_display *disp,
			uint8_t r, uint8_t g, uint8_t b,
			unsigned int x, unsigned int y,
			unsigned int width, unsigned int height)
{
	unsigned int tmp, i;
	uint8_t *dst;
	struct dumb_rb *rb;
	unsigned int sw, sh;

	if (!disp->video || !(disp->flags & DISPLAY_ONLINE))
		return -EINVAL;
	if (!video_is_awake(disp->video))
		return -EINVAL;

	rb = &disp->dumb.rb[disp->dumb.current_rb ^ 1];
	sw = disp->current_mode->dumb.info.hdisplay;
	sh = disp->current_mode->dumb.info.vdisplay;

	tmp = x + width;
	if (tmp < x || x >= sw)
		return -EINVAL;
	if (tmp > sw)
		width = sw - x;
	tmp = y + height;
	if (tmp < y || y >= sh)
		return -EINVAL;
	if (tmp > sh)
		height = sh - y;

	dst = rb->map;
	dst = &dst[y * rb->stride + x * 4];

	while (height--) {
		for (i = 0; i < width; ++i) {
			((uint32_t*)dst)[i] = ((r & 0xff) << 16) |
					      ((g & 0xff) << 8) |
					       (b & 0xff);
		}
		dst += rb->stride;
	}

	return 0;
}
Example #16
0
static int display_fill(struct uterm_display *disp,
			uint8_t r, uint8_t g, uint8_t b,
			unsigned int x, unsigned int y,
			unsigned int width, unsigned int height)
{
	unsigned int tmp, i;
	uint8_t *dst;

	if (!disp->video || !(disp->flags & DISPLAY_ONLINE))
		return -EINVAL;
	if (!video_is_awake(disp->video))
		return -EINVAL;

	tmp = x + width;
	if (tmp < x || x >= disp->fbdev.xres)
		return -EINVAL;
	if (tmp > disp->fbdev.xres)
		width = disp->fbdev.xres - x;
	tmp = y + height;
	if (tmp < y || y >= disp->fbdev.yres)
		return -EINVAL;
	if (tmp > disp->fbdev.yres)
		height = disp->fbdev.yres - y;

	if (!(disp->flags & DISPLAY_DBUF) || disp->fbdev.bufid)
		dst = disp->fbdev.map;
	else
		dst = &disp->fbdev.map[disp->fbdev.yres * disp->fbdev.stride];
	dst = &dst[y * disp->fbdev.stride + x * disp->fbdev.bpp];

	while (height--) {
		for (i = 0; i < width; ++i) {
			((uint32_t*)dst)[i] = ((r & 0xff) << 16) |
					      ((g & 0xff) << 8) |
					       (b & 0xff);
		}
		dst += disp->fbdev.stride;
	}

	return 0;
}
Example #17
0
SHL_EXPORT
int uterm_video_wake_up(struct uterm_video *video)
{
	int ret;

	if (!video)
		return -EINVAL;
	if (video_is_awake(video))
		return 0;

	log_debug("wake up");

	ret = VIDEO_CALL(video->ops->wake_up, 0, video);
	if (ret) {
		video->flags &= ~VIDEO_AWAKE;
		return ret;
	}

	video->flags |= VIDEO_AWAKE;
	VIDEO_CB(video, NULL, UTERM_WAKE_UP);
	return 0;
}
Example #18
0
static int display_swap(struct uterm_display *disp)
{
	int ret;

	if (!display_is_online(disp) || !video_is_awake(disp->video))
		return -EINVAL;
	if (disp->dpms != UTERM_DPMS_ON)
		return -EINVAL;

	errno = 0;
	disp->dumb.current_rb ^= 1;
	ret = drmModePageFlip(disp->video->dumb.fd, disp->dumb.crtc_id,
				disp->dumb.rb[disp->dumb.current_rb].fb,
				DRM_MODE_PAGE_FLIP_EVENT, disp);
	if (ret) {
		log_warn("page-flip failed %d %d", ret, errno);
		return -EFAULT;
	}
	uterm_display_ref(disp);
	disp->flags |= DISPLAY_VSYNC;

	return 0;
}
Example #19
0
static void show_displays(struct uterm_video *video)
{
	int ret;
	struct uterm_display *iter;

	if (!video_is_awake(video))
		return;

	for (iter = video->displays; iter; iter = iter->next) {
		if (!display_is_online(iter))
			continue;
		if (iter->dpms != UTERM_DPMS_ON)
			continue;

		ret = drmModeSetCrtc(video->dumb.fd, iter->dumb.crtc_id,
			iter->dumb.rb[iter->dumb.current_rb].fb, 0, 0,
			&iter->dumb.conn_id, 1, &iter->current_mode->dumb.info);
		if (ret) {
			log_err("cannot set drm-crtc on display %p", iter);
			continue;
		}
	}
}
Example #20
0
static int video_wake_up(struct uterm_video *video)
{
	int ret;

	if (video_is_awake(video))
		return 0;

	ret = drmSetMaster(video->dumb.fd);
	if (ret) {
		log_err("cannot set DRM-master");
		return -EACCES;
	}

	video->flags |= VIDEO_AWAKE;
	ret = hotplug(video);
	if (ret) {
		video->flags &= ~VIDEO_AWAKE;
		drmDropMaster(video->dumb.fd);
		return ret;
	}

	show_displays(video);
	return 0;
}
Example #21
0
static int display_activate_force(struct uterm_display *disp,
				  struct uterm_mode *mode,
				  bool force)
{
	static const char depths[] = { 32, 24, 16, 0 };
	struct fb_var_screeninfo *vinfo;
	struct fb_fix_screeninfo *finfo;
	int ret, i;
	uint64_t quot;
	size_t len;

	if (!disp->video || !video_is_awake(disp->video))
		return -EINVAL;
	if (!force && (disp->flags & DISPLAY_ONLINE))
		return 0;

	/* TODO: We do not support explicit modesetting in fbdev, so we require
	 * @mode to be NULL. You can still switch modes via "fbset" on the
	 * console and then restart the app. It will automatically adapt to the
	 * new mode. The only values changed here are bpp and color mode. */
	if (mode)
		return -EINVAL;

	ret = refresh_info(disp);
	if (ret)
		return ret;

	finfo = &disp->fbdev.finfo;
	vinfo = &disp->fbdev.vinfo;

	vinfo->xoffset = 0;
	vinfo->yoffset = 0;
	vinfo->activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
	vinfo->xres_virtual = vinfo->xres;
	vinfo->yres_virtual = vinfo->yres * 2;
	vinfo->bits_per_pixel = 32;

	log_info("activating display %s to %ux%u %u bpp", disp->fbdev.node,
		 vinfo->xres, vinfo->yres, vinfo->bits_per_pixel);

	ret = ioctl(disp->fbdev.fd, FBIOPUT_VSCREENINFO, vinfo);
	if (ret) {
		disp->flags &= ~DISPLAY_DBUF;
		vinfo->yres_virtual = vinfo->yres;
		ret = ioctl(disp->fbdev.fd, FBIOPUT_VSCREENINFO, vinfo);
		if (ret) {
			log_err("cannot set vinfo (%d): %m",
				errno);
			return -EFAULT;
		}
		log_debug("disabling double buffering");
	} else {
		disp->flags |= DISPLAY_DBUF;
		log_debug("enabling double buffering");
	}

	ret = refresh_info(disp);
	if (ret)
		return ret;

	/* We require TRUECOLOR mode here. That is, each pixel has a color value
	 * that is split into rgba values that we can set directly. Other visual
	 * modes like pseudocolor or direct-color do not provide this. As I have
	 * never seen a device that does not support TRUECOLOR, I think we can
	 * ignore them here. */
	if (finfo->visual != FB_VISUAL_TRUECOLOR) {
		for (i = 0; depths[i]; ++i) {
			vinfo->bits_per_pixel = depths[i];
			vinfo->activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;

			ret = ioctl(disp->fbdev.fd, FBIOPUT_VSCREENINFO,
				    vinfo);
			if (ret < 0)
				continue;

			ret = refresh_info(disp);
			if (ret)
				return ret;

			if (finfo->visual == FB_VISUAL_TRUECOLOR)
				break;
		}
	}

	if (vinfo->xres_virtual < vinfo->xres ||
	    (disp->flags & DISPLAY_DBUF &&
	     vinfo->yres_virtual < vinfo->yres * 2) ||
	    vinfo->yres_virtual < vinfo->yres) {
		log_error("device %s does not support out buffer sizes",
			  disp->fbdev.node);
		return -EFAULT;
	}

	if (vinfo->bits_per_pixel % 8) {
		log_error("device %s uses no power of 8 bpp: %u",
			  disp->fbdev.node, vinfo->bits_per_pixel);
		return -EFAULT;
	}

	if (finfo->visual != FB_VISUAL_TRUECOLOR ||
	    vinfo->bits_per_pixel < 16) {
		log_error("device %s does not support true-color bpp >= 16",
			  disp->fbdev.node);
		return -EFAULT;
	}

	/* TODO: remove this check and correctly provide conversions for the
	 * blitting functions. In fact, the for-loop above is totally useless
	 * while using this restriction here but lets be optimistic and say that
	 * this will be replaced soon. */
	if (vinfo->red.offset != 16 || vinfo->red.length != 8 ||
	    vinfo->green.offset != 8 || vinfo->green.length != 8 ||
	    vinfo->blue.offset != 0 || vinfo->green.length != 8 ||
	    vinfo->bits_per_pixel != 32) {
		log_error("device %s does not support xrgb32",
			  disp->fbdev.node);
		return -EFAULT;
	}

	/* calculate monitor rate, default is 60 Hz */
	quot = (vinfo->upper_margin + vinfo->lower_margin + vinfo->yres);
	quot *= (vinfo->left_margin + vinfo->right_margin + vinfo->xres);
	quot *= vinfo->pixclock;
	if (quot)
		disp->fbdev.rate = 1000000000000000LLU / quot;
	else
		disp->fbdev.rate = 60 * 1000;

	len = finfo->line_length * vinfo->yres;
	if (disp->flags & DISPLAY_DBUF)
		len *= 2;

	disp->fbdev.map = mmap(0, len, PROT_WRITE, MAP_SHARED,
			       disp->fbdev.fd, 0);
	if (disp->fbdev.map == MAP_FAILED) {
		log_error("cannot mmap device %s (%d): %m", disp->fbdev.node,
			  errno);
		return -EFAULT;
	}

	memset(disp->fbdev.map, 0, len);
	disp->fbdev.xres = vinfo->xres;
	disp->fbdev.yres = vinfo->yres;
	disp->fbdev.len = len;
	disp->fbdev.bpp = vinfo->bits_per_pixel / 8;
	disp->fbdev.stride = finfo->line_length;
	disp->fbdev.bufid = 0;

	ret = mode_new(&disp->modes, &fbdev_mode_ops);
	if (ret) {
		munmap(disp->fbdev.map, disp->fbdev.len);
		return ret;
	}
	disp->modes->fbdev.width = disp->fbdev.xres;
	disp->modes->fbdev.height = disp->fbdev.yres;
	disp->current_mode = disp->modes;

	disp->flags |= DISPLAY_ONLINE;
	return 0;
}
Example #22
0
static int display_blend(struct uterm_display *disp,
			 const struct uterm_video_buffer *buf,
			 unsigned int x, unsigned int y,
			 uint8_t fr, uint8_t fg, uint8_t fb,
			 uint8_t br, uint8_t bg, uint8_t bb)
{
	unsigned int tmp;
	uint8_t *dst, *src;
	unsigned int width, height, i;
	unsigned int r, g, b;

	if (!disp->video || !(disp->flags & DISPLAY_ONLINE))
		return -EINVAL;
	if (!buf || !video_is_awake(disp->video))
		return -EINVAL;

	tmp = x + buf->width;
	if (tmp < x || x >= disp->fbdev.xres)
		return -EINVAL;
	if (tmp > disp->fbdev.xres)
		width = disp->fbdev.xres - x;
	else
		width = buf->width;

	tmp = y + buf->height;
	if (tmp < y || y >= disp->fbdev.yres)
		return -EINVAL;
	if (tmp > disp->fbdev.yres)
		height = disp->fbdev.yres - y;
	else
		height = buf->height;

	if (!(disp->flags & DISPLAY_DBUF) || disp->fbdev.bufid)
		dst = disp->fbdev.map;
	else
		dst = &disp->fbdev.map[disp->fbdev.yres * disp->fbdev.stride];
	dst = &dst[y * disp->fbdev.stride + x * disp->fbdev.bpp];
	src = buf->data;

	if (buf->format == UTERM_FORMAT_GREY) {
		while (height--) {
			for (i = 0; i < width; ++i) {
				r = (fr & 0xff) * src[i] / 255 +
				    (br & 0xff) * (255 - src[i]) / 255;
				g = (fg & 0xff) * src[i] / 255 +
				    (bg & 0xff) * (255 - src[i]) / 255;
				b = (fb & 0xff) * src[i] / 255 +
				    (bb & 0xff) * (255 - src[i]) / 255;
				((uint32_t*)dst)[i] =
					((r & 0xff) << 16) |
					((g & 0xff) << 8) |
					 (b & 0xff);
			}
			dst += disp->fbdev.stride;
			src += buf->stride;
		}
	} else {
		log_warning("using unsupported buffer format for blending");
	}

	return 0;
}
Example #23
0
static int display_activate(struct uterm_display *disp, struct uterm_mode *mode)
{
	struct uterm_video *video = disp->video;
	int ret, crtc, i;
	drmModeRes *res;
	drmModeConnector *conn;
	drmModeEncoder *enc;

	if (!video || !video_is_awake(video) || !mode)
		return -EINVAL;
	if (display_is_online(disp))
		return -EINVAL;

	log_info("activating display %p to %ux%u", disp,
			mode->dumb.info.hdisplay, mode->dumb.info.vdisplay);

	res = drmModeGetResources(video->dumb.fd);
	if (!res) {
		log_err("cannot get resources for display %p", disp);
		return -EFAULT;
	}
	conn = drmModeGetConnector(video->dumb.fd, disp->dumb.conn_id);
	if (!conn) {
		log_err("cannot get connector for display %p", disp);
		drmModeFreeResources(res);
		return -EFAULT;
	}

	crtc = -1;
	for (i = 0; i < conn->count_encoders; ++i) {
		enc = drmModeGetEncoder(video->dumb.fd, conn->encoders[i]);
		if (!enc)
			continue;
		crtc = find_crtc(video, res, enc);
		drmModeFreeEncoder(enc);
		if (crtc >= 0)
			break;
	}

	drmModeFreeConnector(conn);
	drmModeFreeResources(res);

	if (crtc < 0) {
		log_warn("cannot find crtc for new display");
		return -ENODEV;
	}

	disp->dumb.crtc_id = crtc;
	disp->dumb.current_rb = 0;
	disp->current_mode = mode;
	disp->dumb.saved_crtc = drmModeGetCrtc(video->dumb.fd,
					       disp->dumb.crtc_id);

	ret = init_rb(disp, &disp->dumb.rb[0]);
	if (ret)
		goto err_saved;

	ret = init_rb(disp, &disp->dumb.rb[1]);
	if (ret)
		goto err_rb;

	ret = drmModeSetCrtc(video->dumb.fd, disp->dumb.crtc_id,
			disp->dumb.rb[0].fb, 0, 0, &disp->dumb.conn_id, 1,
			&disp->current_mode->dumb.info);
	if (ret) {
		log_err("cannot set drm-crtc");
		ret = -EFAULT;
		goto err_fb;
	}

	disp->flags |= DISPLAY_ONLINE;
	return 0;

err_fb:
	destroy_rb(disp, &disp->dumb.rb[1]);
err_rb:
	destroy_rb(disp, &disp->dumb.rb[0]);
err_saved:
	disp->current_mode = NULL;
	if (disp->dumb.saved_crtc) {
		drmModeFreeCrtc(disp->dumb.saved_crtc);
		disp->dumb.saved_crtc = NULL;
	}
	return ret;
}
Example #24
0
static int hotplug(struct uterm_video *video)
{
	drmModeRes *res;
	drmModeConnector *conn;
	struct uterm_display *disp, *tmp;
	int i;

	if (!video_is_awake(video) || !video_need_hotplug(video))
		return 0;

	res = drmModeGetResources(video->dumb.fd);
	if (!res) {
		log_err("cannot retrieve drm resources");
		return -EACCES;
	}

	for (disp = video->displays; disp; disp = disp->next)
		disp->flags &= ~DISPLAY_AVAILABLE;

	for (i = 0; i < res->count_connectors; ++i) {
		conn = drmModeGetConnector(video->dumb.fd, res->connectors[i]);
		if (!conn)
			continue;
		if (conn->connection == DRM_MODE_CONNECTED) {
			for (disp = video->displays; disp; disp = disp->next) {
				if (disp->dumb.conn_id == res->connectors[i]) {
					disp->flags |= DISPLAY_AVAILABLE;
					break;
				}
			}
			if (!disp)
				bind_display(video, res, conn);
		}
		drmModeFreeConnector(conn);
	}

	drmModeFreeResources(res);

	while (video->displays) {
		tmp = video->displays;
		if (tmp->flags & DISPLAY_AVAILABLE)
			break;

		video->displays = tmp->next;
		tmp->next = NULL;
		unbind_display(tmp);
	}
	for (disp = video->displays; disp && disp->next; ) {
		tmp = disp->next;
		if (tmp->flags & DISPLAY_AVAILABLE) {
			disp = tmp;
		} else {
			disp->next = tmp->next;
			tmp->next = NULL;
			unbind_display(tmp);
		}
	}

	video->flags &= ~VIDEO_HOTPLUG;
	return 0;
}
Example #25
0
static int display_blend(struct uterm_display *disp,
			 const struct uterm_video_buffer *buf,
			 unsigned int x, unsigned int y,
			 uint8_t fr, uint8_t fg, uint8_t fb,
			 uint8_t br, uint8_t bg, uint8_t bb)
{
	unsigned int tmp;
	uint8_t *dst, *src;
	struct dumb_rb *rb;
	unsigned int width, height, i;
	unsigned int sw, sh;
	unsigned int r, g, b;

	if (!disp->video || !display_is_online(disp))
		return -EINVAL;
	if (!buf || !video_is_awake(disp->video))
		return -EINVAL;

	rb = &disp->dumb.rb[disp->dumb.current_rb ^ 1];
	sw = disp->current_mode->dumb.info.hdisplay;
	sh = disp->current_mode->dumb.info.vdisplay;

	tmp = x + buf->width;
	if (tmp < x || x >= sw)
		return -EINVAL;
	if (tmp > sw)
		width = sw - x;
	else
		width = buf->width;

	tmp = y + buf->height;
	if (tmp < y || y >= sh)
		return -EINVAL;
	if (tmp > sh)
		height = sh - y;
	else
		height = buf->height;

	dst = rb->map;
	dst = &dst[y * rb->stride + x * 4];
	src = buf->data;

	if (buf->format == UTERM_FORMAT_GREY) {
		while (height--) {
			for (i = 0; i < width; ++i) {
				r = (fr & 0xff) * src[i] / 255 +
				    (br & 0xff) * (255 - src[i]) / 255;
				g = (fg & 0xff) * src[i] / 255 +
				    (bg & 0xff) * (255 - src[i]) / 255;
				b = (fb & 0xff) * src[i] / 255 +
				    (bb & 0xff) * (255 - src[i]) / 255;
				((uint32_t*)dst)[i] =
					((r & 0xff) << 16) |
					((g & 0xff) << 8) |
					 (b & 0xff);
			}
			dst += rb->stride;
			src += buf->stride;
		}
	} else {
		log_warning("using unsupported buffer format for blending");
	}

	return 0;
}
Example #26
0
static int display_fake_blendv(struct uterm_display *disp,
			       const struct uterm_video_blend_req *req,
			       size_t num)
{
	unsigned int tmp;
	uint8_t *dst, *src;
	struct dumb_rb *rb;
	unsigned int width, height, i, j;
	unsigned int sw, sh;
	unsigned int r, g, b;

	if (!disp->video || !display_is_online(disp))
		return -EINVAL;
	if (!req || !video_is_awake(disp->video))
		return -EINVAL;

	rb = &disp->dumb.rb[disp->dumb.current_rb ^ 1];
	sw = disp->current_mode->dumb.info.hdisplay;
	sh = disp->current_mode->dumb.info.vdisplay;

	for (j = 0; j < num; ++j, ++req) {
		if (!req->buf)
			continue;

		if (req->buf->format != UTERM_FORMAT_GREY)
			return -EOPNOTSUPP;

		tmp = req->x + req->buf->width;
		if (tmp < req->x || req->x >= sw)
			return -EINVAL;
		if (tmp > sw)
			width = sw - req->x;
		else
			width = req->buf->width;

		tmp = req->y + req->buf->height;
		if (tmp < req->y || req->y >= sh)
			return -EINVAL;
		if (tmp > sh)
			height = sh - req->y;
		else
			height = req->buf->height;

		dst = rb->map;
		dst = &dst[req->y * rb->stride + req->x * 4];
		src = req->buf->data;

		while (height--) {
			for (i = 0; i < width; ++i) {
				/* Division by 256 instead of 255 increases
				 * speed by like 20% on slower machines.
				 * Downside is, full white is 254/254/254
				 * instead of 255/255/255. */
				if (src[i] == 0) {
					r = req->br;
					g = req->bg;
					b = req->bb;
				} else if (src[i] == 255) {
					r = req->fr;
					g = req->fg;
					b = req->fb;
				} else {
					r = req->fr * src[i] +
					    req->br * (255 - src[i]);
					r /= 256;
					g = req->fg * src[i] +
					    req->bg * (255 - src[i]);
					g /= 256;
					b = req->fb * src[i] +
					    req->bb * (255 - src[i]);
					b /= 256;
				}
				((uint32_t*)dst)[i] = (r << 16) | (g << 8) | b;
			}
			dst += rb->stride;
			src += req->buf->stride;
		}
	}

	return 0;
}
Example #27
0
static int display_set_dpms(struct uterm_display *disp, int state)
{
	int i, ret, set;
	drmModeConnector *conn;
	drmModePropertyRes *prop;

	if (!display_is_conn(disp) || !video_is_awake(disp->video))
		return -EINVAL;

	switch (state) {
	case UTERM_DPMS_ON:
		set = DRM_MODE_DPMS_ON;
		break;
	case UTERM_DPMS_STANDBY:
		set = DRM_MODE_DPMS_STANDBY;
		break;
	case UTERM_DPMS_SUSPEND:
		set = DRM_MODE_DPMS_SUSPEND;
		break;
	case UTERM_DPMS_OFF:
		set = DRM_MODE_DPMS_OFF;
		break;
	default:
		return -EINVAL;
	}

	log_info("setting DPMS of display %p to %s", disp,
			uterm_dpms_to_name(state));

	conn = drmModeGetConnector(disp->video->dumb.fd, disp->dumb.conn_id);
	if (!conn) {
		log_err("cannot get display connector");
		return -EFAULT;
	}

	ret = 0;
	for (i = 0; i < conn->count_props; ++i) {
		prop = drmModeGetProperty(disp->video->dumb.fd, conn->props[i]);
		if (!prop)
			continue;

		if (!strcmp(prop->name, "DPMS")) {
			ret = drmModeConnectorSetProperty(disp->video->dumb.fd,
				disp->dumb.conn_id, prop->prop_id, set);
			if (ret) {
				log_info("cannot set DPMS");
				ret = -EFAULT;
			}
			drmModeFreeProperty(prop);
			break;
		}
		drmModeFreeProperty(prop);
	}

	if (i == conn->count_props) {
		ret = 0;
		log_warn("display does not support DPMS");
		state = UTERM_DPMS_UNKNOWN;
	}

	drmModeFreeConnector(conn);
	disp->dpms = state;
	return ret;
}
Example #28
0
bool uterm_video_is_awake(struct uterm_video *video)
{
	return video && video_is_awake(video);
}
Example #29
0
static int display_blend(struct uterm_display *disp,
			 const struct uterm_video_buffer *buf,
			 unsigned int x, unsigned int y,
			 uint8_t fr, uint8_t fg, uint8_t fb,
			 uint8_t br, uint8_t bg, uint8_t bb)
{
	unsigned int tmp;
	uint8_t *dst, *src;
	struct dumb_rb *rb;
	unsigned int width, height, i;
	unsigned int sw, sh;
	unsigned int r, g, b;

	if (!disp->video || !display_is_online(disp))
		return -EINVAL;
	if (!buf || !video_is_awake(disp->video))
		return -EINVAL;

	rb = &disp->dumb.rb[disp->dumb.current_rb ^ 1];
	sw = disp->current_mode->dumb.info.hdisplay;
	sh = disp->current_mode->dumb.info.vdisplay;

	tmp = x + buf->width;
	if (tmp < x || x >= sw)
		return -EINVAL;
	if (tmp > sw)
		width = sw - x;
	else
		width = buf->width;

	tmp = y + buf->height;
	if (tmp < y || y >= sh)
		return -EINVAL;
	if (tmp > sh)
		height = sh - y;
	else
		height = buf->height;

	dst = rb->map;
	dst = &dst[y * rb->stride + x * 4];
	src = buf->data;

	if (buf->format == UTERM_FORMAT_GREY) {
		while (height--) {
			for (i = 0; i < width; ++i) {
				/* Division by 256 instead of 255 increases
				 * speed by like 20% on slower machines.
				 * Downside is, full white is 254/254/254
				 * instead of 255/255/255. */
				if (src[i] == 0) {
					r = br;
					g = bg;
					b = bb;
				} else if (src[i] == 255) {
					r = fr;
					g = fg;
					b = fb;
				} else {
					r = fr * src[i] +
					    br * (255 - src[i]);
					r /= 256;
					g = fg * src[i] +
					    bg * (255 - src[i]);
					g /= 256;
					b = fb * src[i] +
					    bb * (255 - src[i]);
					b /= 256;
				}
				((uint32_t*)dst)[i] = (r << 16) | (g << 8) | b;
			}
			dst += rb->stride;
			src += buf->stride;
		}
	} else {
		log_warning("using unsupported buffer format for blending");
	}

	return 0;
}