/** Create \a glyphSet on the backend screen number \a idx. */ int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet) { XRenderPictFormat *pFormat; DMXScreenInfo *dmxScreen = &dmxScreens[idx]; dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); PictFormatPtr pFmt = glyphSet->format; int (*oldErrorHandler) (Display *, XErrorEvent *); pFormat = dmxFindFormat(dmxScreen, pFmt); if (!pFormat) { return BadMatch; } dmxGlyphLastError = 0; oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler); /* Catch when this fails */ glyphPriv->glyphSets[idx] = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat); XSetErrorHandler(oldErrorHandler); if (dmxGlyphLastError) { return dmxGlyphLastError; } return Success; }
/** Create a picture on the appropriate screen. This is the actual * function that creates the picture. However, if the associated * window has not yet been created due to lazy window creation, then * delay the picture creation until the window is mapped. */ static Picture dmxDoCreatePicture(PicturePtr pPicture) { DrawablePtr pDraw = pPicture->pDrawable; ScreenPtr pScreen = pDraw->pScreen; DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; XRenderPictFormat *pFormat; Drawable draw; if (pPicture->pDrawable->type == DRAWABLE_WINDOW) { dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr) (pDraw)); if (!(draw = pWinPriv->window)) { /* Window has not been created yet due to the window * optimization. Delay picture creation until window is * mapped. */ pWinPriv->hasPict = TRUE; return 0; } } else { dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr) (pDraw)); if (!(draw = pPixPriv->pixmap)) { /* FIXME: Zero width/height pixmap?? */ return 0; } } /* This should not be reached if the back-end display has been * detached because the pWinPriv->window or the pPixPriv->pixmap * will be NULL; however, we add it here for completeness */ if (!dmxScreen->beDisplay) return 0; pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat); return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0); }
/** Composite a triangle fan on the appropriate screen. For a complete * description see the protocol document of the RENDER library. */ void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int npoint, xPointFixed *points) { ScreenPtr pScreen = pDst->pDrawable->pScreen; DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; PictureScreenPtr ps = GetPictureScreen(pScreen); dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); DMX_UNWRAP(TriFan, dmxScreen, ps); #if 0 if (ps->TriFan) ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); #endif /* Draw trapezoids on back-end server */ if (pDstPriv->pict) { XRenderPictFormat *pFormat; pFormat = dmxFindFormat(dmxScreen, maskFormat); if (!pFormat) { /* FIXME: Error! */ } XRenderCompositeTriFan(dmxScreen->beDisplay, op, pSrcPriv->pict, pDstPriv->pict, pFormat, xSrc, ySrc, (XPointFixed *)points, npoint); dmxSync(dmxScreen, FALSE); } DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps); }
/** 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((pointer *) &pSrc, stuff->src, PictureType, client, DixReadAccess); pSrcPriv = DMX_GET_PICT_PRIV(pSrc); if (!pSrcPriv->pict) return ret; dixLookupResourceByType((pointer *) &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((pointer *) &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((pointer *) &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((pointer *) &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; }
/** Create a Glyph Set on each screen. Save the glyphset ID from each * screen in the Glyph Set's private structure. Fail if the format * requested is not available or if the Glyph Set cannot be created on * the screen. */ static int dmxProcRenderCreateGlyphSet(ClientPtr client) { int ret; REQUEST(xRenderCreateGlyphSetReq); ret = dmxSaveRenderVector[stuff->renderReqType](client); if (ret == Success) { int (*oldErrorHandler)(Display *, XErrorEvent *); GlyphSetPtr glyphSet; dmxGlyphPrivPtr glyphPriv; int i; PictFormatPtr pFmt; XRenderPictFormat *pFormat; /* Look up glyphSet that was just created ???? */ /* Store glyphsets from backends in glyphSet->devPrivate ????? */ /* Make sure we handle all errors here!! */ glyphSet = SecurityLookupIDByType(client, stuff->gsid, GlyphSetType, SecurityDestroyAccess); glyphPriv = xalloc(sizeof(dmxGlyphPrivRec)); if (!glyphPriv) return BadAlloc; glyphPriv->glyphSets = NULL; MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc); DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv); pFmt = SecurityLookupIDByType(client, stuff->format, PictFormatType, SecurityReadAccess); oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler); for (i = 0; i < dmxNumScreens; i++) { DMXScreenInfo *dmxScreen = &dmxScreens[i]; if (!dmxScreen->beDisplay) { glyphPriv->glyphSets[i] = 0; continue; } pFormat = dmxFindFormat(dmxScreen, pFmt); if (!pFormat) { int j; /* Free the glyph sets we've allocated thus far */ for (j = 0; j < i; j++) dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet); /* Free the resource created by render */ FreeResource(stuff->gsid, RT_NONE); ret = BadMatch; break; } /* Catch when this fails */ glyphPriv->glyphSets[i] = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat); if (dmxGlyphLastError) { int j; /* Free the glyph sets we've allocated thus far */ for (j = 0; j < i; j++) dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet); /* Free the resource created by render */ FreeResource(stuff->gsid, RT_NONE); ret = dmxGlyphLastError; break; } } XSetErrorHandler(oldErrorHandler); } return ret; }