void _terminfo_finalize_ncurses(void) { ggLock(ncurses_lock); if (!(--count)) { ggUnlock(ncurses_lock); ggLockDestroy(ncurses_lock); } else { ggUnlock(ncurses_lock); } }
static int GGI_X_flush_draw(struct ggi_visual *vis, int x, int y, int w, int h, int tryflag) { ggi_x_priv *priv; priv = GGIX_PRIV(vis); if (tryflag == 0) { /* flush later, this is in signal handler context * when using the signal based scheduler */ ggUnlock(priv->flushlock); return 0; } if (tryflag != 2) GGI_X_LOCK_XLIB(vis); _ggi_x_flush_cmap(vis); /* Update the palette/gamma */ /* Flush any pending Xlib operations. */ XFlush(priv->disp); if (tryflag != 2) { GGI_X_UNLOCK_XLIB(vis); } return 0; }
SCREEN *_terminfo_new_screen(const char *term_type, FILE *out, FILE *in) { SCREEN *_newscr; ggLock(ncurses_lock); if ( term_type == NULL ) { term_type = getenv("TERM"); if ( term_type == NULL ) { term_type = "vt100"; } } { char *temp; temp = (char *)malloc(sizeof(char) * ( strlen(term_type) + 1 )); strcpy(temp, term_type); _newscr = newterm(temp, out, in); free(temp); } if ( _newscr == NULL ) { ggUnlock(ncurses_lock); } else { ncurses_screen = _newscr; set_term(_newscr); start_color(); cbreak(); noecho(); nonl(); timeout(0); meta(stdscr, TRUE); keypad(stdscr, TRUE); } return _newscr; }
int GGI_palemu_flush(struct ggi_visual *vis, int x, int y, int w, int h, int tryflag) { ggi_palemu_priv *priv = PALEMU_PRIV(vis); int err; MANSYNC_ignore(vis); ggLock(priv->flush_lock); if (priv->target == PALEMU_TARGET) { err = _ggi_palemu_Flush(vis); } else { err = _ggi_monotext_Flush(vis); } if (! err) { err = _ggiInternFlush(GGI_VISUAL(priv->parent), x, y, w, h, tryflag); } ggUnlock(priv->flush_lock); MANSYNC_cont(vis); return err; }
void _terminfo_destroy_screen(void) { endwin(); delscreen(ncurses_screen); ncurses_screen = NULL; ggUnlock(ncurses_lock); }
static int do_cleanup(struct ggi_visual *vis) { ggi_libkgi_priv *priv = LIBKGI_PRIV(vis); /* We may be called more than once due to the LibGG cleanup stuff */ if (priv == NULL) return 0; DPRINT("display-libkgi: GGIdlcleanup start.\n"); if (LIBGGI_FD(vis) >= 0) close(LIBGGI_FD(vis)); if (vis->input != NULL) { giiClose(vis->input); vis->input = NULL; } free(priv); LIBKGI_PRIV(vis) = NULL; ggUnregisterCleanup((ggcleanup_func *)do_cleanup, vis); ggLock(_ggi_global_lock); refcount--; refcount--; if (refcount == 0) { ggLockDestroy(_ggi_libkgi_lock); _ggi_libkgi_lock = NULL; } ggUnlock(_ggi_global_lock); DPRINT("display-libkgi: GGIdlcleanup done.\n"); return 0; }
static void testcase1(const char *desc) { void *lock; int result; printteststart(__FILE__, __PRETTY_FUNCTION__, EXPECTED2PASS, desc); if (dontrun) return; lock = ggLockCreate(); if(lock == NULL) { printfailure("Failed to create lock."); return; } ggLock(lock); result = ggTryLock(lock); if(result == 0) { printfailure("Lock should have been locked already."); return; } printassert(result == GGI_EBUSY, "Lock not busy. result: %i\n", result); ggUnlock(lock); result = ggTryLock(lock); printassert(result != GGI_EBUSY, "Lock shouldn't be busy. result: %i\n", result); if (result != 0) { printfailure("Locking failed.\n" "expected result: 0\n" "actual result: %i\n", result); return; } ggUnlock(lock); result = ggLockDestroy(lock); if(result != 0) { printfailure("Failed to destroy lock."); return; } printsuccess(); return; }
void _terminfo_init_ncurses(void) { if (!(count++)) { /* FIXME !!! race condition */ ncurses_lock = ggLockCreate(); ggLock(ncurses_lock); ncurses_screen = NULL; ggUnlock(ncurses_lock); } else { ggLock(ncurses_lock); } }
int GGI_trueemu_flush(struct ggi_visual *vis, int x, int y, int w, int h, int tryflag) { ggi_trueemu_priv *priv = TRUEEMU_PRIV(vis); int err; MANSYNC_ignore(vis); ggLock(priv->flush_lock); err = _ggi_trueemu_Flush(vis); if (! err) { err = _ggiInternFlush(GGI_VISUAL(priv->parent), x, y, w, h, tryflag); } ggUnlock(priv->flush_lock); MANSYNC_cont(vis); return err; }
int GGI_X_flush_ximage_child(struct ggi_visual *vis, int x, int y, int w, int h, int tryflag) { ggi_x_priv *priv; int mansync; priv = GGIX_PRIV(vis); if (tryflag == 0) { /* flush later, this is in signal handler context * when using the signal based scheduler */ ggUnlock(priv->flushlock); return 0; } if (priv->opmansync) MANSYNC_ignore(vis); mansync = 1; /* Do we call MANSYNC_cont later? By default, yes. */ if (tryflag != 2) GGI_X_LOCK_XLIB(vis); _ggi_x_flush_cmap(vis); /* Update the palette/gamma */ /* Flush any pending Xlib operations. */ XSync(priv->disp, 0); if (priv->fullflush || (GGI_ACTYPE_WRITE & vis->w_frame->resource->curactype)) { /* Flush all requested data */ if (tryflag != 2) { GGI_X_CLEAN(vis, x, y, w, h); y = GGI_X_WRITE_Y; } /* else it's a non-translated exposure event. */ XPutImage(priv->disp, priv->drawable, priv->tempgc, priv->ximage, x, y, x, y, (unsigned)w, (unsigned)h); if (LIBGGI_FLAGS(vis) & GGIFLAG_TIDYBUF) mansync = 0; } else { /* Just flush the intersection with the dirty region */ int x2, y2; if (priv->dirtytl.x > priv->dirtybr.x) goto clean; if (x > priv->dirtybr.x) goto clean; if (y > priv->dirtybr.y) goto clean; x2 = x + w - 1; if (x2 < priv->dirtytl.x) goto clean; y2 = y + h - 1; if (y2 < priv->dirtytl.y) goto clean; if (x < priv->dirtytl.x) x = priv->dirtytl.x; if (y < priv->dirtytl.y) y = priv->dirtytl.y; if (x2 > priv->dirtybr.x) x2 = priv->dirtybr.x; if (y2 > priv->dirtybr.y) y2 = priv->dirtybr.y; w = x2 - x + 1; h = y2 - y + 1; if ((w <= 0) || (h <= 0)) goto clean; XPutImage(priv->disp, priv->drawable, priv->tempgc, priv->ximage, x, GGI_X_WRITE_Y, x, GGI_X_WRITE_Y, (unsigned)w, (unsigned)h); GGI_X_CLEAN(vis, x, y, w, h); } /* Tell X Server to start blitting */ XFlush(priv->disp); clean: if (tryflag != 2) GGI_X_UNLOCK_XLIB(vis); if (priv->opmansync && mansync) MANSYNC_cont(vis); return 0; }
void _terminfo_release_screen(void) { ggUnlock(ncurses_lock); }
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; }
static int _ggi_xshm_create_ximage(struct ggi_visual *vis) { char target[GGI_MAX_APILEN]; ggi_mode tm; ggi_x_priv *priv; int err, i; XShmSegmentInfo *myshminfo; size_t shmsize; err = GGI_OK; priv = GGIX_PRIV(vis); DPRINT_MODE("X: MIT-SHM: Creating shared MIT-SHM buffer\n"); _ggi_xshm_free_ximage(vis); priv->priv = calloc(1, sizeof(XShmSegmentInfo)); if (!priv->priv) return GGI_ENOMEM; myshminfo = priv->priv; priv->ximage = XShmCreateImage(priv->disp, priv->vilist[priv->viidx].vi->visual, (unsigned)priv->vilist[priv->viidx].vi->depth, ZPixmap, /* format */ NULL, /* data */ myshminfo, /* shm object */ (unsigned)LIBGGI_VIRTX(vis), (unsigned)(LIBGGI_VIRTY(vis) * LIBGGI_MODE(vis)->frames)); if (priv->ximage == NULL) { DPRINT("XShmCreateImage() failed."); err = GGI_ENOMEM; goto err0; } shmsize = priv->ximage->bytes_per_line * LIBGGI_VIRTY(vis) * LIBGGI_MODE(vis)->frames; DPRINT_MODE("X: MIT-SHM: Try to shmget() a buffer of %lu (0x%lx) size bytes\n", shmsize, shmsize); myshminfo->shmid = shmget(IPC_PRIVATE, shmsize, IPC_CREAT | 0777); if (myshminfo->shmid == -1) { DPRINT("shmget() failed.\n"); priv->fb = NULL; err = GGI_ENOMEM; goto err1; } priv->fb = shmat(myshminfo->shmid,0,0); if (priv->fb == (void *)-1) { DPRINT("shmat() failed.\n"); priv->fb = NULL; err = GGI_ENOMEM; goto err1; } myshminfo->shmaddr = priv->ximage->data = (char *)priv->fb; DPRINT_MODE("X: MIT-SHM: shmat success at %p.\n", priv->fb); myshminfo->readOnly = False; ggLock(_ggi_global_lock); /* Entering protected section */ shmerror = 0; DPRINT_MODE("X: MIT-SHM: install error handler\n"); oldshmerrorhandler = XSetErrorHandler(shmerrorhandler); DPRINT_MODE("X: MIT-SHM: Attach shm to display\n"); XShmAttach(priv->disp, myshminfo); XSync(priv->disp, 0); DPRINT_MODE("X: MIT-SHM: restore error handler\n"); XSetErrorHandler(oldshmerrorhandler); if (shmerror) { ggUnlock(_ggi_global_lock); /* Exiting protected section */ DPRINT("can not access XSHM.\n"); err = GGI_ENOMEM; goto err2; } else { /* Take the shmid away so noone else can get it. */ shmctl(myshminfo->shmid, IPC_RMID, 0); DPRINT_MODE("X: MIT-SHM: ShmImage allocated\n"); } ggUnlock(_ggi_global_lock); /* Exiting protected section */ err = _ggi_create_dbs(vis); if (err) goto err3; /* We assume LIBGGI_MODE(vis) structure has already been filled out */ memcpy(&tm, LIBGGI_MODE(vis), sizeof(ggi_mode)); /* Make sure we do not fail due to physical size constraints, * which are meaningless on a memory visual. */ tm.size.x = tm.size.y = GGI_AUTO; i = 0; memset(target, '\0', sizeof(target)); i += snprintf(target, sizeof(target), "display-memory:-pixfmt="); _ggi_build_pixfmtstr(vis, target + i, sizeof(target) - i, 1); i = strlen(target); snprintf(target + i, sizeof(target) - i, ":-layout=%iplb%i:-physz=%i,%i:pointer", priv->ximage->bytes_per_line * LIBGGI_VIRTY(vis), priv->ximage->bytes_per_line, LIBGGI_MODE(vis)->size.x, LIBGGI_MODE(vis)->size.y); err = _ggi_openslave(vis, target, &tm); if (err) goto err3; priv->ximage->byte_order = ImageByteOrder(priv->disp); priv->ximage->bitmap_bit_order = BitmapBitOrder(priv->disp); vis->opdisplay->flush = GGI_XSHM_flush_ximage_child; DPRINT_MODE("X: MIT-SHM: XSHMImage and slave visual %p share buffer at %p\n", priv->slave, priv->fb); return GGI_OK; err3: fprintf(stderr, "XSHM extension failed to initialize. Retry with -noshm\n"); _ggi_xshm_free_ximage(vis); return err; err2: XShmDetach(priv->disp, myshminfo); shmdt(priv->fb); priv->fb = NULL; err1: XDestroyImage(priv->ximage); priv->ximage = NULL; err0: fprintf(stderr, "XSHM extension failed to initialize. Retry with -noshm\n"); return err; }
int GGI_X_getvline_draw(ggi_visual *vis, int x, int y, int h, void *data) { ggi_x_priv *priv; XImage *ximg; int (*olderrorhandler) (Display *, XErrorEvent *); int ret = 0; uint8_t *data8; priv = GGIX_PRIV(vis); GGI_X_LOCK_XLIB(vis); XSync(priv->disp, 0); ggLock(_ggi_global_lock); geterror = 0; olderrorhandler = XSetErrorHandler(errorhandler); /* This will cause a BadMatch error when the window is iconified or on another virtual screen... */ ximg = XGetImage(priv->disp, priv->drawable, x, GGI_X_READ_Y, 1, (unsigned)h, AllPlanes, ZPixmap); XSync(priv->disp,0); XSetErrorHandler(olderrorhandler); #warning honor various ximage format fields here. #warning 1,2,4-bit support needed if (geterror) { ret = -1; goto out; } if (ximg->byte_order == #ifdef GGI_LITTLE_ENDIAN LSBFirst #else MSBFirst #endif ) goto noswab; if (ximg->bits_per_pixel == 16) { uint8_t *ximgptr; data8 = (uint8_t *)data; ximgptr = (uint8_t *)(ximg->data) + ximg->xoffset * 2; while (h--) { *(data8) = *(ximgptr + 1); *(data8 + 1) = *(ximgptr); ximgptr += ximg->bytes_per_line; data8 += 2; } } else if (ximg->bits_per_pixel == 32) { uint8_t *ximgptr; data8 = (uint8_t *)data; ximgptr = (uint8_t *)(ximg->data) + ximg->xoffset * 4; while (h--) { *(data8) = *(ximgptr + 3); *(data8 + 1) = *(ximgptr + 2); *(data8 + 2) = *(ximgptr + 1); *(data8 + 3) = *(ximgptr); ximgptr += ximg->bytes_per_line; data8 += 4; } } else { uint8_t *ximgptr; noswab: ximgptr = (uint8_t *)(ximg->data) + (ximg->xoffset * ximg->bits_per_pixel)/8; data8 = (uint8_t *)data; while (h--) { memcpy(data8, ximgptr, (unsigned)ximg->bits_per_pixel/8); ximgptr += ximg->bytes_per_line; data8 += ximg->bits_per_pixel/8; } } XDestroyImage(ximg); out: ggUnlock(_ggi_global_lock); GGI_X_UNLOCK_XLIB(vis); return ret; }