mbsmemb_update.c revision 830
830N/A/* Copyright 1999 Sun Microsystems, Inc. All rights reserved.
830N/A * Use is subject to license terms.
830N/A *
830N/A * Permission is hereby granted, free of charge, to any person obtaining a
830N/A * copy of this software and associated documentation files (the
830N/A * "Software"), to deal in the Software without restriction, including
830N/A * without limitation the rights to use, copy, modify, merge, publish,
830N/A * distribute, and/or sell copies of the Software, and to permit persons
830N/A * to whom the Software is furnished to do so, provided that the above
830N/A * copyright notice(s) and this permission notice appear in all copies of
830N/A * the Software and that both the above copyright notice(s) and this
830N/A * permission notice appear in supporting documentation.
830N/A *
830N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
830N/A * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
830N/A * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
830N/A * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
830N/A * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
830N/A * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
830N/A * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
830N/A * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
830N/A * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
830N/A *
830N/A * Except as contained in this notice, the name of a copyright holder
830N/A * shall not be used in advertising or otherwise to promote the sale, use
830N/A * or other dealings in this Software without prior written authorization
830N/A * of the copyright holder.
830N/A */
830N/A
830N/A#pragma ident "@(#)mbsmemb_update.c 35.8 09/11/09 SMI"
830N/A
830N/A/*
830N/A**
830N/A** mbsmemb_update.c
830N/A**
830N/A** Routines of the update phase that apply equally to both types of
830N/A** multibuffer set members, windows and multibuffers.
830N/A*/
830N/A
830N/A#include <stdio.h>
830N/A#include <sys/types.h>
830N/A#ifdef SERVER_DGA
830N/A#include <X11/Xlib.h>
830N/A#endif /* SERVER_DGA */
830N/A#include "dga_incls.h"
830N/A#include "pix_grab.h"
830N/A#include "mbufsetstr.h"
830N/A
830N/Astatic void dgai_mbsmemb_notifySiteChg (_Dga_window dgawin);
830N/Astatic void dgai_mbsmemb_notifyMbChg (_Dga_window dgawin);
830N/Astatic void dgai_mbsmemb_notifyOvlState (_Dga_window dgawin);
830N/A
830N/A/*
830N/A** The update phase entry routine for mbufset members.
830N/A** Called if the master change count of the shared info
830N/A** differs from the last recorded count in the client structure.
830N/A*/
830N/A
830N/Aint
830N/Adgai_mbsmemb_update (Dga_drawable dgadraw, short bufIndex)
830N/A{
830N/A _Dga_window dgawin = (_Dga_window) dgadraw;
830N/A int status;
830N/A
830N/A#ifdef MT
830N/A if (dgaMTOn) {
830N/A mutex_lock(dgawin->mutexp); /* lock the per-window mutex */
830N/A DGA_LOCK(dgadraw);
830N/A /* check the real change count that we saved away */
830N/A if (dgawin->shadow_chngcnt[bufIndex + 1] == *dgawin->s_chngcnt_p) {
830N/A DGA_UNLOCK(dgadraw);
830N/A mutex_unlock(dgawin->mutexp);
830N/A return (0);
830N/A }
830N/A }
830N/A mutex_lock(&dgaGlobalMutex);
830N/A#endif
830N/A /* establish the new real lock subject */
830N/A dgawin->rLockSubj = bufIndex;
830N/A
830N/A /* save last lock subject. This may be used later in the update phase */
830N/A dgawin->eLockSubjPrev = dgawin->eLockSubj;
830N/A
830N/A /* start out assuming we're not aliased. This may change if we detect
830N/A aliasing later in the update phase */
830N/A dgawin->eLockSubj = dgawin->rLockSubj;
830N/A
830N/A /* the first thing we do is distinguish between locking a window
830N/A and a multibuffer. The update logic is different */
830N/A if (bufIndex == -1) {
830N/A status = dgai_win_update(dgawin, bufIndex);
830N/A } else {
830N/A status = dgai_mbuf_update(dgawin, bufIndex);
830N/A }
830N/A#ifdef MT
830N/A if (dgaMTOn) {
830N/A /* save the real change count */
830N/A dgawin->shadow_chngcnt[bufIndex + 1] =
830N/A dgawin->c_wm_chngcnt[bufIndex + 1];
830N/A /* For the MT case, make sure that this update function gets called
830N/A * the next time around, so overwrite the change count to make it
830N/A * different.
830N/A */
830N/A dgawin->c_wm_chngcnt[bufIndex + 1] = *dgawin->s_chngcnt_p - 1;
830N/A DGA_UNLOCK(dgadraw);
830N/A mutex_unlock(dgawin->mutexp); /* unlock the per-window mutex */
830N/A }
830N/A mutex_unlock(&dgaGlobalMutex);
830N/A#endif
830N/A return (status);
830N/A}
830N/A
830N/A
830N/A/*
830N/A** See if the shared info of the main window is still valid.
830N/A** Nonzero is returned if it is no longer valid and has become
830N/A** a zombie.
830N/A*/
830N/A
830N/Aint
830N/Adgai_mbsmemb_syncZombie (_Dga_window dgawin)
830N/A{
830N/A WXINFO *infop;
830N/A
830N/A infop = (WXINFO *) dgawin->w_info;
830N/A
830N/A if (infop->w_obsolete) {
830N/A dgawin->changeMask |= DGA_CHANGE_ZOMBIE;
830N/A return (1);
830N/A } else {
830N/A return (0);
830N/A }
830N/A}
830N/A
830N/A/*
830N/A** The way we deal with any composition change is to destroy the old
830N/A** multibuffer set and establish a new one.
830N/A*/
830N/A
830N/Avoid
830N/Adgai_mbsmemb_syncMbufset (_Dga_window dgawin)
830N/A{
830N/A
830N/A DgaMbufSetPtr pMbs;
830N/A WXINFO *infop;
830N/A
830N/A /* check to see if this is an actual composition change or simply
830N/A a display change */
830N/A if (dgawin->c_mbcomposseq == *dgawin->s_mbcomposseq_p) {
830N/A /* no change -- must be only a display change */
830N/A return;
830N/A }
830N/A
830N/A /* this is a real composition change. Destroy the old mbufset (if any)
830N/A and create a new one */
830N/A
830N/A infop = (WXINFO *) dgawin->w_info;
830N/A pMbs = dgawin->pMbs;
830N/A
830N/A /* remember whether window was previously multibuffered. This is
830N/A used later in the update phase to determine the reason for the
830N/A mbufset change */
830N/A dgawin->prevWasMbuffered = (pMbs != NULL);
830N/A
830N/A /* destroy the old one */
830N/A if (pMbs) {
830N/A dgai_mbufset_decref(pMbs);
830N/A dgawin->pMbs = NULL;
830N/A }
830N/A
830N/A dgawin->c_mbcomposseq = *dgawin->s_mbcomposseq_p;
830N/A
830N/A if (!infop->w_mbsInfo.enabled) {
830N/A return;
830N/A }
830N/A
830N/A /* create a new one */
830N/A pMbs = dgai_mbufset_create(dgawin);
830N/A
830N/A if (!pMbs) {
830N/A /* TODO: really the only way we have of responding to this is treat
830N/A it as a zombie. It's not ideal, but what else can we do? */
830N/A dgawin->changeMask |= DGA_CHANGE_ZOMBIE;
830N/A }
830N/A
830N/A dgawin->pMbs = pMbs;
830N/A}
830N/A
830N/A
830N/A/*
830N/A** If a render buffer notification function has been registered
830N/A** and the current effective lock subject differs from the current
830N/A** write buffer, call the notification function to change the render
830N/A** buffer state.
830N/A*/
830N/A
830N/Avoid
830N/Adgai_mbsmemb_syncRendBuf (_Dga_window dgawin)
830N/A{
830N/A WXINFO *infop;
830N/A short *pRendBuf;
830N/A
830N/A infop = (WXINFO *) dgawin->w_info;
830N/A
830N/A /* has client registered the notification function? */
830N/A if (!dgawin->rendBufNotifyFunc) {
830N/A return;
830N/A }
830N/A
830N/A /* we only need to notify in single-address access mode */
830N/A if (infop->w_mbsInfo.accessMode != DGA_MBACCESS_SINGLEADDR) {
830N/A return;
830N/A }
830N/A
830N/A /*
830N/A * Only notify if rend buf is different from what we want it to be
830N/A * Note: we treat the write buffer index as the render buffer and ignore
830N/A * the read buffer index.
830N/A */
830N/A pRendBuf = &infop->wx_dbuf.write_buffer;
830N/A if (*pRendBuf != dgawin->eLockSubj) {
830N/A (*dgawin->rendBufNotifyFunc)((Dga_drawable)dgawin, dgawin->eLockSubj,
830N/A dgawin->rendBufNotifyClientData);
830N/A
830N/A /* update the shared info so both the server and other clients can
830N/A see and react to the change */
830N/A *pRendBuf = dgawin->eLockSubj;
830N/A }
830N/A}
830N/A
830N/A/*
830N/A** A derivative change is one which is dependent on changes discovered
830N/A** earlier in the update phase (i.e. the basic changes). We determine here which ones need
830N/A** to be reported. Derivative changes may be reported along with
830N/A** the basic changes. The derivative changes in common for mbufset
830N/A** members are: site change.
830N/A*/
830N/A
830N/Avoid
830N/Adgai_mbsmemb_figureDerivChgs (_Dga_window dgawin)
830N/A{
830N/A /* safety */
830N/A dgawin->siteChgReason = DGA_SITECHG_UNKNOWN;
830N/A
830N/A /* check for zombie */
830N/A if (dgawin->changeMask & DGA_CHANGE_ZOMBIE) {
830N/A /* report both a site change and a clip for zombies. This is simply
830N/A more insurance that the client will sync up with the null clip. */
830N/A dgawin->changeMask |= (DGA_CHANGE_SITE | DGA_CHANGE_CLIP);
830N/A dgawin->siteChgReason = DGA_SITECHG_ZOMBIE;
830N/A return;
830N/A }
830N/A
830N/A /* check for first time */
830N/A if ((dgawin->eLockSubj == -1) && !dgawin->prevLocked) {
830N/A dgawin->changeMask |= DGA_CHANGE_SITE;
830N/A dgawin->siteChgReason = DGA_SITECHG_INITIAL;
830N/A dgawin->prevLocked = 1;
830N/A return;
830N/A } else if ((dgawin->eLockSubj >= 0) &&
830N/A !dgawin->pMbs->prevLocked[(int)dgawin->eLockSubj]) {
830N/A dgawin->changeMask |= DGA_CHANGE_SITE;
830N/A dgawin->siteChgReason = DGA_SITECHG_INITIAL;
830N/A dgawin->pMbs->prevLocked[dgawin->eLockSubj] = 1;
830N/A return;
830N/A }
830N/A
830N/A /* check for cache change */
830N/A if (dgawin->changeMask & DGA_CHANGE_CACHE) {
830N/A dgawin->changeMask |= DGA_CHANGE_SITE;
830N/A dgawin->siteChgReason = DGA_SITECHG_CACHE;
830N/A return;
830N/A }
830N/A
830N/A /* check for alias change */
830N/A if (dgawin->changeMask & DGA_CHANGE_ALIAS) {
830N/A dgawin->changeMask |= DGA_CHANGE_SITE;
830N/A dgawin->siteChgReason = DGA_SITECHG_ALIAS;
830N/A return;
830N/A }
830N/A
830N/A /* check for mbufset composition change */
830N/A if (dgawin->changeMask & DGA_CHANGE_MBUFSET) {
830N/A dgawin->changeMask |= DGA_CHANGE_SITE;
830N/A dgawin->siteChgReason = DGA_SITECHG_MB;
830N/A return;
830N/A }
830N/A}
830N/A
830N/A
830N/A/*
830N/A** If we can report any changes through notification, do so now.
830N/A*/
830N/A
830N/Avoid
830N/Adgai_mbsmemb_notify (_Dga_window dgawin)
830N/A{
830N/A /* report any mbufset change */
830N/A if (dgawin->changeMask & DGA_CHANGE_MBUFSET) {
830N/A dgai_mbsmemb_notifyMbChg(dgawin);
830N/A }
830N/A
830N/A if (dgawin->changeMask & DGA_CHANGE_SITE) {
830N/A dgai_mbsmemb_notifySiteChg(dgawin);
830N/A }
830N/A
830N/A if (dgawin->changeMask & DGA_CHANGE_OVLSTATE) {
830N/A dgai_mbsmemb_notifyOvlState(dgawin);
830N/A }
830N/A
830N/A /* there are no notify functions for the following:
830N/A clip, cursor, bstore, cache */
830N/A}
830N/A
830N/Avoid
830N/Adgai_mbsmemb_devinfo_update(_Dga_window dgawin)
830N/A{
830N/A if (!DGA_LOCKSUBJ_VALID(dgawin, dgawin->eLockSubj) ||
830N/A dgawin->changeMask & DGA_CHANGE_ZOMBIE) {
830N/A return;
830N/A }
830N/A
830N/A if (DGA_LOCKSUBJ_WINDOW(dgawin, dgawin->eLockSubj)) {
830N/A /* check for window devinfo change */
830N/A if (dgawin->c_devinfoseq != *dgawin->s_devinfoseq_p) {
830N/A dgawin->changeMask |= DGA_CHANGE_DEVINFO;
830N/A dgawin->c_devinfoseq = *dgawin->s_devinfoseq_p;
830N/A }
830N/A } else if (!DGA_LOCKSUBJ_VIEWABLE(dgawin, dgawin->eLockSubj)) {
830N/A /* check for nonviewable mbuf devinfo change */
830N/A dgai_nmbuf_devinfo_update(dgawin);
830N/A }
830N/A
830N/A /* Note: viewable mbufs don't have dev info */
830N/A}
830N/A
830N/Astatic void
830N/Adgai_mbsmemb_notifySiteChg (_Dga_window dgawin)
830N/A{
830N/A if (dgawin->siteNotifyFunc) {
830N/A (*dgawin->siteNotifyFunc)((Dga_drawable)dgawin, dgawin->eLockSubj,
830N/A dgawin->siteNotifyClientData,
830N/A dgawin->siteChgReason);
830N/A dgawin->changeMask &= ~DGA_CHANGE_SITE;
830N/A dgawin->siteChgReason = DGA_SITECHG_UNKNOWN;
830N/A } else {
830N/A /* client must find out through dga_draw_sitechg */
830N/A }
830N/A}
830N/A
830N/A
830N/Astatic void
830N/Adgai_mbsmemb_notifyMbChg (_Dga_window dgawin)
830N/A{
830N/A /* figure out reason for change */
830N/A if (!dgawin->prevWasMbuffered && dgawin->pMbs) {
830N/A dgawin->mbChgReason = DGA_MBCHG_ACTIVATION;
830N/A } else if (dgawin->prevWasMbuffered && !dgawin->pMbs) {
830N/A dgawin->mbChgReason = DGA_MBCHG_DEACTIVATION;
830N/A } else if (dgawin->prevWasMbuffered && dgawin->pMbs) {
830N/A dgawin->mbChgReason = DGA_MBCHG_REPLACEMENT;
830N/A } else {
830N/A /* this might happen if the mbufset was activated and then, in
830N/A the same update phase, deactivated. In this case, allow it,
830N/A but just don't report any changes */
830N/A dgawin->changeMask &= ~DGA_CHANGE_MBUFSET;
830N/A dgawin->mbChgReason = DGA_MBCHG_UNKNOWN;
830N/A return;
830N/A }
830N/A
830N/A if (dgawin->mbNotifyFunc) {
830N/A (*dgawin->mbNotifyFunc)((Dga_drawable)dgawin,
830N/A dgawin->mbNotifyClientData,
830N/A dgawin->mbChgReason);
830N/A dgawin->changeMask &= ~DGA_CHANGE_MBUFSET;
830N/A dgawin->mbChgReason = DGA_MBCHG_UNKNOWN;
830N/A } else {
830N/A /* client must find out through dga_draw_mbchg */
830N/A }
830N/A}
830N/A
830N/A
830N/Astatic void
830N/Adgai_mbsmemb_notifyOvlState (_Dga_window dgawin)
830N/A{
830N/A if (dgawin->ovlStateNotifyFunc) {
830N/A (*dgawin->ovlStateNotifyFunc)((Dga_drawable)dgawin,
830N/A dgawin->ovlStateNotifyClientData,
830N/A dgawin->c_ovlstate);
830N/A dgawin->changeMask &= ~DGA_CHANGE_OVLSTATE;
830N/A } else {
830N/A /* client must find out through dga_draw_sitechg */
830N/A }
830N/A}
830N/A