/* Copyright (c) 1993, 1997, Oracle and/or its affiliates. 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
 * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS 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.
 */


/* 
** mbufset.c - Routines to manipulate multibuffer set objects.
*/

#include <malloc.h>
#ifdef SERVER_DGA
#include <X11/Xlib.h>
#endif /* SERVER_DGA */
#include "dga_incls.h"
#include "pix_grab.h"
#include "mbufsetstr.h"

static void dgai_mbufset_destroy (DgaMbufSetPtr pMbs);

extern int dga_pixlist_add(Dga_token token, Display *dpy, Pixmap pix);

/*
** Create a client-side multibuffer set object based on information
** in the shinfo of a window.  The window must be locked prior to calling.
*/

DgaMbufSetPtr
dgai_mbufset_create (_Dga_window dgawin)
{
    DgaMbufSetPtr 	pMbs;
    WXINFO		*infop;
    DgaMbufSetShinfoPtr	pMbsInfo;
    short		numBufs, i;
    unsigned long	bufViewableFlags, bufMask;
    Dga_token		token;
    _Dga_pixmap		dgapix;
    XID			*pShinfoId;

    infop = (WXINFO *) dgawin->w_info;
    pMbsInfo = &infop->w_mbsInfo;    
    token = (Dga_token) pMbsInfo->nmbufShpxToken;
    pShinfoId = &(pMbsInfo->nmbufIds[0]);

    /* allocate mbufset client structure */
    if (!(pMbs = (DgaMbufSetPtr) malloc(sizeof(DgaMbufSet)))) {
	return (NULL);
    }

    numBufs = infop->wx_dbuf.number_buffers;
    pMbs->numBufs = numBufs;

    for (i = 0; i < numBufs;  i++) {
	pMbs->pNbPixmaps[i] = NULL;
    }

    bufViewableFlags = pMbsInfo->bufViewableFlags;
    bufMask = 1L;
    for (i = 0; i < numBufs;  i++, pShinfoId++) {
	if (!(bufViewableFlags & bufMask)) {
	    if (!dga_pixlist_add(token, dgawin->w_dpy, (Pixmap)*pShinfoId) ||
	        !(dgapix = dga_pix_grab(token, (Pixmap)*pShinfoId))) {
		goto Bad;
	    }
	    pMbs->pNbPixmaps[i] = dgapix;
	    pMbs->pNbShinfo[i] = (SHARED_PIXMAP_INFO *)dgapix->p_infop;
	} else {
	    pMbs->pNbShinfo[i] = NULL;
	}
	pMbs->mbufseq[i] = 0;
	pMbs->clipseq[i] = 0;
	pMbs->curseq[i] = 0;
	pMbs->cacheSeqs[i] = 0;
	pMbs->devInfoSeqs[i] = 0;
	pMbs->prevLocked[i] = 0;
	bufMask = bufMask << 1;
    }

    /* success */
    pMbs->refcnt = 1;
    return (pMbs);

Bad:
    dgai_mbufset_destroy(pMbs);
    return (NULL);
}


void
dgai_mbufset_incref (DgaMbufSetPtr pMbs)
{
    pMbs->refcnt++;
}


static void
dgai_mbufset_destroy (DgaMbufSetPtr pMbs)
{
    short i;

    for (i = 0; i < pMbs->numBufs;  i++) {
	if (pMbs->pNbPixmaps[i]) {
	    dga_pix_ungrab(pMbs->pNbPixmaps[i]);
	}
    }
    free(pMbs);
}

void
dgai_mbufset_decref (DgaMbufSetPtr pMbs)
{
    if ((int)(--(pMbs->refcnt)) <= 0) {
	dgai_mbufset_destroy(pMbs);
    }
}