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; }
int GGI_X_drawvline_draw(ggi_visual *vis, int x, int y, int h) { ggi_x_priv *priv; priv = GGIX_PRIV(vis); y = GGI_X_WRITE_Y; GGI_X_LOCK_XLIB(vis); XDrawLine(priv->disp, priv->drawable, priv->gc, x, y, x, y+h-1); GGI_X_MAYBE_SYNC(vis); GGI_X_UNLOCK_XLIB(vis); return 0; }
int GGI_X_drawvline_slave_draw(ggi_visual *vis, int x, int y, int h) { ggi_x_priv *priv; priv = GGIX_PRIV(vis); LIBGGICLIP_XYH(vis, x, y, h); GGI_X_CLEAN(vis, x, y, 1, h); priv->slave->opdraw->drawvline_nc(priv->slave, x, y, h); y = GGI_X_WRITE_Y; GGI_X_LOCK_XLIB(vis); XDrawLine(priv->disp, priv->drawable, priv->gc, x, y, x, y+h-1); GGI_X_MAYBE_SYNC(vis); GGI_X_UNLOCK_XLIB(vis); return 0; }
int GGI_X_fillscreen_draw(ggi_visual *vis) { ggi_x_priv *priv; XGCValues gcValue; GC gc; priv = GGIX_PRIV(vis); DPRINT("X_fillscreen_draw enter!\n"); GGI_X_LOCK_XLIB(vis); /* XXX: What is priv->gc ? is it appropriate to use that here? */ gcValue.foreground = LIBGGI_GC(vis)->fg_color; gcValue.background = LIBGGI_GC(vis)->fg_color; gcValue.function = GXcopy; gc = XCreateGC( priv->disp, priv->drawable, GCForeground | GCBackground | GCFunction, &gcValue); if (LIBGGI_GC(vis)->cliptl.x > 0 || LIBGGI_GC(vis)->cliptl.y > 0 || LIBGGI_GC(vis)->clipbr.x < LIBGGI_VIRTX(vis) || LIBGGI_GC(vis)->clipbr.y < LIBGGI_VIRTY(vis)) { int y; /* Note: GGI_X_WRITE_Y is a macro that makes use * of the value stored in y. */ y = LIBGGI_GC(vis)->cliptl.y; y = GGI_X_WRITE_Y; /* CLIPSIZE macro is defined above in * GGI_X_fillscreen_slave_draw() */ XFillRectangle(priv->disp, priv->drawable, gc, LIBGGI_GC(vis)->cliptl.x, y, CLIPSIZE(x), CLIPSIZE(y) ); } else { XFillRectangle(priv->disp, priv->drawable, gc, 0, 0, LIBGGI_VIRTX(vis), LIBGGI_VIRTY(vis) ); } GGI_X_MAYBE_SYNC(vis); GGI_X_UNLOCK_XLIB(vis); DPRINT_LIBS("X_fillscreen_draw exit!\n"); return 0; }
int GGI_X_putvline_draw(ggi_visual *vis, int x, int y, int h, const void *data) { XImage *ximg; ggi_x_priv *priv; priv = GGIX_PRIV(vis); GGI_X_LOCK_XLIB(vis); #warning 1,2,4-bit support needed. ximg = _ggi_x_create_ximage( vis, (char*)data, 1, h); if (ximg == NULL) return GGI_ENOMEM; XPutImage(priv->disp, priv->drawable, priv->gc, ximg, 0, 0, x, GGI_X_WRITE_Y, 1, (unsigned)h); #ifndef HAVE_XINITIMAGE XFree(ximg); #else free(ximg); #endif GGI_X_MAYBE_SYNC(vis); GGI_X_UNLOCK_XLIB(vis); return 0; }
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; }
int GGI_X_fillscreen_slave_draw(ggi_visual *vis) { ggi_x_priv *priv; XGCValues gcValue; GC gc; priv = GGIX_PRIV(vis); DPRINT("X_fillscreen_slave_draw enter!\n"); GGI_X_LOCK_XLIB(vis); /* XXX: What is priv->gc ? is it appropriate to use that here? */ gcValue.foreground = LIBGGI_GC(vis)->fg_color; gcValue.background = LIBGGI_GC(vis)->fg_color; gcValue.function = GXcopy; gc = XCreateGC( priv->disp, priv->drawable, GCForeground | GCBackground | GCFunction, &gcValue); if (LIBGGI_GC(vis)->cliptl.x > 0 || LIBGGI_GC(vis)->cliptl.y > 0 || LIBGGI_GC(vis)->clipbr.x < LIBGGI_VIRTX(vis) || LIBGGI_GC(vis)->clipbr.y < LIBGGI_VIRTY(vis)) { int y; DPRINT("X_fillscreen_slave_draw small clip!\n"); GGI_X_CLEAN(vis, LIBGGI_GC(vis)->cliptl.x, LIBGGI_GC(vis)->cliptl.y, LIBGGI_GC(vis)->clipbr.x-LIBGGI_GC(vis)->cliptl.x, LIBGGI_GC(vis)->clipbr.y-LIBGGI_GC(vis)->cliptl.y); DPRINT("X_fillscreen_slave_draw calling opdraw->fillscreen\n"); priv->slave->opdraw->fillscreen(priv->slave); /* What is this? y is set twice? which value is * proper? Answer: GGI_X_WRITE_Y is a macro that makes * use of the value stored in y. */ y = LIBGGI_GC(vis)->cliptl.y; y = GGI_X_WRITE_Y; #define CLIPSIZE(xy) \ (unsigned)LIBGGI_GC(vis)->clipbr.xy-LIBGGI_GC(vis)->cliptl.xy XFillRectangle(priv->disp, priv->drawable, gc, LIBGGI_GC(vis)->cliptl.x, y, CLIPSIZE(x), CLIPSIZE(y) ); } else { DPRINT("X_fillscreen_slave_draw large clip!\n"); GGI_X_CLEAN(vis, 0, 0, LIBGGI_VIRTX(vis), LIBGGI_VIRTY(vis)); DPRINT("X_fillscreen_slave_draw calling opdraw->fillscreen\n"); priv->slave->opdraw->fillscreen(priv->slave); XFillRectangle(priv->disp, priv->drawable, gc, 0, 0, LIBGGI_VIRTX(vis), LIBGGI_VIRTY(vis) ); } GGI_X_MAYBE_SYNC(vis); XFreeGC(priv->disp, gc); GGI_X_UNLOCK_XLIB(vis); return GGI_OK; }
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; }