示例#1
0
文件: if_mem.c 项目: kanzure/brlcad
HIDDEN int
mem_poll(FBIO *ifp)
{
    if (MI(ifp)->write_thru) {
	return fb_poll(MI(ifp)->fbp);
    }
    return 0;
}
static void
sigalarm(int UNUSED(code))
{
    printf("alarm %s\n", fb_server_fbp ? "FBP" : "NULL");
    if ( fb_server_fbp != FB_NULL ) {
	fb_poll(fb_server_fbp);
    }
#ifdef SIGALRM
    (void)signal( SIGALRM, sigalarm );	/* some systems remove handler */
#endif
    alarm(1);
}
/*
 *  Loop forever handling clients as they come and go.
 *  Access to the framebuffer may be interleaved, if the user
 *  wants it that way.
 */
static void
main_loop(void)
{
    int	nopens = 0;
    int	ncloses = 0;

    while ( !fb_server_got_fb_free ) {
	long refresh_rate = 60000000; /* old default */
	fd_set infds;
	struct timeval tv;
	int	i;

	if (fb_server_fbp) {
	    if (fb_poll_rate(fb_server_fbp) > 0)
		refresh_rate = fb_poll_rate(fb_server_fbp);
	}

	infds = select_list;	/* struct copy */

	tv.tv_sec = 0L;
	tv.tv_usec = refresh_rate;
	if ((select( max_fd+1, &infds, (fd_set *)0, (fd_set *)0, (struct timeval *)&tv ) == 0)) {
	    /* Process fb events while waiting for client */
	    /*printf("select timeout waiting for client\n");*/
	    if (fb_server_fbp) {
		if (fb_poll(fb_server_fbp)) {
		    return;
		}
	    }
	    continue;
	}
	/* Handle any events from the framebuffer */
	if (fb_is_set_fd(fb_server_fbp, &infds)) {
	    fb_poll(fb_server_fbp);
	}

	/* Accept any new client connections */
	if (netfd > 0 && FD_ISSET(netfd, &infds)) {
	    new_client( pkg_getclient( netfd, fb_server_pkg_switch, comm_error, 0 ) );
	    nopens++;
	}

	/* Process arrivals from existing clients */
	/* First, pull the data out of the kernel buffers */
	for (i = MAX_CLIENTS-1; i >= 0; i--) {
	    if (clients[i] == NULL )  continue;
	    if (pkg_process( clients[i] ) < 0) {
		fprintf(stderr, "pkg_process error encountered (1)\n");
	    }
	    if (! FD_ISSET( clients[i]->pkc_fd, &infds )) continue;
	    if (pkg_suckin( clients[i] ) <= 0) {
		/* Probably EOF */
		drop_client( i );
		ncloses++;
		continue;
	    }
	}
	/* Second, process all the finished ones that we just got */
	for (i = MAX_CLIENTS-1; i >= 0; i--) {
	    if (clients[i] == NULL )  continue;
	    if (pkg_process( clients[i] ) < 0) {
		fprintf(stderr, "pkg_process error encountered (2)\n");
	    }
	}
	if (once_only && nopens > 1 && ncloses > 1)
	    return;
    }
}
示例#4
0
static void fb_wait(GP_Backend *self)
{
	struct fb_priv *fb = GP_BACKEND_PRIV(self);

	struct pollfd fd = {.fd = fb->con_fd, .events = POLLIN, .revents = 0};

	if (poll(&fd, 1, -1) > 0)
		fb_poll(self);
	else
		GP_WARN("poll(): %s", strerror(errno));
}

static void fb_exit(GP_Backend *self)
{
	struct fb_priv *fb = GP_BACKEND_PRIV(self);

	/* unmap framebuffer */
	munmap(fb->context.pixels, fb->bsize);
	close(fb->fb_fd);

	/* reset keyboard */
	ioctl(fb->con_fd, KDSETMODE, KD_TEXT);

	/* restore keyboard mode */
	if (fb->flag) {
		if (ioctl(fb->con_fd, KDSKBMODE, fb->saved_kb_mode) < 0) {
			GP_DEBUG(1, "Failed to ioctl KDSKBMODE (restore KBMODE)"
                                 " /dev/tty%i: %s", fb->con_nr, strerror(errno));
		}
	}

	/* switch back console */
	if (fb->last_con_nr != -1)
		ioctl(fb->con_fd, VT_ACTIVATE, fb->last_con_nr);

	close(fb->con_fd);
	free(self);
}

GP_Backend *GP_BackendLinuxFBInit(const char *path, int flag)
{
	GP_Backend *backend;
	struct fb_priv *fb;
	struct fb_fix_screeninfo fscri;
	struct fb_var_screeninfo vscri;
	int fd;

	backend = malloc(sizeof(GP_Backend) +
	                 sizeof(struct fb_priv) + strlen(path) + 1);

	if (backend == NULL)
		return NULL;

	fb = GP_BACKEND_PRIV(backend);

	if (allocate_console(fb, flag))
		goto err1;

	/* open and mmap framebuffer */
	GP_DEBUG(1, "Opening framebuffer '%s'", path);

	fd = open(path, O_RDWR);

	if (fd < 0) {
		GP_DEBUG(1, "Opening framebuffer failed: %s", strerror(errno));
		goto err2;
	}

	if (ioctl(fd, FBIOGET_FSCREENINFO, &fscri) < 0) {
		GP_DEBUG(1, "Failed to ioctl FBIOGET_FSCREENINFO: %s",
		            strerror(errno));
		goto err3;
	}

	if (ioctl(fd, FBIOGET_VSCREENINFO, &vscri) < 0) {
		GP_DEBUG(1, "Failed to ioctl FBIOGET_VSCREENINFO: %s",
		            strerror(errno));
		goto err3;
	}

	GP_DEBUG(1, "Have framebufer %ix%i %s %ibpp", vscri.xres, vscri.yres,
                 vscri.grayscale ? "Gray" : "RGB", vscri.bits_per_pixel);

	/*
	 * Framebuffer is grayscale.
	 */
	if (vscri.grayscale) {
		//TODO
		goto err3;
	}

	enum GP_PixelType pixel_type;
	pixel_type = GP_PixelRGBLookup(vscri.red.length,    vscri.red.offset,
	                               vscri.green.length,  vscri.green.offset,
	                               vscri.blue.length,   vscri.blue.offset,
	                               vscri.transp.length, vscri.transp.offset,
	                               vscri.bits_per_pixel);

	if (pixel_type == GP_PIXEL_UNKNOWN) {
		GP_DEBUG(1, "Unknown pixel type\n");
		goto err3;
	}

	fb->context.pixels = mmap(NULL, fscri.smem_len,
	                          PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
				  fd, 0);

	if (fb->context.pixels == MAP_FAILED) {
		GP_DEBUG(1, "mmaping framebuffer failed: %s", strerror(errno));
		goto err3;
	}

	fb->fb_fd = fd;
	fb->bsize  = fscri.smem_len;
	strcpy(fb->path, path);
	fb->flag = flag;

	fb->context.w = vscri.xres;
	fb->context.h = vscri.yres;

	fb->context.axes_swap = 0;
	fb->context.x_swap    = 0;
	fb->context.y_swap    = 0;

	fb->context.bpp = vscri.bits_per_pixel;
	fb->context.bytes_per_row  = fscri.line_length;
	fb->context.pixel_type = pixel_type;

	/* update API */
	backend->name          = "Linux FB";
	backend->context       = &fb->context;
	backend->Flip          = NULL;
	backend->UpdateRect    = NULL;
	backend->Exit          = fb_exit;
	backend->SetAttributes = NULL;
	backend->ResizeAck     = NULL;
	backend->Poll          = flag ? fb_poll : NULL;
	backend->Wait          = flag ? fb_wait : NULL;
	backend->fd            = fb->con_fd;
	backend->timers        = NULL;

	GP_EventQueueInit(&backend->event_queue, vscri.xres, vscri.yres, 0);

	return backend;
err3:
	close(fd);
err2:
	close(fb->con_fd);

	/* reset keyboard */
	ioctl(fb->con_fd, KDSETMODE, KD_TEXT);

	/* switch back console */
	if (fb->last_con_nr != -1)
		ioctl(fb->con_fd, VT_ACTIVATE, fb->last_con_nr);
err1:
	free(backend);
	return NULL;
}
示例#5
0
static void fb_wait(GP_Backend *self)
{
	struct fb_priv *fb = GP_BACKEND_PRIV(self);

	struct pollfd fd = {.fd = fb->con_fd, .events = POLLIN, .revents = 0};

	if (poll(&fd, 1, -1) > 0)
		fb_poll(self);
	else
		GP_WARN("poll(): %s", strerror(errno));
}

static void fb_exit(GP_Backend *self)
{
	struct fb_priv *fb = GP_BACKEND_PRIV(self);

	if (fb->flags & GP_FB_SHADOW)
		free(fb->context.pixels);

	/* unmap framebuffer */
	munmap(fb->fb_mem, fb->bsize);
	close(fb->fb_fd);

	if (fb->flags & GP_FB_INPUT_KBD)
		exit_kbd(fb);

	free_console(fb);

	free(self);
}

static void fb_flip_shadow(GP_Backend *self)
{
	struct fb_priv *fb = GP_BACKEND_PRIV(self);

	GP_DEBUG(2, "Flipping buffer");

	memcpy(fb->fb_mem, fb->context.pixels, fb->bsize);
}

static void fb_update_rect_shadow(GP_Backend *self, GP_Coord x0, GP_Coord y0,
                                  GP_Coord x1, GP_Coord y1)
{
	struct fb_priv *fb = GP_BACKEND_PRIV(self);

	GP_DEBUG(2, "Flipping buffer");

	size_t size = ((x1 - x0) * fb->context.bpp) / 8;

	for (;y0 <= y1; y0++) {
		void *src = GP_PIXEL_ADDR(&fb->context, x0, y0);
		void *dst = (char*)fb->fb_mem +
                            y0 * fb->context.bytes_per_row +
                            (x0 * fb->context.bpp)/8;
		memcpy(dst, src, size);
	}
}

GP_Backend *GP_BackendLinuxFBInit(const char *path, int flags)
{
	GP_Backend *backend;
	struct fb_priv *fb;
	struct fb_fix_screeninfo fscri;
	struct fb_var_screeninfo vscri;
	int fd;

	backend = malloc(sizeof(GP_Backend) +
	                 sizeof(struct fb_priv) + strlen(path) + 1);

	if (backend == NULL)
		return NULL;

	fb = GP_BACKEND_PRIV(backend);

	if (allocate_console(fb, flags))
		goto err0;

	if (flags & GP_FB_INPUT_KBD) {
		if (init_kbd(fb))
			goto err1;
	}

	/* open and mmap framebuffer */
	GP_DEBUG(1, "Opening framebuffer '%s'", path);

	fd = open(path, O_RDWR);

	if (fd < 0) {
		GP_DEBUG(1, "Opening framebuffer failed: %s", strerror(errno));
		goto err2;
	}

	if (ioctl(fd, FBIOGET_FSCREENINFO, &fscri) < 0) {
		GP_DEBUG(1, "Failed to ioctl FBIOGET_FSCREENINFO: %s",
		            strerror(errno));
		goto err3;
	}

	if (ioctl(fd, FBIOGET_VSCREENINFO, &vscri) < 0) {
		GP_DEBUG(1, "Failed to ioctl FBIOGET_VSCREENINFO: %s",
		            strerror(errno));
		goto err3;
	}

	GP_DEBUG(1, "Have framebufer %ix%i %s %ibpp", vscri.xres, vscri.yres,
                 vscri.grayscale ? "Gray" : "RGB", vscri.bits_per_pixel);

	/*
	 * Framebuffer is grayscale.
	 */
	if (vscri.grayscale) {
		GP_WARN("Grayscale not implemented!");
		goto err3;
	}

	enum GP_PixelType pixel_type;
	pixel_type = GP_PixelRGBLookup(vscri.red.length,    vscri.red.offset,
	                               vscri.green.length,  vscri.green.offset,
	                               vscri.blue.length,   vscri.blue.offset,
	                               vscri.transp.length, vscri.transp.offset,
	                               vscri.bits_per_pixel);

	if (pixel_type == GP_PIXEL_UNKNOWN) {
		GP_DEBUG(1, "Unknown pixel type\n");
		goto err3;
	}

	if (flags & GP_FB_SHADOW) {
		fb->context.pixels = malloc(fscri.smem_len);

		if (!fb->context.pixels) {
			GP_DEBUG(1, "Malloc failed :(");
			goto err3;
		}
	}

	fb->fb_mem = mmap(NULL, fscri.smem_len,
	                  PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0);

	if (fb->fb_mem == MAP_FAILED) {
		GP_DEBUG(1, "mmaping framebuffer failed: %s", strerror(errno));
		goto err4;
	}

	fb->fb_fd = fd;
	fb->bsize = fscri.smem_len;
	strcpy(fb->path, path);
	fb->flags = flags;

	if (!(flags & GP_FB_SHADOW))
		fb->context.pixels = fb->fb_mem;

	fb->context.w = vscri.xres;
	fb->context.h = vscri.yres;

	fb->context.axes_swap = 0;
	fb->context.x_swap    = 0;
	fb->context.y_swap    = 0;

	fb->context.bpp = vscri.bits_per_pixel;
	fb->context.bytes_per_row  = fscri.line_length;
	fb->context.pixel_type = pixel_type;

	int shadow = flags & GP_FB_SHADOW;
	int kbd = flags & GP_FB_INPUT_KBD;

	/* update API */
	backend->name          = "Linux FB";
	backend->context       = &fb->context;
	backend->Flip          = shadow ? fb_flip_shadow : NULL;
	backend->UpdateRect    = shadow ? fb_update_rect_shadow : NULL;
	backend->Exit          = fb_exit;
	backend->SetAttributes = NULL;
	backend->ResizeAck     = NULL;
	backend->Poll          = kbd ? fb_poll : NULL;
	backend->Wait          = kbd ? fb_wait : NULL;
	backend->fd            = fb->con_fd;
	backend->timers        = NULL;

	GP_EventQueueInit(&backend->event_queue, vscri.xres, vscri.yres, 0);

	return backend;
err4:
	if (flags & GP_FB_SHADOW)
		free(fb->context.pixels);
err3:
	close(fd);
err2:
	if (flags & GP_FB_INPUT_KBD)
		exit_kbd(fb);
err1:
	free_console(fb);
err0:
	free(backend);
	return NULL;
}