/** Load the font, \a pFont, on the back-end server associated with \a * pScreen. When a font is loaded, the font path on back-end server is * first initialized to that specified on the command line with the * -fontpath options, and then the font is loaded. */ Bool dmxBELoadFont(ScreenPtr pScreen, FontPtr pFont) { DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; dmxFontPrivPtr pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex); const char *name; char **oldFontPath = NULL; int nOldPaths; Atom name_atom, value_atom; int i; /* Make sure we have a font private struct to work with */ if (!pFontPriv) return FALSE; /* Don't load a font over top of itself */ if (pFontPriv->font[pScreen->myNum]) { return TRUE; /* Already loaded font */ } /* Save old font path */ oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths); /* Set the font path for the font about to be loaded on the back-end */ if (dmxSetFontPath(dmxScreen)) { char **fp; int npaths; Bool *goodfps; /* This could fail only when first starting the X server and * loading the default font. If it fails here, then the default * font path is invalid, no default font path will be set, the * DMX server will fail to load the default font, and it will * exit with an error unless we remove the offending font paths * with the -ignorebadfontpaths command line option. */ fp = dmxGetFontPath(&npaths); if (!fp) { dmxLog(dmxError, "No default font path set.\n"); dmxLog(dmxError, "Please see the Xdmx man page for information on how to\n"); dmxLog(dmxError, "initialize the DMX server's default font path.\n"); XFreeFontPath(oldFontPath); return FALSE; } if (!dmxFontPath) dmxLog(dmxWarning, "No default font path is set.\n"); goodfps = xallocarray(npaths, sizeof(*goodfps)); dmxLog(dmxError, "The DMX server failed to set the following font paths on " "screen #%d:\n", pScreen->myNum); for (i = 0; i < npaths; i++) if (!(goodfps[i] = dmxCheckFontPathElement(dmxScreen, fp[i]))) dmxLog(dmxError, " %s\n", fp[i]); if (dmxIgnoreBadFontPaths) { char *newfp; int newnpaths = 0; int len = 0; int j = 0; dmxLog(dmxError, "These font paths will not be used because the " "\"-ignorebadfontpaths\"\n"); dmxLog(dmxError, "option is set.\n"); for (i = 0; i < npaths; i++) if (goodfps[i]) { len += strlen(fp[i]) + 1; newnpaths++; } if (!newnpaths) { /* No valid font paths were found */ dmxLog(dmxError, "After removing the font paths above, no valid font " "paths were\n"); dmxLog(dmxError, "available. Please check that the font paths set on " "the command\n"); dmxLog(dmxError, "line or in the configuration file via the " "\"-fontpath\" option\n"); dmxLog(dmxError, "are valid on all back-end servers. See the Xdmx man " "page for\n"); dmxLog(dmxError, "more information on font paths.\n"); dmxFreeFontPath(fp); XFreeFontPath(oldFontPath); free(goodfps); return FALSE; } newfp = xallocarray(len, sizeof(*newfp)); for (i = 0; i < npaths; i++) { if (goodfps[i]) { int n = strlen(fp[i]); newfp[j++] = n; strncpy(&newfp[j], fp[i], n); j += n; } } if (SetFontPath(serverClient, newnpaths, (unsigned char *) newfp)) { /* Note that this should never happen since all of the * FPEs were previously valid. */ dmxLog(dmxError, "Cannot reset the default font path.\n"); } } else if (dmxFontPath) { dmxLog(dmxError, "Please remove these font paths from the command line " "or\n"); dmxLog(dmxError, "configuration file, or set the \"-ignorebadfontpaths\" " "option to\n"); dmxLog(dmxError, "ignore them. For more information on these options, see " "the\n"); dmxLog(dmxError, "Xdmx man page.\n"); } else { dmxLog(dmxError, "Please specify the font paths that are available on all " "back-end\n"); dmxLog(dmxError, "servers with the \"-fontpath\" option, or use the " "\"-ignorebadfontpaths\"\n"); dmxLog(dmxError, "to ignore bad defaults. For more information on " "these and other\n"); dmxLog(dmxError, "font-path-related options, see the Xdmx man page.\n"); } free(goodfps); if (!dmxIgnoreBadFontPaths || (dmxIgnoreBadFontPaths && dmxSetFontPath(dmxScreen))) { /* We still have errors so return with error */ dmxFreeFontPath(fp); XFreeFontPath(oldFontPath); return FALSE; } } /* Find requested font on back-end server */ name_atom = MakeAtom("FONT", 4, TRUE); value_atom = 0L; for (i = 0; i < pFont->info.nprops; i++) { if ((Atom) pFont->info.props[i].name == name_atom) { value_atom = pFont->info.props[i].value; break; } } if (!value_atom) return FALSE; name = NameForAtom(value_atom); if (!name) return FALSE; pFontPriv->font[pScreen->myNum] = XLoadQueryFont(dmxScreen->beDisplay, name); /* Restore old font path */ XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths); XFreeFontPath(oldFontPath); dmxSync(dmxScreen, FALSE); if (!pFontPriv->font[pScreen->myNum]) return FALSE; return TRUE; }
/** Change the picture's list of clip rectangles. */ int dmxChangePictureClip(PicturePtr pPicture, int clipType, void *value, int n) { ScreenPtr pScreen = pPicture->pDrawable->pScreen; DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; PictureScreenPtr ps = GetPictureScreen(pScreen); dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); DMX_UNWRAP(ChangePictureClip, dmxScreen, ps); #if 1 if (ps->ChangePictureClip) ps->ChangePictureClip(pPicture, clipType, value, n); #endif /* Change picture clip rects on back-end server */ if (pPictPriv->pict) { /* The clip has already been changed into a region by the mi * routine called above. */ if (clipType == CT_NONE) { /* Disable clipping, show all */ XFixesSetPictureClipRegion(dmxScreen->beDisplay, pPictPriv->pict, 0, 0, None); } else if (pPicture->clientClip) { RegionPtr pClip = pPicture->clientClip; BoxPtr pBox = RegionRects(pClip); int nBox = RegionNumRects(pClip); XRectangle *pRects; XRectangle *pRect; int nRects; nRects = nBox; pRects = pRect = malloc(nRects * sizeof(*pRect)); while (nBox--) { pRect->x = pBox->x1; pRect->y = pBox->y1; pRect->width = pBox->x2 - pBox->x1; pRect->height = pBox->y2 - pBox->y1; pBox++; pRect++; } XRenderSetPictureClipRectangles(dmxScreen->beDisplay, pPictPriv->pict, 0, 0, pRects, nRects); free(pRects); } else { XRenderSetPictureClipRectangles(dmxScreen->beDisplay, pPictPriv->pict, 0, 0, NULL, 0); } dmxSync(dmxScreen, FALSE); } else { /* FIXME: Handle saving clip region when offscreen */ } DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps); return Success; }
/** Composite glyphs on each screen into the requested picture. If * either the src or dest picture has not been allocated due to lazy * window creation, this request will gracefully return. */ static int dmxProcRenderCompositeGlyphs(ClientPtr client) { int ret; REQUEST(xRenderCompositeGlyphsReq); ret = dmxSaveRenderVector[stuff->renderReqType] (client); /* For the following to work with PanoramiX, it assumes that Render * wraps the ProcRenderVector after dmxRenderInit has been called. */ if (ret == Success) { PicturePtr pSrc; dmxPictPrivPtr pSrcPriv; PicturePtr pDst; dmxPictPrivPtr pDstPriv; PictFormatPtr pFmt; XRenderPictFormat *pFormat; int size; int scrnNum; DMXScreenInfo *dmxScreen; CARD8 *buffer; CARD8 *end; int space; int nglyph; char *glyphs; char *curGlyph; xGlyphElt *elt; int nelt; XGlyphElt8 *elts; XGlyphElt8 *curElt; GlyphSetPtr glyphSet; dmxGlyphPrivPtr glyphPriv; dixLookupResourceByType((void **) &pSrc, stuff->src, PictureType, client, DixReadAccess); pSrcPriv = DMX_GET_PICT_PRIV(pSrc); if (!pSrcPriv->pict) return ret; dixLookupResourceByType((void **) &pDst, stuff->dst, PictureType, client, DixWriteAccess); pDstPriv = DMX_GET_PICT_PRIV(pDst); if (!pDstPriv->pict) return ret; scrnNum = pDst->pDrawable->pScreen->myNum; dmxScreen = &dmxScreens[scrnNum]; /* Note: If the back-end display has been detached, then it * should not be possible to reach here since the pSrcPriv->pict * and pDstPriv->pict will have already been set to 0. */ if (!dmxScreen->beDisplay) return ret; if (stuff->maskFormat) dixLookupResourceByType((void **) &pFmt, stuff->maskFormat, PictFormatType, client, DixReadAccess); else pFmt = NULL; pFormat = dmxFindFormat(dmxScreen, pFmt); switch (stuff->renderReqType) { case X_RenderCompositeGlyphs8: size = sizeof(CARD8); break; case X_RenderCompositeGlyphs16: size = sizeof(CARD16); break; case X_RenderCompositeGlyphs32: size = sizeof(CARD32); break; default: return BadPictOp; /* Can't happen */ } buffer = (CARD8 *) (stuff + 1); end = (CARD8 *) stuff + (stuff->length << 2); nelt = 0; nglyph = 0; while (buffer + sizeof(xGlyphElt) < end) { elt = (xGlyphElt *) buffer; buffer += sizeof(xGlyphElt); if (elt->len == 0xff) { buffer += 4; } else { nelt++; nglyph += elt->len; space = size * elt->len; if (space & 3) space += 4 - (space & 3); buffer += space; } } /* The following only works for Render version > 0.2 */ /* All of the XGlyphElt* structure sizes are identical */ elts = malloc(nelt * sizeof(XGlyphElt8)); if (!elts) return BadAlloc; glyphs = malloc(nglyph * size); if (!glyphs) { free(elts); return BadAlloc; } buffer = (CARD8 *) (stuff + 1); end = (CARD8 *) stuff + (stuff->length << 2); curGlyph = glyphs; curElt = elts; dixLookupResourceByType((void **) &glyphSet, stuff->glyphset, GlyphSetType, client, DixReadAccess); glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); while (buffer + sizeof(xGlyphElt) < end) { elt = (xGlyphElt *) buffer; buffer += sizeof(xGlyphElt); if (elt->len == 0xff) { dixLookupResourceByType((void **) &glyphSet, *((CARD32 *) buffer), GlyphSetType, client, DixReadAccess); glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); buffer += 4; } else { curElt->glyphset = glyphPriv->glyphSets[scrnNum]; curElt->xOff = elt->deltax; curElt->yOff = elt->deltay; curElt->nchars = elt->len; curElt->chars = curGlyph; memcpy(curGlyph, buffer, size * elt->len); curGlyph += size * elt->len; curElt++; space = size * elt->len; if (space & 3) space += 4 - (space & 3); buffer += space; } } switch (stuff->renderReqType) { case X_RenderCompositeGlyphs8: XRenderCompositeText8(dmxScreen->beDisplay, stuff->op, pSrcPriv->pict, pDstPriv->pict, pFormat, stuff->xSrc, stuff->ySrc, 0, 0, elts, nelt); break; case X_RenderCompositeGlyphs16: XRenderCompositeText16(dmxScreen->beDisplay, stuff->op, pSrcPriv->pict, pDstPriv->pict, pFormat, stuff->xSrc, stuff->ySrc, 0, 0, (XGlyphElt16 *) elts, nelt); break; case X_RenderCompositeGlyphs32: XRenderCompositeText32(dmxScreen->beDisplay, stuff->op, pSrcPriv->pict, pDstPriv->pict, pFormat, stuff->xSrc, stuff->ySrc, 0, 0, (XGlyphElt32 *) elts, nelt); break; } dmxSync(dmxScreen, FALSE); free(elts); free(glyphs); } return ret; }
/** Validate the picture's attributes before rendering to it. Update * any picture attributes that have been changed by one of the higher * layers. */ void dmxValidatePicture(PicturePtr pPicture, Mask mask) { ScreenPtr pScreen = pPicture->pDrawable->pScreen; DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; PictureScreenPtr ps = GetPictureScreen(pScreen); dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); DMX_UNWRAP(ValidatePicture, dmxScreen, ps); /* Change picture attributes on back-end server */ if (pPictPriv->pict) { XRenderPictureAttributes attribs; if (mask & CPRepeat) { attribs.repeat = pPicture->repeatType; } if (mask & CPAlphaMap) { if (pPicture->alphaMap) { dmxPictPrivPtr pAlphaPriv; pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap); if (pAlphaPriv->pict) { attribs.alpha_map = pAlphaPriv->pict; } else { /* FIXME: alpha picture drawable has not been created?? */ return; /* or should this be: attribs.alpha_map = None; */ } } else { attribs.alpha_map = None; } } if (mask & CPAlphaXOrigin) attribs.alpha_x_origin = pPicture->alphaOrigin.x; if (mask & CPAlphaYOrigin) attribs.alpha_y_origin = pPicture->alphaOrigin.y; if (mask & CPClipXOrigin) attribs.clip_x_origin = pPicture->clipOrigin.x; if (mask & CPClipYOrigin) attribs.clip_y_origin = pPicture->clipOrigin.y; if (mask & CPClipMask) mask &= ~CPClipMask; /* Handled in ChangePictureClip */ if (mask & CPGraphicsExposure) attribs.graphics_exposures = pPicture->graphicsExposures; if (mask & CPSubwindowMode) attribs.subwindow_mode = pPicture->subWindowMode; if (mask & CPPolyEdge) attribs.poly_edge = pPicture->polyEdge; if (mask & CPPolyMode) attribs.poly_mode = pPicture->polyMode; if (mask & CPComponentAlpha) attribs.component_alpha = pPicture->componentAlpha; XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict, mask, &attribs); dmxSync(dmxScreen, FALSE); } else { pPictPriv->savedMask |= mask; } #if 1 if (ps->ValidatePicture) ps->ValidatePicture(pPicture, mask); #endif DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps); }
/** Transfer \a pBits image to back-end server associated with \a * pDrawable's screen. If primitive subdivision optimization is * enabled, then only transfer the sections of \a pBits that are * visible (i.e., not-clipped) to the back-end server. */ void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits) { DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); XImage *img; if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; img = XCreateImage(dmxScreen->beDisplay, dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, depth, format, leftPad, pBits, w, h, BitmapPad(dmxScreen->beDisplay), (format == ZPixmap) ? PixmapBytePad(w, depth) : BitmapBytePad(w+leftPad)); if (img) { Drawable draw; DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); if (dmxSubdividePrimitives && pGC->pCompositeClip) { RegionPtr pSubImages; RegionPtr pClip; BoxRec box; BoxPtr pBox; int nBox; box.x1 = x; box.y1 = y; box.x2 = x + w; box.y2 = y + h; pSubImages = RegionCreate(&box, 1); pClip = RegionCreate(NullBox, 1); RegionCopy(pClip, pGC->pCompositeClip); RegionTranslate(pClip, -pDrawable->x, -pDrawable->y); RegionIntersect(pSubImages, pSubImages, pClip); nBox = RegionNumRects(pSubImages); pBox = RegionRects(pSubImages); while (nBox--) { XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, img, pBox->x1 - box.x1, pBox->y1 - box.y1, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); pBox++; } RegionDestroy(pClip); RegionDestroy(pSubImages); } else { XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, img, 0, 0, x, y, w, h); } XFree(img); /* Use XFree instead of XDestroyImage * because pBits is passed in from the * caller. */ dmxSync(dmxScreen, FALSE); } else { /* Error -- this should not happen! */ } }
/** Set the values in the graphics context on the back-end server * associated with \a pGC's screen. */ void dmxChangeGC(GCPtr pGC, unsigned long mask) { ScreenPtr pScreen = pGC->pScreen; DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); XGCValues v; DMX_GC_FUNC_PROLOGUE(pGC); #if 0 pGC->funcs->ChangeGC(pGC, mask); #endif /* Handle "magic special case" from CreateGC */ if (pGCPriv->msc) { /* The "magic special case" is used to handle the case where a * foreground pixel is set when the GC is created so that a * "pseudo default-tile" can be created and used in case the * fillstyle was set to FillTiled. This specific case is tested * in xtest (XCreateGC test #3). What has happened in dix by * the time it reaches here is (1) the pGC->tile.pixel has been * set to pGC->fgPixel and pGC->tileIsPixel is set, (2) if a * tile has also been set, then pGC->tileIsPixel is unset and * pGC->tile.pixmap is initialized; else, the default tile is * created and pGC->tileIsPixel is unset and pGC->tile.pixmap is * initialized to the "pseudo default-tile". In either case, * pGC->tile.pixmap is set; however, in the "magic special case" * the mask is not updated to allow us to detect that we should * initialize the GCTile in the back-end server. Thus, we catch * this case in dmxCreateGC and add GCTile to the mask here. * Are there any cases that I've missed? */ /* Make sure that the tile.pixmap is set, just in case the user * set GCTile in the mask but forgot to set vals.pixmap */ if (pGC->tile.pixmap) mask |= GCTile; /* This only happens once when the GC is created */ pGCPriv->msc = FALSE; } /* Update back-end server's gc */ if (mask & GCFunction) v.function = pGC->alu; if (mask & GCPlaneMask) v.plane_mask = pGC->planemask; if (mask & GCForeground) v.foreground = pGC->fgPixel; if (mask & GCBackground) v.background = pGC->bgPixel; if (mask & GCLineWidth) v.line_width = pGC->lineWidth; if (mask & GCLineStyle) v.line_style = pGC->lineStyle; if (mask & GCCapStyle) v.cap_style = pGC->capStyle; if (mask & GCJoinStyle) v.join_style = pGC->joinStyle; if (mask & GCFillStyle) v.fill_style = pGC->fillStyle; if (mask & GCFillRule) v.fill_rule = pGC->fillRule; if (mask & GCTile) { if (pGC->tileIsPixel) { mask &= ~GCTile; } else { dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->tile.pixmap); v.tile = (Drawable) pPixPriv->pixmap; } } if (mask & GCStipple) { dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->stipple); v.stipple = (Drawable) pPixPriv->pixmap; } if (mask & GCTileStipXOrigin) v.ts_x_origin = pGC->patOrg.x; if (mask & GCTileStipYOrigin) v.ts_y_origin = pGC->patOrg.y; if (mask & GCFont) { if (dmxScreen->beDisplay) { dmxFontPrivPtr pFontPriv; pFontPriv = FontGetPrivate(pGC->font, dmxFontPrivateIndex); v.font = pFontPriv->font[pScreen->myNum]->fid; } else { mask &= ~GCFont; } } if (mask & GCSubwindowMode) v.subwindow_mode = pGC->subWindowMode; /* Graphics exposures are not needed on the back-ends since they can be generated on the front-end thereby saving bandwidth. */ if (mask & GCGraphicsExposures) mask &= ~GCGraphicsExposures; if (mask & GCClipXOrigin) v.clip_x_origin = pGC->clipOrg.x; if (mask & GCClipYOrigin) v.clip_y_origin = pGC->clipOrg.y; if (mask & GCClipMask) mask &= ~GCClipMask; /* See ChangeClip */ if (mask & GCDashOffset) v.dash_offset = pGC->dashOffset; if (mask & GCDashList) { mask &= ~GCDashList; if (dmxScreen->beDisplay) XSetDashes(dmxScreen->beDisplay, pGCPriv->gc, pGC->dashOffset, (char *) pGC->dash, pGC->numInDashList); } if (mask & GCArcMode) v.arc_mode = pGC->arcMode; if (mask && dmxScreen->beDisplay) { XChangeGC(dmxScreen->beDisplay, pGCPriv->gc, mask, &v); dmxSync(dmxScreen, FALSE); } DMX_GC_FUNC_EPILOGUE(pGC); }