1 /* Copyright (c) 1993, 1999, Oracle and/or its affiliates. All rights reserved.
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice (including the next
11 * paragraph) shall be included in all copies or substantial portions of the
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
28 ** Routines of the update phase that apply equally to both types of
29 ** multibuffer set members, windows and multibuffers.
33 #include <sys/types.h>
36 #endif /* SERVER_DGA */
37 #include "dga_incls.h"
39 #include "mbufsetstr.h"
41 static void dgai_mbsmemb_notifySiteChg (_Dga_window dgawin
);
42 static void dgai_mbsmemb_notifyMbChg (_Dga_window dgawin
);
43 static void dgai_mbsmemb_notifyOvlState (_Dga_window dgawin
);
46 ** The update phase entry routine for mbufset members.
47 ** Called if the master change count of the shared info
48 ** differs from the last recorded count in the client structure.
52 dgai_mbsmemb_update (Dga_drawable dgadraw
, short bufIndex
)
54 _Dga_window dgawin
= (_Dga_window
) dgadraw
;
59 mutex_lock(dgawin
->mutexp
); /* lock the per-window mutex */
61 /* check the real change count that we saved away */
62 if (dgawin
->shadow_chngcnt
[bufIndex
+ 1] == *dgawin
->s_chngcnt_p
) {
64 mutex_unlock(dgawin
->mutexp
);
68 mutex_lock(&dgaGlobalMutex
);
70 /* establish the new real lock subject */
71 dgawin
->rLockSubj
= bufIndex
;
73 /* save last lock subject. This may be used later in the update phase */
74 dgawin
->eLockSubjPrev
= dgawin
->eLockSubj
;
76 /* start out assuming we're not aliased. This may change if we detect
77 aliasing later in the update phase */
78 dgawin
->eLockSubj
= dgawin
->rLockSubj
;
80 /* the first thing we do is distinguish between locking a window
81 and a multibuffer. The update logic is different */
83 status
= dgai_win_update(dgawin
, bufIndex
);
85 status
= dgai_mbuf_update(dgawin
, bufIndex
);
89 /* save the real change count */
90 dgawin
->shadow_chngcnt
[bufIndex
+ 1] =
91 dgawin
->c_wm_chngcnt
[bufIndex
+ 1];
92 /* For the MT case, make sure that this update function gets called
93 * the next time around, so overwrite the change count to make it
96 dgawin
->c_wm_chngcnt
[bufIndex
+ 1] = *dgawin
->s_chngcnt_p
- 1;
98 mutex_unlock(dgawin
->mutexp
); /* unlock the per-window mutex */
100 mutex_unlock(&dgaGlobalMutex
);
107 ** See if the shared info of the main window is still valid.
108 ** Nonzero is returned if it is no longer valid and has become
113 dgai_mbsmemb_syncZombie (_Dga_window dgawin
)
117 infop
= (WXINFO
*) dgawin
->w_info
;
119 if (infop
->w_obsolete
) {
120 dgawin
->changeMask
|= DGA_CHANGE_ZOMBIE
;
128 ** The way we deal with any composition change is to destroy the old
129 ** multibuffer set and establish a new one.
133 dgai_mbsmemb_syncMbufset (_Dga_window dgawin
)
139 /* check to see if this is an actual composition change or simply
141 if (dgawin
->c_mbcomposseq
== *dgawin
->s_mbcomposseq_p
) {
142 /* no change -- must be only a display change */
146 /* this is a real composition change. Destroy the old mbufset (if any)
147 and create a new one */
149 infop
= (WXINFO
*) dgawin
->w_info
;
152 /* remember whether window was previously multibuffered. This is
153 used later in the update phase to determine the reason for the
155 dgawin
->prevWasMbuffered
= (pMbs
!= NULL
);
157 /* destroy the old one */
159 dgai_mbufset_decref(pMbs
);
163 dgawin
->c_mbcomposseq
= *dgawin
->s_mbcomposseq_p
;
165 if (!infop
->w_mbsInfo
.enabled
) {
169 /* create a new one */
170 pMbs
= dgai_mbufset_create(dgawin
);
173 /* TODO: really the only way we have of responding to this is treat
174 it as a zombie. It's not ideal, but what else can we do? */
175 dgawin
->changeMask
|= DGA_CHANGE_ZOMBIE
;
183 ** If a render buffer notification function has been registered
184 ** and the current effective lock subject differs from the current
185 ** write buffer, call the notification function to change the render
190 dgai_mbsmemb_syncRendBuf (_Dga_window dgawin
)
195 infop
= (WXINFO
*) dgawin
->w_info
;
197 /* has client registered the notification function? */
198 if (!dgawin
->rendBufNotifyFunc
) {
202 /* we only need to notify in single-address access mode */
203 if (infop
->w_mbsInfo
.accessMode
!= DGA_MBACCESS_SINGLEADDR
) {
208 * Only notify if rend buf is different from what we want it to be
209 * Note: we treat the write buffer index as the render buffer and ignore
210 * the read buffer index.
212 pRendBuf
= &infop
->wx_dbuf
.write_buffer
;
213 if (*pRendBuf
!= dgawin
->eLockSubj
) {
214 (*dgawin
->rendBufNotifyFunc
)((Dga_drawable
)dgawin
, dgawin
->eLockSubj
,
215 dgawin
->rendBufNotifyClientData
);
217 /* update the shared info so both the server and other clients can
218 see and react to the change */
219 *pRendBuf
= dgawin
->eLockSubj
;
224 ** A derivative change is one which is dependent on changes discovered
225 ** earlier in the update phase (i.e. the basic changes). We determine here which ones need
226 ** to be reported. Derivative changes may be reported along with
227 ** the basic changes. The derivative changes in common for mbufset
228 ** members are: site change.
232 dgai_mbsmemb_figureDerivChgs (_Dga_window dgawin
)
235 dgawin
->siteChgReason
= DGA_SITECHG_UNKNOWN
;
237 /* check for zombie */
238 if (dgawin
->changeMask
& DGA_CHANGE_ZOMBIE
) {
239 /* report both a site change and a clip for zombies. This is simply
240 more insurance that the client will sync up with the null clip. */
241 dgawin
->changeMask
|= (DGA_CHANGE_SITE
| DGA_CHANGE_CLIP
);
242 dgawin
->siteChgReason
= DGA_SITECHG_ZOMBIE
;
246 /* check for first time */
247 if ((dgawin
->eLockSubj
== -1) && !dgawin
->prevLocked
) {
248 dgawin
->changeMask
|= DGA_CHANGE_SITE
;
249 dgawin
->siteChgReason
= DGA_SITECHG_INITIAL
;
250 dgawin
->prevLocked
= 1;
252 } else if ((dgawin
->eLockSubj
>= 0) &&
253 !dgawin
->pMbs
->prevLocked
[(int)dgawin
->eLockSubj
]) {
254 dgawin
->changeMask
|= DGA_CHANGE_SITE
;
255 dgawin
->siteChgReason
= DGA_SITECHG_INITIAL
;
256 dgawin
->pMbs
->prevLocked
[dgawin
->eLockSubj
] = 1;
260 /* check for cache change */
261 if (dgawin
->changeMask
& DGA_CHANGE_CACHE
) {
262 dgawin
->changeMask
|= DGA_CHANGE_SITE
;
263 dgawin
->siteChgReason
= DGA_SITECHG_CACHE
;
267 /* check for alias change */
268 if (dgawin
->changeMask
& DGA_CHANGE_ALIAS
) {
269 dgawin
->changeMask
|= DGA_CHANGE_SITE
;
270 dgawin
->siteChgReason
= DGA_SITECHG_ALIAS
;
274 /* check for mbufset composition change */
275 if (dgawin
->changeMask
& DGA_CHANGE_MBUFSET
) {
276 dgawin
->changeMask
|= DGA_CHANGE_SITE
;
277 dgawin
->siteChgReason
= DGA_SITECHG_MB
;
284 ** If we can report any changes through notification, do so now.
288 dgai_mbsmemb_notify (_Dga_window dgawin
)
290 /* report any mbufset change */
291 if (dgawin
->changeMask
& DGA_CHANGE_MBUFSET
) {
292 dgai_mbsmemb_notifyMbChg(dgawin
);
295 if (dgawin
->changeMask
& DGA_CHANGE_SITE
) {
296 dgai_mbsmemb_notifySiteChg(dgawin
);
299 if (dgawin
->changeMask
& DGA_CHANGE_OVLSTATE
) {
300 dgai_mbsmemb_notifyOvlState(dgawin
);
303 /* there are no notify functions for the following:
304 clip, cursor, bstore, cache */
308 dgai_mbsmemb_devinfo_update(_Dga_window dgawin
)
310 if (!DGA_LOCKSUBJ_VALID(dgawin
, dgawin
->eLockSubj
) ||
311 dgawin
->changeMask
& DGA_CHANGE_ZOMBIE
) {
315 if (DGA_LOCKSUBJ_WINDOW(dgawin
, dgawin
->eLockSubj
)) {
316 /* check for window devinfo change */
317 if (dgawin
->c_devinfoseq
!= *dgawin
->s_devinfoseq_p
) {
318 dgawin
->changeMask
|= DGA_CHANGE_DEVINFO
;
319 dgawin
->c_devinfoseq
= *dgawin
->s_devinfoseq_p
;
321 } else if (!DGA_LOCKSUBJ_VIEWABLE(dgawin
, dgawin
->eLockSubj
)) {
322 /* check for nonviewable mbuf devinfo change */
323 dgai_nmbuf_devinfo_update(dgawin
);
326 /* Note: viewable mbufs don't have dev info */
330 dgai_mbsmemb_notifySiteChg (_Dga_window dgawin
)
332 if (dgawin
->siteNotifyFunc
) {
333 (*dgawin
->siteNotifyFunc
)((Dga_drawable
)dgawin
, dgawin
->eLockSubj
,
334 dgawin
->siteNotifyClientData
,
335 dgawin
->siteChgReason
);
336 dgawin
->changeMask
&= ~DGA_CHANGE_SITE
;
337 dgawin
->siteChgReason
= DGA_SITECHG_UNKNOWN
;
339 /* client must find out through dga_draw_sitechg */
345 dgai_mbsmemb_notifyMbChg (_Dga_window dgawin
)
347 /* figure out reason for change */
348 if (!dgawin
->prevWasMbuffered
&& dgawin
->pMbs
) {
349 dgawin
->mbChgReason
= DGA_MBCHG_ACTIVATION
;
350 } else if (dgawin
->prevWasMbuffered
&& !dgawin
->pMbs
) {
351 dgawin
->mbChgReason
= DGA_MBCHG_DEACTIVATION
;
352 } else if (dgawin
->prevWasMbuffered
&& dgawin
->pMbs
) {
353 dgawin
->mbChgReason
= DGA_MBCHG_REPLACEMENT
;
355 /* this might happen if the mbufset was activated and then, in
356 the same update phase, deactivated. In this case, allow it,
357 but just don't report any changes */
358 dgawin
->changeMask
&= ~DGA_CHANGE_MBUFSET
;
359 dgawin
->mbChgReason
= DGA_MBCHG_UNKNOWN
;
363 if (dgawin
->mbNotifyFunc
) {
364 (*dgawin
->mbNotifyFunc
)((Dga_drawable
)dgawin
,
365 dgawin
->mbNotifyClientData
,
366 dgawin
->mbChgReason
);
367 dgawin
->changeMask
&= ~DGA_CHANGE_MBUFSET
;
368 dgawin
->mbChgReason
= DGA_MBCHG_UNKNOWN
;
370 /* client must find out through dga_draw_mbchg */
376 dgai_mbsmemb_notifyOvlState (_Dga_window dgawin
)
378 if (dgawin
->ovlStateNotifyFunc
) {
379 (*dgawin
->ovlStateNotifyFunc
)((Dga_drawable
)dgawin
,
380 dgawin
->ovlStateNotifyClientData
,
382 dgawin
->changeMask
&= ~DGA_CHANGE_OVLSTATE
;
384 /* client must find out through dga_draw_sitechg */