1276 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1276 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
 | 
						|
 *
 | 
						|
 * All Rights Reserved.
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining
 | 
						|
 * a copy of this software and associated documentation files (the
 | 
						|
 * "Software"), to deal in the Software without restriction, including
 | 
						|
 * without limitation on the rights to use, copy, modify, merge,
 | 
						|
 * publish, distribute, sublicense, and/or sell copies of the Software,
 | 
						|
 * and to permit persons to whom the Software is furnished to do so,
 | 
						|
 * subject to the following conditions:
 | 
						|
 *
 | 
						|
 * The above copyright notice and this permission notice (including the
 | 
						|
 * next paragraph) shall be included in all copies or substantial
 | 
						|
 * portions of the Software.
 | 
						|
 *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
						|
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
						|
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
						|
 * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
 | 
						|
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
						|
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						|
 * SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * Authors:
 | 
						|
 *   Kevin E. Martin <kem@redhat.com>
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/** \file
 | 
						|
 *  Provide support for the RENDER extension (version 0.8).
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DMX_CONFIG_H
 | 
						|
#include <dmx-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "dmx.h"
 | 
						|
#include "dmxsync.h"
 | 
						|
#include "dmxpict.h"
 | 
						|
#include "dmxwindow.h"
 | 
						|
#include "dmxpixmap.h"
 | 
						|
 | 
						|
#include "fb.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "dixstruct.h"
 | 
						|
 | 
						|
#include <X11/extensions/render.h>
 | 
						|
#include <X11/extensions/renderproto.h>
 | 
						|
#include <X11/extensions/Xfixes.h>
 | 
						|
#include "picture.h"
 | 
						|
#include "picturestr.h"
 | 
						|
#include "mipict.h"
 | 
						|
#include "fbpict.h"
 | 
						|
 | 
						|
extern int (*ProcRenderVector[RenderNumberRequests]) (ClientPtr);
 | 
						|
 | 
						|
static int (*dmxSaveRenderVector[RenderNumberRequests]) (ClientPtr);
 | 
						|
 | 
						|
static int dmxProcRenderCreateGlyphSet(ClientPtr client);
 | 
						|
static int dmxProcRenderFreeGlyphSet(ClientPtr client);
 | 
						|
static int dmxProcRenderAddGlyphs(ClientPtr client);
 | 
						|
static int dmxProcRenderFreeGlyphs(ClientPtr client);
 | 
						|
static int dmxProcRenderCompositeGlyphs(ClientPtr client);
 | 
						|
static int dmxProcRenderSetPictureTransform(ClientPtr client);
 | 
						|
static int dmxProcRenderSetPictureFilter(ClientPtr client);
 | 
						|
 | 
						|
#if 0
 | 
						|
/* FIXME: Not (yet) supported */
 | 
						|
static int dmxProcRenderCreateCursor(ClientPtr client);
 | 
						|
static int dmxProcRenderCreateAnimCursor(ClientPtr client);
 | 
						|
#endif
 | 
						|
 | 
						|
/** Catch errors that might occur when allocating Glyph Sets.  Errors
 | 
						|
 *  are saved in dmxGlyphLastError for later handling. */
 | 
						|
static int dmxGlyphLastError;
 | 
						|
static int
 | 
						|
dmxGlyphErrorHandler(Display * dpy, XErrorEvent * ev)
 | 
						|
{
 | 
						|
    dmxGlyphLastError = ev->error_code;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/** Initialize the Proc Vector for the RENDER extension.  The functions
 | 
						|
 *  here cannot be handled by the mi layer RENDER hooks either because
 | 
						|
 *  the required information is no longer available when it reaches the
 | 
						|
 *  mi layer or no mi layer hooks exist.  This function is called from
 | 
						|
 *  InitOutput() since it should be initialized only once per server
 | 
						|
 *  generation. */
 | 
						|
void
 | 
						|
dmxInitRender(void)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < RenderNumberRequests; i++)
 | 
						|
        dmxSaveRenderVector[i] = ProcRenderVector[i];
 | 
						|
 | 
						|
    ProcRenderVector[X_RenderCreateGlyphSet]
 | 
						|
        = dmxProcRenderCreateGlyphSet;
 | 
						|
    ProcRenderVector[X_RenderFreeGlyphSet]
 | 
						|
        = dmxProcRenderFreeGlyphSet;
 | 
						|
    ProcRenderVector[X_RenderAddGlyphs]
 | 
						|
        = dmxProcRenderAddGlyphs;
 | 
						|
    ProcRenderVector[X_RenderFreeGlyphs]
 | 
						|
        = dmxProcRenderFreeGlyphs;
 | 
						|
    ProcRenderVector[X_RenderCompositeGlyphs8]
 | 
						|
        = dmxProcRenderCompositeGlyphs;
 | 
						|
    ProcRenderVector[X_RenderCompositeGlyphs16]
 | 
						|
        = dmxProcRenderCompositeGlyphs;
 | 
						|
    ProcRenderVector[X_RenderCompositeGlyphs32]
 | 
						|
        = dmxProcRenderCompositeGlyphs;
 | 
						|
    ProcRenderVector[X_RenderSetPictureTransform]
 | 
						|
        = dmxProcRenderSetPictureTransform;
 | 
						|
    ProcRenderVector[X_RenderSetPictureFilter]
 | 
						|
        = dmxProcRenderSetPictureFilter;
 | 
						|
}
 | 
						|
 | 
						|
/** Reset the Proc Vector for the RENDER extension back to the original
 | 
						|
 *  functions.  This function is called from dmxCloseScreen() during the
 | 
						|
 *  server reset (only for screen #0). */
 | 
						|
void
 | 
						|
dmxResetRender(void)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < RenderNumberRequests; i++)
 | 
						|
        ProcRenderVector[i] = dmxSaveRenderVector[i];
 | 
						|
}
 | 
						|
 | 
						|
/** Initialize the RENDER extension, allocate the picture privates and
 | 
						|
 *  wrap mi function hooks.  If the shadow frame buffer is used, then
 | 
						|
 *  call the appropriate fb initialization function. */
 | 
						|
Bool
 | 
						|
dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
 | 
						|
{
 | 
						|
    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 | 
						|
    PictureScreenPtr ps;
 | 
						|
 | 
						|
    if (!miPictureInit(pScreen, formats, nformats))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey
 | 
						|
        (&dmxPictPrivateKeyRec, PRIVATE_PICTURE, sizeof(dmxPictPrivRec)))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    ps = GetPictureScreen(pScreen);
 | 
						|
 | 
						|
    DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
 | 
						|
    DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
 | 
						|
 | 
						|
    DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
 | 
						|
    DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
 | 
						|
 | 
						|
    DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
 | 
						|
    DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
 | 
						|
 | 
						|
    DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
 | 
						|
    DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps);
 | 
						|
    DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
 | 
						|
 | 
						|
    DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
 | 
						|
    DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/** Find the appropriate format on the requested screen given the
 | 
						|
 *  internal format requested.  The list of formats is searched
 | 
						|
 *  sequentially as the XRenderFindFormat() function does not always
 | 
						|
 *  find the appropriate format when a specific format is requested. */
 | 
						|
static XRenderPictFormat *
 | 
						|
dmxFindFormat(DMXScreenInfo * dmxScreen, PictFormatPtr pFmt)
 | 
						|
{
 | 
						|
    XRenderPictFormat *pFormat = NULL;
 | 
						|
    int i = 0;
 | 
						|
 | 
						|
    if (!pFmt || !dmxScreen->beDisplay)
 | 
						|
        return pFormat;
 | 
						|
 | 
						|
    while (1) {
 | 
						|
        pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
 | 
						|
        if (!pFormat)
 | 
						|
            break;
 | 
						|
 | 
						|
        if (pFormat->type != pFmt->type)
 | 
						|
            continue;
 | 
						|
        if (pFormat->depth != pFmt->depth)
 | 
						|
            continue;
 | 
						|
        if (pFormat->direct.red != pFmt->direct.red)
 | 
						|
            continue;
 | 
						|
        if (pFormat->direct.redMask != pFmt->direct.redMask)
 | 
						|
            continue;
 | 
						|
        if (pFormat->direct.green != pFmt->direct.green)
 | 
						|
            continue;
 | 
						|
        if (pFormat->direct.greenMask != pFmt->direct.greenMask)
 | 
						|
            continue;
 | 
						|
        if (pFormat->direct.blue != pFmt->direct.blue)
 | 
						|
            continue;
 | 
						|
        if (pFormat->direct.blueMask != pFmt->direct.blueMask)
 | 
						|
            continue;
 | 
						|
        if (pFormat->direct.alpha != pFmt->direct.alpha)
 | 
						|
            continue;
 | 
						|
        if (pFormat->direct.alphaMask != pFmt->direct.alphaMask)
 | 
						|
            continue;
 | 
						|
 | 
						|
        /* We have a match! */
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    return pFormat;
 | 
						|
}
 | 
						|
 | 
						|
/** Free \a glyphSet on back-end screen number \a idx. */
 | 
						|
Bool
 | 
						|
dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
 | 
						|
{
 | 
						|
    dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
 | 
						|
    int idx = pScreen->myNum;
 | 
						|
    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
 | 
						|
 | 
						|
    if (glyphPriv->glyphSets[idx]) {
 | 
						|
        XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
 | 
						|
        glyphPriv->glyphSets[idx] = (GlyphSet) 0;
 | 
						|
        return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/** 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 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) {
 | 
						|
        GlyphSetPtr glyphSet;
 | 
						|
        dmxGlyphPrivPtr glyphPriv;
 | 
						|
        int i;
 | 
						|
 | 
						|
        /* Look up glyphSet that was just created ???? */
 | 
						|
        /* Store glyphsets from backends in glyphSet->devPrivate ????? */
 | 
						|
        /* Make sure we handle all errors here!! */
 | 
						|
 | 
						|
        dixLookupResourceByType((void **) &glyphSet,
 | 
						|
                                stuff->gsid, GlyphSetType,
 | 
						|
                                client, DixDestroyAccess);
 | 
						|
 | 
						|
        glyphPriv = malloc(sizeof(dmxGlyphPrivRec));
 | 
						|
        if (!glyphPriv)
 | 
						|
            return BadAlloc;
 | 
						|
        glyphPriv->glyphSets = NULL;
 | 
						|
        MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
 | 
						|
        DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
 | 
						|
 | 
						|
        for (i = 0; i < dmxNumScreens; i++) {
 | 
						|
            DMXScreenInfo *dmxScreen = &dmxScreens[i];
 | 
						|
            int beret;
 | 
						|
 | 
						|
            if (!dmxScreen->beDisplay) {
 | 
						|
                glyphPriv->glyphSets[i] = 0;
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
 | 
						|
            if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
 | 
						|
                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);
 | 
						|
 | 
						|
                return beret;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/** Free the previously allocated Glyph Sets for each screen. */
 | 
						|
static int
 | 
						|
dmxProcRenderFreeGlyphSet(ClientPtr client)
 | 
						|
{
 | 
						|
    GlyphSetPtr glyphSet;
 | 
						|
 | 
						|
    REQUEST(xRenderFreeGlyphSetReq);
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
 | 
						|
    dixLookupResourceByType((void **) &glyphSet,
 | 
						|
                            stuff->glyphset, GlyphSetType,
 | 
						|
                            client, DixDestroyAccess);
 | 
						|
 | 
						|
    if (glyphSet && glyphSet->refcnt == 1) {
 | 
						|
        dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
 | 
						|
        int i;
 | 
						|
 | 
						|
        for (i = 0; i < dmxNumScreens; i++) {
 | 
						|
            DMXScreenInfo *dmxScreen = &dmxScreens[i];
 | 
						|
 | 
						|
            if (dmxScreen->beDisplay) {
 | 
						|
                if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
 | 
						|
                    dmxSync(dmxScreen, FALSE);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        MAXSCREENSFREE(glyphPriv->glyphSets);
 | 
						|
        free(glyphPriv);
 | 
						|
        DMX_SET_GLYPH_PRIV(glyphSet, NULL);
 | 
						|
    }
 | 
						|
 | 
						|
    return dmxSaveRenderVector[stuff->renderReqType] (client);
 | 
						|
}
 | 
						|
 | 
						|
/** Add glyphs to the Glyph Set on each screen. */
 | 
						|
static int
 | 
						|
dmxProcRenderAddGlyphs(ClientPtr client)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
 | 
						|
    REQUEST(xRenderAddGlyphsReq);
 | 
						|
 | 
						|
    ret = dmxSaveRenderVector[stuff->renderReqType] (client);
 | 
						|
 | 
						|
    if (ret == Success) {
 | 
						|
        GlyphSetPtr glyphSet;
 | 
						|
        dmxGlyphPrivPtr glyphPriv;
 | 
						|
        int i;
 | 
						|
        int nglyphs;
 | 
						|
        CARD32 *gids;
 | 
						|
        Glyph *gidsCopy;
 | 
						|
        xGlyphInfo *gi;
 | 
						|
        CARD8 *bits;
 | 
						|
        int nbytes;
 | 
						|
 | 
						|
        dixLookupResourceByType((void **) &glyphSet,
 | 
						|
                                stuff->glyphset, GlyphSetType,
 | 
						|
                                client, DixReadAccess);
 | 
						|
        glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
 | 
						|
 | 
						|
        nglyphs = stuff->nglyphs;
 | 
						|
        gids = (CARD32 *) (stuff + 1);
 | 
						|
        gi = (xGlyphInfo *) (gids + nglyphs);
 | 
						|
        bits = (CARD8 *) (gi + nglyphs);
 | 
						|
        nbytes = ((stuff->length << 2) -
 | 
						|
                  sizeof(xRenderAddGlyphsReq) -
 | 
						|
                  (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
 | 
						|
 | 
						|
        gidsCopy = malloc(sizeof(*gidsCopy) * nglyphs);
 | 
						|
        for (i = 0; i < nglyphs; i++)
 | 
						|
            gidsCopy[i] = gids[i];
 | 
						|
 | 
						|
        /* FIXME: Will this ever fail? */
 | 
						|
        for (i = 0; i < dmxNumScreens; i++) {
 | 
						|
            DMXScreenInfo *dmxScreen = &dmxScreens[i];
 | 
						|
 | 
						|
            if (dmxScreen->beDisplay) {
 | 
						|
                XRenderAddGlyphs(dmxScreen->beDisplay,
 | 
						|
                                 glyphPriv->glyphSets[i],
 | 
						|
                                 gidsCopy,
 | 
						|
                                 (XGlyphInfo *) gi,
 | 
						|
                                 nglyphs, (char *) bits, nbytes);
 | 
						|
                dmxSync(dmxScreen, FALSE);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        free(gidsCopy);
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/** Free glyphs from the Glyph Set for each screen. */
 | 
						|
static int
 | 
						|
dmxProcRenderFreeGlyphs(ClientPtr client)
 | 
						|
{
 | 
						|
    GlyphSetPtr glyphSet;
 | 
						|
 | 
						|
    REQUEST(xRenderFreeGlyphsReq);
 | 
						|
 | 
						|
    REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
 | 
						|
    dixLookupResourceByType((void **) &glyphSet,
 | 
						|
                            stuff->glyphset, GlyphSetType,
 | 
						|
                            client, DixWriteAccess);
 | 
						|
 | 
						|
    if (glyphSet) {
 | 
						|
        dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
 | 
						|
        int i;
 | 
						|
        int nglyphs;
 | 
						|
        Glyph *gids;
 | 
						|
 | 
						|
        nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2;
 | 
						|
        if (nglyphs) {
 | 
						|
            gids = malloc(sizeof(*gids) * nglyphs);
 | 
						|
            for (i = 0; i < nglyphs; i++)
 | 
						|
                gids[i] = ((CARD32 *) (stuff + 1))[i];
 | 
						|
 | 
						|
            for (i = 0; i < dmxNumScreens; i++) {
 | 
						|
                DMXScreenInfo *dmxScreen = &dmxScreens[i];
 | 
						|
 | 
						|
                if (dmxScreen->beDisplay) {
 | 
						|
                    XRenderFreeGlyphs(dmxScreen->beDisplay,
 | 
						|
                                      glyphPriv->glyphSets[i], gids, nglyphs);
 | 
						|
                    dmxSync(dmxScreen, FALSE);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            free(gids);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return dmxSaveRenderVector[stuff->renderReqType] (client);
 | 
						|
}
 | 
						|
 | 
						|
/** 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;
 | 
						|
}
 | 
						|
 | 
						|
/** Set the picture transform on each screen. */
 | 
						|
static int
 | 
						|
dmxProcRenderSetPictureTransform(ClientPtr client)
 | 
						|
{
 | 
						|
    DMXScreenInfo *dmxScreen;
 | 
						|
    PicturePtr pPicture;
 | 
						|
    dmxPictPrivPtr pPictPriv;
 | 
						|
    XTransform xform;
 | 
						|
 | 
						|
    REQUEST(xRenderSetPictureTransformReq);
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
 | 
						|
    VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
 | 
						|
 | 
						|
    /* For the following to work with PanoramiX, it assumes that Render
 | 
						|
     * wraps the ProcRenderVector after dmxRenderInit has been called.
 | 
						|
     */
 | 
						|
    dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
 | 
						|
    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 | 
						|
 | 
						|
    if (pPictPriv->pict) {
 | 
						|
        xform.matrix[0][0] = stuff->transform.matrix11;
 | 
						|
        xform.matrix[0][1] = stuff->transform.matrix12;
 | 
						|
        xform.matrix[0][2] = stuff->transform.matrix13;
 | 
						|
        xform.matrix[1][0] = stuff->transform.matrix21;
 | 
						|
        xform.matrix[1][1] = stuff->transform.matrix22;
 | 
						|
        xform.matrix[1][2] = stuff->transform.matrix23;
 | 
						|
        xform.matrix[2][0] = stuff->transform.matrix31;
 | 
						|
        xform.matrix[2][1] = stuff->transform.matrix32;
 | 
						|
        xform.matrix[2][2] = stuff->transform.matrix33;
 | 
						|
 | 
						|
        XRenderSetPictureTransform(dmxScreen->beDisplay,
 | 
						|
                                   pPictPriv->pict, &xform);
 | 
						|
        dmxSync(dmxScreen, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    return dmxSaveRenderVector[stuff->renderReqType] (client);
 | 
						|
}
 | 
						|
 | 
						|
/** Set the picture filter on each screen. */
 | 
						|
static int
 | 
						|
dmxProcRenderSetPictureFilter(ClientPtr client)
 | 
						|
{
 | 
						|
    DMXScreenInfo *dmxScreen;
 | 
						|
    PicturePtr pPicture;
 | 
						|
    dmxPictPrivPtr pPictPriv;
 | 
						|
    char *filter;
 | 
						|
    XFixed *params;
 | 
						|
    int nparams;
 | 
						|
 | 
						|
    REQUEST(xRenderSetPictureFilterReq);
 | 
						|
 | 
						|
    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
 | 
						|
    VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
 | 
						|
 | 
						|
    /* For the following to work with PanoramiX, it assumes that Render
 | 
						|
     * wraps the ProcRenderVector after dmxRenderInit has been called.
 | 
						|
     */
 | 
						|
    dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
 | 
						|
    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 | 
						|
 | 
						|
    if (pPictPriv->pict) {
 | 
						|
        filter = (char *) (stuff + 1);
 | 
						|
        params = (XFixed *) (filter + ((stuff->nbytes + 3) & ~3));
 | 
						|
        nparams = ((XFixed *) stuff + client->req_len) - params;
 | 
						|
 | 
						|
        XRenderSetPictureFilter(dmxScreen->beDisplay,
 | 
						|
                                pPictPriv->pict, filter, params, nparams);
 | 
						|
        dmxSync(dmxScreen, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    return dmxSaveRenderVector[stuff->renderReqType] (client);
 | 
						|
}
 | 
						|
 | 
						|
/** 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);
 | 
						|
}
 | 
						|
 | 
						|
/** Create a list of pictures.  This function is called by
 | 
						|
 *  dmxCreateAndRealizeWindow() during the lazy window creation
 | 
						|
 *  realization process.  It creates the entire list of pictures that
 | 
						|
 *  are associated with the given window. */
 | 
						|
void
 | 
						|
dmxCreatePictureList(WindowPtr pWindow)
 | 
						|
{
 | 
						|
    PicturePtr pPicture = GetPictureWindow(pWindow);
 | 
						|
 | 
						|
    while (pPicture) {
 | 
						|
        dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 | 
						|
 | 
						|
        /* Create the picture for this window */
 | 
						|
        pPictPriv->pict = dmxDoCreatePicture(pPicture);
 | 
						|
 | 
						|
        /* ValidatePicture takes care of the state changes */
 | 
						|
 | 
						|
        pPicture = pPicture->pNext;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/** Create \a pPicture on the backend. */
 | 
						|
int
 | 
						|
dmxBECreatePicture(PicturePtr pPicture)
 | 
						|
{
 | 
						|
    dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 | 
						|
 | 
						|
    /* Create picutre on BE */
 | 
						|
    pPictPriv->pict = dmxDoCreatePicture(pPicture);
 | 
						|
 | 
						|
    /* Flush changes to the backend server */
 | 
						|
    dmxValidatePicture(pPicture, (1 << (CPLastBit + 1)) - 1);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
/** Create a picture.  This function handles the CreatePicture
 | 
						|
 *  unwrapping/wrapping and calls dmxDoCreatePicture to actually create
 | 
						|
 *  the picture on the appropriate screen.  */
 | 
						|
int
 | 
						|
dmxCreatePicture(PicturePtr pPicture)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
 | 
						|
    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 | 
						|
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 | 
						|
    dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 | 
						|
    int ret = Success;
 | 
						|
 | 
						|
    DMX_UNWRAP(CreatePicture, dmxScreen, ps);
 | 
						|
#if 1
 | 
						|
    if (ps->CreatePicture)
 | 
						|
        ret = ps->CreatePicture(pPicture);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Create picture on back-end server */
 | 
						|
    pPictPriv->pict = dmxDoCreatePicture(pPicture);
 | 
						|
    pPictPriv->savedMask = 0;
 | 
						|
 | 
						|
    DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/** Destroy \a pPicture on the back-end server. */
 | 
						|
Bool
 | 
						|
dmxBEFreePicture(PicturePtr pPicture)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
 | 
						|
    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 | 
						|
    dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 | 
						|
 | 
						|
    if (pPictPriv->pict) {
 | 
						|
        XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
 | 
						|
        pPictPriv->pict = (Picture) 0;
 | 
						|
        return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/** Destroy a list of pictures that are associated with the window that
 | 
						|
 *  is being destroyed.  This function is called by #dmxDestroyWindow().
 | 
						|
 *  */
 | 
						|
Bool
 | 
						|
dmxDestroyPictureList(WindowPtr pWindow)
 | 
						|
{
 | 
						|
    PicturePtr pPicture = GetPictureWindow(pWindow);
 | 
						|
    Bool ret = FALSE;
 | 
						|
 | 
						|
    while (pPicture) {
 | 
						|
        ret |= dmxBEFreePicture(pPicture);
 | 
						|
        pPicture = pPicture->pNext;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/** Destroy a picture.  This function calls the wrapped function that
 | 
						|
 *  frees the resources in the DMX server associated with this
 | 
						|
 *  picture. */
 | 
						|
void
 | 
						|
dmxDestroyPicture(PicturePtr pPicture)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
 | 
						|
    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 | 
						|
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 | 
						|
 | 
						|
    DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
 | 
						|
 | 
						|
    /* Destroy picture on back-end server */
 | 
						|
    if (dmxBEFreePicture(pPicture))
 | 
						|
        dmxSync(dmxScreen, FALSE);
 | 
						|
 | 
						|
#if 1
 | 
						|
    if (ps->DestroyPicture)
 | 
						|
        ps->DestroyPicture(pPicture);
 | 
						|
#endif
 | 
						|
    DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
 | 
						|
}
 | 
						|
 | 
						|
/** 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;
 | 
						|
}
 | 
						|
 | 
						|
/** Destroy the picture's list of clip rectangles. */
 | 
						|
void
 | 
						|
dmxDestroyPictureClip(PicturePtr pPicture)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
 | 
						|
    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 | 
						|
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 | 
						|
    dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 | 
						|
 | 
						|
    DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
 | 
						|
#if 1
 | 
						|
    if (ps->DestroyPictureClip)
 | 
						|
        ps->DestroyPictureClip(pPicture);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Destroy picture clip rects on back-end server */
 | 
						|
    if (pPictPriv->pict) {
 | 
						|
        XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
 | 
						|
                                        pPictPriv->pict, 0, 0, NULL, 0);
 | 
						|
        dmxSync(dmxScreen, FALSE);
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        /* FIXME: Handle destroying clip region when offscreen */
 | 
						|
    }
 | 
						|
 | 
						|
    DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
 | 
						|
}
 | 
						|
 | 
						|
/** Change the attributes of the pictures.  If the picture has not yet
 | 
						|
 *  been created due to lazy window creation, save the mask so that it
 | 
						|
 *  can be used to appropriately initialize the picture's attributes
 | 
						|
 *  when it is created later. */
 | 
						|
void
 | 
						|
dmxChangePicture(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(ChangePicture, dmxScreen, ps);
 | 
						|
#if 1
 | 
						|
    if (ps->ChangePicture)
 | 
						|
        ps->ChangePicture(pPicture, mask);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Picture attribute changes are handled in ValidatePicture */
 | 
						|
    pPictPriv->savedMask |= mask;
 | 
						|
 | 
						|
    DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
 | 
						|
}
 | 
						|
 | 
						|
/** 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);
 | 
						|
}
 | 
						|
 | 
						|
/** Composite a picture on the appropriate screen by combining the
 | 
						|
 *  specified rectangle of the transformed src and mask operands with
 | 
						|
 *  the specified rectangle of the dst using op as the compositing
 | 
						|
 *  operator.  For a complete description see the protocol document of
 | 
						|
 *  the RENDER library. */
 | 
						|
void
 | 
						|
dmxComposite(CARD8 op,
 | 
						|
             PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
 | 
						|
             INT16 xSrc, INT16 ySrc,
 | 
						|
             INT16 xMask, INT16 yMask,
 | 
						|
             INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
 | 
						|
    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 | 
						|
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 | 
						|
    dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
 | 
						|
    dmxPictPrivPtr pMaskPriv = NULL;
 | 
						|
    dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
 | 
						|
 | 
						|
    if (pMask)
 | 
						|
        pMaskPriv = DMX_GET_PICT_PRIV(pMask);
 | 
						|
 | 
						|
    DMX_UNWRAP(Composite, dmxScreen, ps);
 | 
						|
#if 0
 | 
						|
    if (ps->Composite)
 | 
						|
        ps->Composite(op, pSrc, pMask, pDst,
 | 
						|
                      xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Composite on back-end server */
 | 
						|
    if (pSrcPriv->pict && pDstPriv->pict &&
 | 
						|
        ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
 | 
						|
        XRenderComposite(dmxScreen->beDisplay,
 | 
						|
                         op,
 | 
						|
                         pSrcPriv->pict,
 | 
						|
                         pMaskPriv ? pMaskPriv->pict : None,
 | 
						|
                         pDstPriv->pict,
 | 
						|
                         xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
 | 
						|
        dmxSync(dmxScreen, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
 | 
						|
}
 | 
						|
 | 
						|
/** Null function to catch when/if RENDER calls lower level mi hooks.
 | 
						|
 *  Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
 | 
						|
 *  This function should never be called. */
 | 
						|
void
 | 
						|
dmxGlyphs(CARD8 op,
 | 
						|
          PicturePtr pSrc, PicturePtr pDst,
 | 
						|
          PictFormatPtr maskFormat,
 | 
						|
          INT16 xSrc, INT16 ySrc,
 | 
						|
          int nlists, GlyphListPtr lists, GlyphPtr * glyphs)
 | 
						|
{
 | 
						|
    /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
 | 
						|
}
 | 
						|
 | 
						|
/** Fill a rectangle on the appropriate screen by combining the color
 | 
						|
 *  with the dest picture in the area specified by the list of
 | 
						|
 *  rectangles.  For a complete description see the protocol document of
 | 
						|
 *  the RENDER library. */
 | 
						|
void
 | 
						|
dmxCompositeRects(CARD8 op,
 | 
						|
                  PicturePtr pDst,
 | 
						|
                  xRenderColor * color, int nRect, xRectangle *rects)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
 | 
						|
    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 | 
						|
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 | 
						|
    dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst);
 | 
						|
 | 
						|
    DMX_UNWRAP(CompositeRects, dmxScreen, ps);
 | 
						|
#if 0
 | 
						|
    if (ps->CompositeRects)
 | 
						|
        ps->CompositeRects(op, pDst, color, nRect, rects);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* CompositeRects on back-end server */
 | 
						|
    if (pPictPriv->pict) {
 | 
						|
        XRenderFillRectangles(dmxScreen->beDisplay,
 | 
						|
                              op,
 | 
						|
                              pPictPriv->pict,
 | 
						|
                              (XRenderColor *) color,
 | 
						|
                              (XRectangle *) rects, nRect);
 | 
						|
        dmxSync(dmxScreen, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
 | 
						|
}
 | 
						|
 | 
						|
/** Indexed color visuals are not yet supported. */
 | 
						|
Bool
 | 
						|
dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
 | 
						|
{
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/** Indexed color visuals are not yet supported. */
 | 
						|
void
 | 
						|
dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
/** Indexed color visuals are not yet supported. */
 | 
						|
void
 | 
						|
dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
 | 
						|
                 int ndef, xColorItem * pdef)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
/** Composite a list of trapezoids on the appropriate screen.  For a
 | 
						|
 *  complete description see the protocol document of the RENDER
 | 
						|
 *  library. */
 | 
						|
void
 | 
						|
dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 | 
						|
              PictFormatPtr maskFormat,
 | 
						|
              INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps)
 | 
						|
{
 | 
						|
    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(Trapezoids, dmxScreen, ps);
 | 
						|
#if 0
 | 
						|
    if (ps->Trapezoids)
 | 
						|
        ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Draw trapezoids on back-end server */
 | 
						|
    if (pDstPriv->pict) {
 | 
						|
        XRenderPictFormat *pFormat;
 | 
						|
 | 
						|
        pFormat = dmxFindFormat(dmxScreen, maskFormat);
 | 
						|
        if (!pFormat) {
 | 
						|
            /* FIXME: Error! */
 | 
						|
        }
 | 
						|
 | 
						|
        XRenderCompositeTrapezoids(dmxScreen->beDisplay,
 | 
						|
                                   op,
 | 
						|
                                   pSrcPriv->pict,
 | 
						|
                                   pDstPriv->pict,
 | 
						|
                                   pFormat,
 | 
						|
                                   xSrc, ySrc, (XTrapezoid *) traps, ntrap);
 | 
						|
        dmxSync(dmxScreen, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
 | 
						|
}
 | 
						|
 | 
						|
/** Composite a list of triangles on the appropriate screen.  For a
 | 
						|
 *  complete description see the protocol document of the RENDER
 | 
						|
 *  library. */
 | 
						|
void
 | 
						|
dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 | 
						|
             PictFormatPtr maskFormat,
 | 
						|
             INT16 xSrc, INT16 ySrc, int ntri, xTriangle * tris)
 | 
						|
{
 | 
						|
    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(Triangles, dmxScreen, ps);
 | 
						|
#if 0
 | 
						|
    if (ps->Triangles)
 | 
						|
        ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Draw trapezoids on back-end server */
 | 
						|
    if (pDstPriv->pict) {
 | 
						|
        XRenderPictFormat *pFormat;
 | 
						|
 | 
						|
        pFormat = dmxFindFormat(dmxScreen, maskFormat);
 | 
						|
        if (!pFormat) {
 | 
						|
            /* FIXME: Error! */
 | 
						|
        }
 | 
						|
 | 
						|
        XRenderCompositeTriangles(dmxScreen->beDisplay,
 | 
						|
                                  op,
 | 
						|
                                  pSrcPriv->pict,
 | 
						|
                                  pDstPriv->pict,
 | 
						|
                                  pFormat,
 | 
						|
                                  xSrc, ySrc, (XTriangle *) tris, ntri);
 | 
						|
        dmxSync(dmxScreen, FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
 | 
						|
}
 |