Ejemplo n.º 1
0
static int
GGIopen(ggi_visual * vis, struct ggi_dlhandle *dlh,
	const char *args, void *argptr, uint32_t * dlret)
{
	int err = GGI_OK;
	directx_priv *priv;
	GGIGII ggigii;
	gg_option options[NUM_OPTS];

	DPRINT("DirectX-target starting\n");

	memcpy(options, optlist, sizeof(options));

	priv = malloc(sizeof(directx_priv));
	if (priv == NULL) {
		err = GGI_ENOMEM;
		goto err0;
	}
	if ((LIBGGI_GC(vis) = malloc(sizeof(ggi_gc))) == NULL) {
		err = GGI_ENOMEM;
		goto err1;
	}

	memset(priv, 0, sizeof(directx_priv));
	LIBGGI_PRIVATE(vis) = priv;

	priv->cs = GGI_directx_LockCreate();
	if (priv->cs == NULL) {
		err = GGI_ENOMEM;
		goto err2;
	}
	priv->spincs = GGI_directx_LockCreate();
	if (priv->spincs == NULL) {
		err = GGI_ENOMEM;
		goto err3;
	}
	priv->redraw = 1;
	priv->setpalette = 1;

	priv->sizingcs = GGI_directx_LockCreate();
	if (priv->sizingcs == NULL) {
		err = GGI_ENOMEM;
		goto err4;
	}
	priv->xmin = 0;
	priv->ymin = 0;
	priv->xmax = 0;
	priv->ymax = 0;
	priv->xstep = -1;
	priv->ystep = -1;

	if (args) {
		args = ggParseOptions(args, options, NUM_OPTS);
		if (args == NULL) {
			fprintf(stderr, "display-directx: error in "
				"arguments.\n");
		}
	}

	if (_ggi_physz_parse_option(options[OPT_PHYSZ].result,
				    &(priv->physzflags), &(priv->physz))) {
		err = GGI_EARGINVAL;
		goto err5;
	}

	if (options[OPT_KEEPCURSOR].result[0] == 'n') {
		priv->cursortype =
		    (options[OPT_NOCURSOR].result[0] == 'n') ? 1 : 0;
	} else {
		priv->cursortype = 2;
	}

	if (options[OPT_INWIN].result[0] != 'n') {
		if (strcmp(options[OPT_INWIN].result, "root")) {
			priv->hParent = (HANDLE)
			    strtoul(options[OPT_INWIN].result, NULL, 0);
			if (!IsWindow(priv->hParent)) {
				fprintf(stderr,
					"0x%08x "
					"is not a valid window handle.\n",
					(unsigned) priv->hParent);
				priv->hParent = NULL;
			}
		} else
			priv->hParent = GetDesktopWindow();
	}

	if (options[OPT_FULLSCREEN].result[0] == 'n') {
		priv->fullscreen = 0;
	} else {
		priv->fullscreen = 1;
	}

	if (!DDInit(vis)) {
		err = GGI_ENODEVICE;
		goto err3;
	}

	ggigii.hWnd = priv->hWnd;
	ggigii.hInstance = priv->hInstance;

	if (tolower((uint8_t) options[OPT_NOINPUT].result[0]) == 'n' &&
	    /* FIXME: dxinput doesn't work with -inwin yet; the following
	       condition disables the default input target if -inwin has been
	       specified */
	    (!priv->hParent ||
	     getenv("GGI_INPUT") || getenv("GGI_INPUT_directx"))) {
		gii_input *inp;

		inp = giiOpen("directx", &ggigii, NULL);
		if (inp == NULL) {
			DPRINT_MISC("Unable to open directx inputlib\n");
			GGIclose(vis, dlh);
			err = GGI_ENODEVICE;
			goto err3;
		}

		priv->inp = inp;
		/* Now join the new event source in. */
		vis->input = giiJoinInputs(vis->input, inp);
	} else {
		priv->inp = NULL;
	}

	vis->opdisplay->setmode = GGI_directx_setmode;
	vis->opdisplay->getmode = GGI_directx_getmode;
	vis->opdisplay->setflags = GGI_directx_setflags;
	vis->opdisplay->checkmode = GGI_directx_checkmode;
	vis->opdisplay->flush = GGI_directx_flush;
	vis->opdisplay->getapi = GGI_directx_getapi;

	*dlret = GGI_DL_OPDISPLAY | GGI_DL_OPDRAW;
	return GGI_OK;

err5:
	GGI_directx_LockDestroy(priv->cs);
err4:
	GGI_directx_LockDestroy(priv->spincs);
err3:
	GGI_directx_LockDestroy(priv->sizingcs);
err2:
	free(LIBGGI_GC(vis));
err1:
	free(priv);
err0:
	return err;
}
Ejemplo n.º 2
0
static int GGIopen(struct ggi_visual *vis, struct ggi_dlhandle *dlh,
                        const char *args, void *argptr, uint32_t *dlret)
{
        gg_option options[NUM_OPTS];
        ggi_libkgi_priv *priv;
	int err;

	/* We need LibGAlloc to be initialized.  Seems OK to do so
	 * from inside here. It would be nice to Attach it here too,
	 * but I'm less confident that that would work :-)
	 */
	ggiGAInit();

        DPRINT("display-libkgi: GGIopen start.\n");

        memcpy(options, optlist, sizeof(options));
        if (args) {
                args = ggParseOptions(args, options, NUM_OPTS);
                if (args == NULL) {
                        fprintf(stderr, "display-libkgi: error in "
                                "arguments.\n");
                        return GGI_EARGINVAL;
                }
        }

        LIBKGI_PRIV(vis) = priv = malloc(sizeof(ggi_libkgi_priv));
        if (priv == NULL) {
                return GGI_ENOMEM;
        }

        priv->have_accel = 0;
        priv->accelpriv = NULL;
        priv->flush = NULL;
        priv->idleaccel = NULL;

	snprintf(priv->suggest, sizeof(priv->suggest), "foodrv");

        DPRINT("display-libkgi: Parsing physz options.\n");
	err = _ggi_physz_parse_option(options[OPT_PHYSZ].result, 
			       &(priv->physzflags), &(priv->physz)); 
	if (err != GGI_OK) {
		do_cleanup(vis);
		return err;
	}

#if 0
	/* Don't know how this will pan out */
	err = kgiInit(&priv->ctx, &priv->client_name, &priv->client_version);
	if (err != KGI_EOK) {
		do_cleanup(vis);
		return err;
	}
	LIBGGI_FD(vis) = priv->ctx.mapper.fd;
#endif

        DPRINT("display-libkgi: Setting up locks.\n");
        ggLock(_ggi_global_lock);
        if (refcount == 0) {
                _ggi_libkgi_lock = ggLockCreate();
                if (_ggi_libkgi_lock == NULL) {
                        ggUnlock(_ggi_global_lock);
                        free(priv);
                        return GGI_ENOMEM;
                }
        }
        priv->lock = _ggi_libkgi_lock;
        priv->refcount = &refcount;
        refcount++;
        ggUnlock(_ggi_global_lock);

	priv->galloc_loaded = 0;

	LIBKGI_PRIV(vis) = priv;

        /* Mode management */
        vis->opdisplay->flush     = GGI_libkgi_flush;
	/* kgicommand obselete */
        vis->opdisplay->getapi    = GGI_libkgi_getapi;
        vis->opdisplay->setflags  = GGI_libkgi_setflags;
        vis->opdisplay->idleaccel = GGI_libkgi_idleaccel;
        vis->opdisplay->getmode   = GGI_libkgi_getmode;
        vis->opdisplay->checkmode = GGI_libkgi_checkmode;
        vis->opdisplay->setmode   = GGI_libkgi_setmode;
        vis->opdisplay->sendevent = GGI_libkgi_sendevent;

	/* GC management */
        vis->opgc->gcchanged = GGI_libkgi_gcchanged;

	/* Drawops. We don't supply _nc variants as we only do fully 
	 * implemented renderers.
	 */
	vis->opdraw->setorigin		= GGI_libkgi_setorigin;
	vis->opdraw->setdisplayframe	= GGI_libkgi_setdisplayframe;
        vis->opdraw->setreadframe	= GGI_libkgi_setreadframe;
        vis->opdraw->setwriteframe	= GGI_libkgi_setwriteframe;
        vis->opdraw->fillscreen		= GGI_libkgi_fillscreen;
        vis->opdraw->putc		= GGI_libkgi_putc;
        vis->opdraw->puts		= GGI_libkgi_puts;
        vis->opdraw->getcharsize	= GGI_libkgi_getcharsize;
        vis->opdraw->drawpixel		= GGI_libkgi_drawpixel;
        vis->opdraw->putpixel		= GGI_libkgi_putpixel;
        vis->opdraw->getpixel		= GGI_libkgi_getpixel;
        vis->opdraw->drawline		= GGI_libkgi_drawline;
        vis->opdraw->drawhline		= GGI_libkgi_drawhline;
        vis->opdraw->puthline		= GGI_libkgi_puthline;
        vis->opdraw->gethline		= GGI_libkgi_gethline;
        vis->opdraw->drawvline		= GGI_libkgi_drawvline;
        vis->opdraw->putvline		= GGI_libkgi_putvline;
        vis->opdraw->getvline		= GGI_libkgi_getvline;
        vis->opdraw->drawbox		= GGI_libkgi_drawbox;
        vis->opdraw->putbox		= GGI_libkgi_putbox;
        vis->opdraw->getbox		= GGI_libkgi_getbox;
        vis->opdraw->copybox		= GGI_libkgi_copybox;
        vis->opdraw->crossblit		= GGI_libkgi_crossblit;

	/* Color ops will use generic color libs. */

        /* Register cleanup handler */
        ggRegisterCleanup((ggcleanup_func *)do_cleanup, vis);

        DPRINT("display-libkgi: GGIopen success.\n");

        *dlret = GGI_DL_OPDISPLAY;
        return 0;
}
Ejemplo n.º 3
0
static int GGIopen(ggi_visual *vis, struct ggi_dlhandle *dlh,
		   const char *args, void *argptr, uint32_t *dlret)
{
	ggi_ipc_priv *priv;
	gg_option options[NUM_OPTS];
	struct sockaddr_un address;

	DPRINT_MISC("display-ipc coming up.\n");
	memcpy(options, optlist, sizeof(options));

	LIBGGI_GC(vis) = malloc(sizeof(ggi_gc));
	if (!LIBGGI_GC(vis)) return GGI_ENOMEM;

	/* Allocate descriptor for screen memory */
	priv = malloc(sizeof(ggi_ipc_priv));

	if (!priv) {
		free(LIBGGI_GC(vis));
		return GGI_ENOMEM;
	}	/* if */

	LIBGGI_PRIVATE(vis) = priv;
	priv->inputbuffer = NULL;	/* Default to no input */
	priv->inputoffset = 0;		/* Setup offset. */

	if (!args) {
		DPRINT("display-ipc: required arguments missing\n");
		return GGI_EARGREQ;
	}	/* if */

	args = ggParseOptions(args, options, NUM_OPTS);
	if (args == NULL) {
		DPRINT("display-ipc: error in arguments.\n");
		return GGI_EARGREQ;
	}	/* if */

	if (_ggi_physz_parse_option(options[OPT_PHYSZ].result,
			     &(priv->physzflags), &(priv->physz)))
	{
		free(priv);
		free(LIBGGI_GC(vis));
		return GGI_EARGINVAL;   
        }	/* if */

	if (!options[OPT_SOCKET].result[0]
	   && !options[OPT_SEMID].result[0]
	   && !options[OPT_SHMID].result[0])
	{
		DPRINT("display-ipc: required arguments missing\n");
		return GGI_EARGREQ;
	}	/* if */

	if (!(sscanf(options[OPT_SOCKET].result,"%s", address.sun_path)
	   && sscanf(options[OPT_SEMID].result,"%d", &(priv->semid))
	   && sscanf(options[OPT_SHMID].result,"%d", &(priv->shmid))))
	{
		DPRINT("display-ipc: argument format error\n");
		return GGI_EARGREQ;
	}	/* if */

	DPRINT("display-ipc parsed args: socket: %s semid: %d shmid: %d\n",
		   address.sun_path, priv->semid, priv->shmid);
	address.sun_family = AF_UNIX;
	if ((priv->sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1
	   || connect(priv->sockfd, (const struct sockaddr *)(&address),
		sizeof(struct sockaddr_un)) == -1
	   || (priv->memptr = (char *)shmat(priv->shmid, 0, 0)) == (char *)-1)
	{
		DPRINT("display-ipc initialization failed : %s\n", strerror(errno));
		return GGI_ENODEVICE;
	}	/* if */

	if (options[OPT_INPUT].result[0]) {
		priv->inputbuffer=priv->memptr;
		priv->memptr=(char *)priv->memptr+INPBUFSIZE;
		DPRINT("display-ipc: moved mem to %p for input-buffer.\n",
			priv->memptr);
	}	/* if */

	vis->opdisplay->flush     = GGI_ipc_flush;
	vis->opdisplay->getmode   = GGI_ipc_getmode;
	vis->opdisplay->setmode   = GGI_ipc_setmode;
	vis->opdisplay->getapi    = GGI_ipc_getapi;
	vis->opdisplay->checkmode = GGI_ipc_checkmode;
	vis->opdisplay->setflags  = GGI_ipc_setflags;
  
	if (priv->inputbuffer) {
		gii_input *inp;
      
		priv->inputbuffer->visx		=
		priv->inputbuffer->visy		=
		priv->inputbuffer->virtx	=
		priv->inputbuffer->virty	=
		priv->inputbuffer->frames	=
		priv->inputbuffer->visframe	= 0;

		DPRINT_MISC("Adding gii to shmem-memtarget\n");

		/* First allocate a new gii_input descriptor. */

		if (NULL==(inp=_giiInputAlloc())) {
			DPRINT_MISC("giiInputAlloc failure.\n");
			goto out;
		}	/* if */
		DPRINT_MISC("gii inp=%p\n",inp);

		/* Now fill in the blanks. */
      
		inp->priv = priv;	/* We need that in poll() */
		priv->inputbuffer->writeoffset = 0;	/* Not too good, but ... */

		inp->targetcan= emAll;
		inp->GIIseteventmask(inp,inp->targetcan);
		inp->maxfd = 0;		/* This is polled. */
		inp->flags |= GII_FLAGS_HASPOLLED;
      
		inp->GIIeventpoll = GII_ipc_poll;
		inp->GIIsendevent = GII_ipc_send;
      
		/* Now join the new event source in. */
		vis->input=giiJoinInputs(vis->input,inp);
  out:
		while(0){};
	}	/* if */
  
	*dlret = GGI_DL_OPDISPLAY;
	return 0;

}	/* GGIopen */
Ejemplo n.º 4
0
static int GGIopen(ggi_visual *vis, struct ggi_dlhandle *dlh,
		   const char *args, void *argptr, uint32_t *dlret)
{
	struct TIhooks *priv;
	gg_option options[NUM_OPTS];
	char *term_type;
	char *term_path;
	int i, err;

        memcpy(options, optlist, sizeof(options));
	if (args != NULL) {
		args = ggParseOptions(args, options, NUM_OPTS);
		if (args == NULL) {
			fprintf(stderr, "display-x: error in arguments.\n");
			return GGI_EARGINVAL;
		}
        }
	term_path = options[OPT_PATH].result;
	term_type = options[OPT_TERM].result;
	if ((*term_type) == '\0') term_type = NULL;

	DPRINT("display-terminfo: initializing %s on %s.\n", term_type, ( ( *term_path == '\0' ) ? "stdin/stdout" : term_path ));

	priv = (struct TIhooks *)malloc(sizeof(struct TIhooks));
	if (priv == NULL) return GGI_ENOMEM;
	LIBGGI_PRIVATE(vis) = priv;

	err = _ggi_physz_parse_option(options[OPT_PHYSZ].result, 
			       &(priv->physzflags), &(priv->physz)); 
	if (err != GGI_OK) {
	  free(priv);
	  return err;
	}

	LIBGGI_GC(vis) = malloc(sizeof(ggi_gc));
	if (LIBGGI_GC(vis) == NULL) {
		free(priv);
		return GGI_ENOMEM;
	}

	priv->splitline = 0;

	priv->virgin = 1;

	if ( *term_path == '\0' ) {
		priv->f_in = fdopen(dup(fileno(stdin)), "r");
		priv->f_out = fdopen(dup(fileno(stdout)), "w");
	} else {
		priv->f_in = priv->f_out = fopen(term_path, "rw");
	}

	_terminfo_init_ncurses();

	priv->scr = _terminfo_new_screen(term_type, priv->f_out, priv->f_in);
	if (priv->scr == NULL) {
		fprintf(stderr, "display-terminfo: error creating ncurses"
				" SCREEN\n");
		fclose(priv->f_in);
		fclose(priv->f_out);
		free(LIBGGI_GC(vis));
		free(priv);
		return GGI_ENODEVICE;
	}

	LIBGGI_FD(vis) = fileno(priv->f_out);

	if ( has_colors() ) {
		static const int vga_color[8] = {
			COLOR_BLACK,
			COLOR_BLUE,
			COLOR_GREEN,
			COLOR_CYAN,
			COLOR_RED,
			COLOR_MAGENTA,
			COLOR_YELLOW,
			COLOR_WHITE
		};
		int j;
		DPRINT("display-terminfo: terminal supports %d colors\n", COLORS);
		DPRINT("display-terminfo: initializing %d - 1 color pairs\n", COLOR_PAIRS);
		for ( i = 1 ; i < COLOR_PAIRS ; i++ ) {
			if ( init_pair(i, COLORS - ( i % COLORS ) - 1, i / COLORS) == ERR ) {
				DPRINT("display-terminfo: error initializing color pair %d to %d,%d\n", i, COLORS - ( i % COLORS ) - 1, i / COLORS);
				fprintf(stderr, "display-terminfo: error initializing colors\n");
				break;
			}
		}
		for ( i = 0 ; i < 16 ; i++ ) {
			for ( j = 0 ; j < 16 ; j++ ) {
				priv->color16_table[i+(j<<4)] =
					COLOR_PAIR(((COLORS-vga_color[i&0x07]%COLORS-1)
					 +(vga_color[j&0x07]%COLORS*COLORS))%COLOR_PAIRS)
					| ( ( i > 7 ) ? A_BOLD : A_NORMAL )
					| ( ( j > 7 ) ? A_BLINK : A_NORMAL );
			}
		}

	} else {
		DPRINT("display-terminfo: terminal lacks color support\n");
	}
	construct_charmap(priv->charmap);
#if ( NCURSES_MOUSE_VERSION == 1 ) 
	DPRINT("display-terminfo: mouse support is enabled\n");
	mousemask(REPORT_MOUSE_POSITION | BUTTON1_PRESSED | BUTTON1_RELEASED |
			BUTTON2_PRESSED | BUTTON2_RELEASED | BUTTON3_PRESSED |
			BUTTON3_RELEASED | BUTTON4_PRESSED | BUTTON4_RELEASED,
			NULL);
#else
	DPRINT("display-terminfo: mouse support is disabled\n");
#endif

	/* mode management */
	vis->opdisplay->flush     = GGI_terminfo_flush;
	vis->opdisplay->getmode   = GGI_terminfo_getmode;
	vis->opdisplay->setmode   = GGI_terminfo_setmode;
	vis->opdisplay->checkmode = GGI_terminfo_checkmode;
	vis->opdisplay->getapi    = GGI_terminfo_getapi;
	vis->opdisplay->setflags  = GGI_terminfo_setflags;

	/* event management */
	{
		gii_input *inp;
		inp = _giiInputAlloc();

		if (inp == NULL) {
			fprintf(stderr, "display-terminfo: error allocating gii_input\n");
			_terminfo_destroy_screen();
			fclose(priv->f_in);
			fclose(priv->f_out);
			free(LIBGGI_GC(vis));
			free(priv);
			return GGI_ENOMEM;
		}

#if ( NCURSES_MOUSE_VERSION == 1 )
		inp->targetcan =emKey | emPtrButton | emPtrAbsolute,
#else
		inp->targetcan =emKey, /* without mouse support */
#endif
		inp->GIIseteventmask(inp,inp->targetcan);

		inp->GIIeventpoll = GII_terminfo_eventpoll;
		inp->GIIsendevent = GII_terminfo_sendevent;

		priv->vis = vis;
		inp->priv = (void *)priv;

		inp->maxfd=0;   /* This is polled. */
		inp->flags|=GII_FLAGS_HASPOLLED;

		vis->input = giiJoinInputs(vis->input, inp);
	}

	_terminfo_release_screen();
 
	*dlret = GGI_DL_OPDISPLAY;
	return 0;
}
Ejemplo n.º 5
0
static int GGIopen(struct ggi_visual *vis, struct ggi_dlhandle *dlh,
			const char *args, void *argptr, uint32_t *dlret)
{
	ggi_memory_priv *priv;
	gg_option options[NUM_OPTS];
	int err = 0;

	DPRINT_MISC("GGIopen: coming up.\n");
	memcpy(options, optlist, sizeof(options));

	LIBGGI_GC(vis) = malloc(sizeof(ggi_gc));
	if (!LIBGGI_GC(vis)) return GGI_ENOMEM;

	/* Allocate descriptor for screen memory */
	priv = calloc(1, sizeof(ggi_memory_priv));
	if (!priv) {
		err = GGI_ENOMEM;
		goto err0;
	}
	LIBGGI_PRIVATE(vis) = priv;

	priv->inp = NULL;
	priv->memtype = MT_MALLOC;	/* Default to mallocing. */
	priv->inputbuffer = NULL;	/* Default to no input */

	if (args) {
		args = ggParseOptions(args, options, NUM_OPTS);
		if (args == NULL) {
			fprintf(stderr, "display-memory: error in "
				"arguments.\n");
		}
	}

	if (_ggi_physz_parse_option(options[OPT_PHYSZ].result, 
			     &(priv->physzflags), &(priv->physz)))
	{ 
		err = GGI_EARGINVAL;
		goto err1;
	}

	if (args && *args) {	/* We have parameters. Analyze them. */
		DPRINT("has args: \"%s\"\n", args);
#ifdef _GG_HAVE_SHM
		if (strncmp(args, "shmid:", 6) == 0) {
			sscanf(args + 6, "%i", &(priv->shmid));
			DPRINT("has shmid-arg: %d.\n", priv->shmid);
			priv->memptr = shmat(priv->shmid, NULL, 0);
			DPRINT("shmat at %p.\n", priv->memptr);
			if (priv->memptr != (void *)-1) {
				priv->memtype = MT_SHMID;
				if (options[OPT_INPUT].result[0]) {
					priv->inputbuffer = priv->memptr;
					priv->memptr = (char *)priv->memptr
							+ INPBUFSIZE;
					DPRINT("moved mem to %p for input-buffer.\n",
						priv->memptr);
				} 
			}
		} else if (strncmp(args, "keyfile:", 8) == 0) {
			unsigned int size;
			char id;
			char filename[1024];

			sscanf(args + 8, "%u:%c:%s", &size, &id, filename);
			DPRINT("has keyfile-arg:%d:%c:%s.\n",
				size, id, filename);

			priv->shmid = shmget(ftok(filename,id), size,
						IPC_CREAT|0666);
			DPRINT("has shmid:%d.\n", priv->shmid);

			priv->memptr = shmat(priv->shmid,NULL,0);
			DPRINT("shmat at %p.\n", priv->memptr);
			if (priv->memptr != (void *)-1) {
				priv->memtype = MT_SHMID;
				if (options[OPT_INPUT].result[0]) {
					priv->inputbuffer = priv->memptr;
					priv->memptr = (char *)priv->memptr
							+ INPBUFSIZE;
					DPRINT("moved mem to %p for input-buffer.\n",
						priv->memptr);
				}
			}
		} else
#endif /* _GG_HAVE_SHM */
		if (strncmp(args, "pointer", 7) == 0) {
			priv->memptr = argptr;
			if (priv->memptr) {
				priv->memtype = MT_EXTERN;
			}
		}
	}

	/* Explicit pixelformat. */
	if (options[OPT_PIXFMT].result[0]) {
		_ggi_parse_pixfmtstr(options[OPT_PIXFMT].result, '\0', NULL,
				strlen(options[OPT_PIXFMT].result)+1,
				&priv->r_mask, &priv->g_mask, &priv->b_mask,
				&priv->a_mask, &priv->pixfmt_flags);
	}

	/* Explicit layout for preallocated buffers with nontrivial layouts. */
	if (options[OPT_LAYOUT].result[0] != 'n') {
		char *idx;
		priv->fstride = strtoul(options[OPT_LAYOUT].result, &idx, 10);
		if (strncmp(idx, "plb", 3) == 0) {
			priv->layout = blPixelLinearBuffer;
			idx += 3;
			priv->buffer.plb.stride = strtoul(idx, NULL, 10);
		} else if (strncmp(idx, "plan", 4) == 0) {
			priv->layout = blPixelPlanarBuffer;
			idx += 4;
			priv->buffer.plan.next_plane = strtoul(idx, &idx, 10);
			if (*idx != ',') {
				priv->buffer.plan.next_line = 0;
			} else {
				idx++;
				priv->buffer.plan.next_line = 
				  strtoul(idx, &idx, 10);
			}
		} else { 
			if (*idx != '\0') 
				fprintf(stderr, "bad layout params\n");
			priv->layout = blPixelLinearBuffer;
			priv->buffer.plb.stride = 0;
		}
	}

	/* Do not blank the framebuffer on SetMode.
	 * (Preserves data in prealloced memory area.) 
	 */
	priv->noblank = (options[OPT_NOBLANK].result[0] != 'n');

	vis->opdisplay->flush = GGI_memory_flush; 
	vis->opdisplay->getmode = GGI_memory_getmode;
	vis->opdisplay->setmode = GGI_memory_setmode;
	vis->opdisplay->getapi = GGI_memory_getapi;
	vis->opdisplay->checkmode = GGI_memory_checkmode;
	vis->opdisplay->setflags = GGI_memory_setflags;

	if (priv->inputbuffer) {
		struct gg_api *gii;

#if 0
		priv->inputbuffer->visx =
		priv->inputbuffer->visy =
		priv->inputbuffer->virtx =
		priv->inputbuffer->virty =
		priv->inputbuffer->frames =
		priv->inputbuffer->visframe = 0;
#endif

		DPRINT_MISC("Adding gii to shmem-memtarget\n");
		gii = ggGetAPIByName("gii");
		if (gii != NULL && STEM_HAS_API(vis->instance.stem, gii)) {
			char inputstr[1024];

			snprintf(inputstr, sizeof(inputstr),
				"-size=%i:-pointer", INPBUFSIZE);
			DPRINT("\"input-memory\" inputstr \"%s\" at %p\n",
				inputstr, priv->inputbuffer->buffer);
			priv->inp = ggPlugModule(gii, vis->instance.stem,
						"input-memory", inputstr,
						priv->inputbuffer->buffer);
			DPRINT("ggPlugModule for input-memory returned %p\n",
				priv->inp);

			if (priv->inp == NULL) {
				fprintf(stderr,
					"display-memory: unable to open input-memory\n");
				err = GGI_ENODEVICE;
				goto err1;
			}
		}
	}
	
	*dlret = GGI_DL_OPDISPLAY;
	return 0;

err1:
	free(priv);
err0:
	free(LIBGGI_GC(vis));

	*dlret = GGI_DL_OPDISPLAY;
	return err;
}