1 /* Copyright (c) 1993, 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.
27 ** Routines of the update phase for multibuffers.
33 #endif /* SERVER_DGA */
34 #include "dga_incls.h"
36 #include "mbufsetstr.h"
38 static void dgai_mbuf_getLastSeqs (_Dga_window dgawin
, DgaLastSeqsPtr pLastSeqs
, short bufIndex
);
39 static int dgai_mbuf_syncAgain (_Dga_window dgawin
, DgaLastSeqsPtr pLastSeqs
);
40 static void dgai_mbuf_mb_update (_Dga_window dgawin
);
41 static void dgai_mbuf_syncLockSubj (_Dga_window dgawin
);
42 static void dgai_mbuf_figureDerivChgs (_Dga_window dgawin
);
45 ** Note: On every alias or mbufset change, we will report the following
46 ** types of changes. See comment at start of win_update.c for reason why we
47 ** don't try to optimize change reporting.
53 ** cache (nonviewable mbufs only)
55 ** TODO: ISSUE: since an alias change occurs on every multibuffer frame,
56 ** if we don't optimize for multibuffers this could add unwanted per-frame
57 ** overhead. Is it significant? If so, we are forced to optimize alias
58 ** change reporting. Composition changes are so infrequent that it still
59 ** won't be worth optimizing the reporting of them. (Note: this issue
60 ** doesn't apply to windows.)
65 ** ENTRY ROUTINE FOR MULTIBUFFER UPDATE PHASE
69 dgai_mbuf_update (_Dga_window dgawin
, short bufIndex
)
72 DgaMbufSetPtr pMbufSet
;
75 * Before we get going check to make sure that composition changes
76 * have been noticed. If we don't and the number of multibuffers
77 * has increased bad things will happen.
80 if (dgawin
->c_mbufseq
!= *dgawin
->s_mbufseq_p
)
81 dgai_mbsmemb_syncMbufset(dgawin
);
84 ** 1. The first thing we do in the update phase is to synchronize
85 ** the client structure. When all pertinent client change
86 ** counters match the server, we are synchronized. The
87 ** reason we must do this in a loop is that some of the
88 ** synchronizations require us to temporarily unlock and
89 ** relock. While the drawable is unlocked, it can undergo
90 ** more changes, so we may need to start the synchronization
94 pMbufSet
= dgawin
->pMbs
;
95 /* Determine sequence counts for state reported to client */
96 dgai_mbuf_getLastSeqs(dgawin
, &lastSeqs
, bufIndex
);
98 /* start accumulating changes */
99 dgawin
->changeMask
= 0;
101 /* repeat synchronization functions as needed through possible unlock/relocks */
104 /* first, see if the window shared info is still valid */
105 if (dgai_mbsmemb_syncZombie(dgawin
)) {
109 /* the first thing we must change is the multibuffer state.
110 This may later the effective lock subject, whose type the
111 other synchronization checks depend on */
112 if (lastSeqs
.mbufseq
!= *dgawin
->s_mbufseq_p
) {
113 dgai_mbuf_mb_update(dgawin
);
114 lastSeqs
.mbufseq
= *dgawin
->s_mbufseq_p
;
115 pMbufSet
->mbufseq
[bufIndex
] = lastSeqs
.mbufseq
;
118 /* synchronize with current changes to attributes of
119 the effective lock subject -- depends on the type
120 of the current lock subject */
121 if (DGA_LOCKSUBJ_WINDOW(dgawin
, dgawin
->eLockSubj
)) {
122 dgai_win_syncChanges(dgawin
, &lastSeqs
);
123 } else if (DGA_LOCKSUBJ_VMBUFFER(dgawin
, dgawin
->eLockSubj
)) {
124 dgai_vmbuf_syncChanges(dgawin
, &lastSeqs
, bufIndex
);
125 } else if (DGA_LOCKSUBJ_NMBUFFER(dgawin
, dgawin
->eLockSubj
)) {
126 dgai_nmbuf_syncChanges(dgawin
);
128 /* should never happen */
132 /* Note: whether we need to sync again depends on the type too */
133 } while (dgai_mbuf_syncAgain(dgawin
, &lastSeqs
));
135 /* Check if the devinfo has changed */
136 dgai_mbsmemb_devinfo_update(dgawin
);
139 ** 2. The foregoing synchronization step has determined whether
140 ** any attribute changes have occurred. We must now determine
141 ** if there are any derivative changes to report.
143 dgai_mbuf_figureDerivChgs(dgawin
);
147 ** 3. Next, we must report changes through notification functions,
151 /* report any changes that we can through notification */
152 dgai_mbsmemb_notify(dgawin
);
156 ** 4. Lastly, indicate that we are fully synchronized and get out.
159 /* the dgawin client structure is now fully synchronized with the
161 dgawin
->c_wm_chngcnt
[bufIndex
+ 1] = *dgawin
->s_chngcnt_p
;
163 /* if there are still any changes that were not notified through notification
164 functions, DGA_DRAW_MODIF will return nonzero (the client is
165 supposed to call this routine immediately following the lock).
166 This will cause a well-behaved client to synchronize with
167 the remaining unreported changes */
168 return (dgawin
->changeMask
);
173 dgai_mbuf_getLastSeqs (_Dga_window dgawin
, DgaLastSeqsPtr pLastSeqs
, short bufIndex
)
175 DgaMbufSetPtr pMbufSet
= dgawin
->pMbs
;
177 if (DGA_LOCKSUBJ_WINDOW(dgawin
, dgawin
->eLockSubj
)) {
178 pLastSeqs
->mbufseq
= dgawin
->c_mbufseq
;
179 pLastSeqs
->clipseq
= dgawin
->c_clipseq
;
180 pLastSeqs
->curseq
= dgawin
->c_curseq
;
181 pLastSeqs
->rtnseq
= dgawin
->c_rtnseq
;
183 pLastSeqs
->mbufseq
= pMbufSet
->mbufseq
[bufIndex
];
184 pLastSeqs
->clipseq
= pMbufSet
->clipseq
[bufIndex
];
185 pLastSeqs
->curseq
= pMbufSet
->curseq
[bufIndex
];
186 pLastSeqs
->rtnseq
= dgawin
->c_rtnseq
;
192 ** Returns nonzero if we are still not synchronized
196 dgai_mbuf_syncAgain (_Dga_window dgawin
, DgaLastSeqsPtr pLastSeqs
)
198 /* if a multibuffer change happened, we're still not done */
199 if (pLastSeqs
->mbufseq
!= *dgawin
->s_mbufseq_p
) {
203 if (DGA_LOCKSUBJ_WINDOW(dgawin
, dgawin
->eLockSubj
)) {
204 if ((pLastSeqs
->clipseq
== *dgawin
->s_clipseq_p
) &&
205 (pLastSeqs
->curseq
== *dgawin
->s_curseq_p
) &&
206 (pLastSeqs
->rtnseq
== *dgawin
->s_rtnseq_p
)) {
209 } else if (DGA_LOCKSUBJ_VMBUFFER(dgawin
, dgawin
->eLockSubj
)) {
210 if ((pLastSeqs
->clipseq
== *dgawin
->s_clipseq_p
) &&
211 (pLastSeqs
->curseq
== *dgawin
->s_curseq_p
)) {
212 /* Note: viewable mbuf never has bstore to sync up to */
215 } else if (DGA_LOCKSUBJ_NMBUFFER(dgawin
, dgawin
->eLockSubj
)) {
216 /* Note: we don't need to check the cacheseq here, because for
217 a nonviewable drawable the cache is the only thing to sync
218 so there will never be any reason for it to be out-of-sync
223 /* we're now all synchronized */
229 ** Called at window lock time when we have detected an mbufset change.
230 ** At the return of this routine, dgawin->eLockSubj indicates the member
231 ** drawable for which subsequent changes are to be detected.
235 dgai_mbuf_mb_update (_Dga_window dgawin
)
237 /* react to enable and composition changes */
238 dgai_mbsmemb_syncMbufset(dgawin
);
240 /* if window is multibuffered we may need to synchronize */
244 infop
= (WXINFO
*) dgawin
->w_info
;
246 /* Now that we know the current mbufset composition, we know the
247 number of multibuffers. if the real lock subject is beyond
248 this, treat it as a zombie */
249 if (dgawin
->rLockSubj
!= -1 &&
250 dgawin
->rLockSubj
>= infop
->wx_dbuf
.number_buffers
) {
251 dgawin
->changeMask
|= DGA_CHANGE_ZOMBIE
;
255 /* synchronize with any display buffer change */
256 dgai_mbuf_syncLockSubj(dgawin
);
258 /* synchronize render buffer state (if necessary) */
259 dgai_mbsmemb_syncRendBuf(dgawin
);
262 /* The window is no longer multibuffered. This multibuffer is a zombie */
263 dgawin
->changeMask
|= DGA_CHANGE_ZOMBIE
;
267 /* an mbufset change causes us to report changes to all attrs */
268 { u_int reportChanges
;
269 if (DGA_LOCKSUBJ_WINDOW(dgawin
, dgawin
->eLockSubj
)) {
270 reportChanges
= DGA_WIN_CHANGEABLE_ATTRS
;
271 } else if (DGA_LOCKSUBJ_VMBUFFER(dgawin
, dgawin
->eLockSubj
)) {
272 reportChanges
= DGA_VMBUF_CHANGEABLE_ATTRS
;
274 reportChanges
= DGA_NMBUF_CHANGEABLE_ATTRS
;
276 dgawin
->changeMask
|= (DGA_CHANGE_MBUFSET
| reportChanges
);
281 ** Determine effective lock subject for a multibuffered window.
285 dgai_mbuf_syncLockSubj (_Dga_window dgawin
)
289 infop
= (WXINFO
*) dgawin
->w_info
;
291 /* see if there is buffer aliasing. Buffer aliasing
292 can only happen in copy flip mode */
293 /* TODO Daryl Is this true? In document it talks about
294 * buffer aliasing with DGA_MBFLIP_VIDEO mode. */
295 if ((infop
->w_mbsInfo
.flipMode
== DGA_MBFLIP_COPY
) &&
296 (infop
->wx_dbuf
.display_buffer
== dgawin
->rLockSubj
)) {
298 /* when the buffer is aliased, the effective lock subject is
299 always the main window */
300 dgawin
->eLockSubj
= -1;
302 if (dgawin
->eLockSubj
!= dgawin
->eLockSubjPrev
) {
304 /* an alias change causes us to report changes on all attributes */
305 dgawin
->changeMask
|= (DGA_CHANGE_ALIAS
| DGA_WIN_CHANGEABLE_ATTRS
);
313 ** In addition to the mbufset-common types of derivative changes,
314 ** we may also need to cause a clip change to be reported.
318 dgai_mbuf_figureDerivChgs (_Dga_window dgawin
)
324 dgai_mbsmemb_figureDerivChgs(dgawin
);
327 ** If we've switched from a viewable lock subject to
328 ** a nonviewable one (or vice versa) force a clip change even
329 ** if the clip of the current effective lock subject has not changed.
330 ** This is because the clips of nonviewable drawables are
331 ** always rectangular and those of viewable ones may not be.
333 curViewable
= DGA_LOCKSUBJ_VALID(dgawin
, dgawin
->eLockSubj
) &&
334 (dgawin
->eLockSubj
== -1 ||
335 DGA_MBUF_ISVIEWABLE(dgawin
->pMbs
, dgawin
->eLockSubj
));
336 prevViewable
= DGA_LOCKSUBJ_VALID(dgawin
, dgawin
->eLockSubjPrev
) &&
337 (dgawin
->eLockSubjPrev
== -1 ||
338 DGA_MBUF_ISVIEWABLE(dgawin
->pMbs
, dgawin
->eLockSubjPrev
));
340 if ((curViewable
&& !prevViewable
) ||
341 (!curViewable
&& prevViewable
)) {
342 dgawin
->changeMask
|= DGA_CHANGE_CLIP
;
348 ** Current lock subject is a viewable multibuffer. Synchronize with changes.
352 dgai_vmbuf_syncChanges (_Dga_window dgawin
, DgaLastSeqsPtr pLastSeqs
, short bufIndex
)
354 /* Note: viewable multibuffers share the clip and cursor state
355 of the main window */
357 /* clip state of main window has changed? */
358 if (pLastSeqs
->clipseq
!= *dgawin
->s_clipseq_p
) {
359 dgawin
->changeMask
|= DGA_CHANGE_CLIP
;
360 dgai_win_clip_update(dgawin
);
361 pLastSeqs
->clipseq
= *dgawin
->s_clipseq_p
;
362 dgawin
->pMbs
->clipseq
[bufIndex
] = pLastSeqs
->clipseq
;
365 /* cursor state of main window has changed? */
366 if (pLastSeqs
->curseq
!= *dgawin
->s_curseq_p
) {
367 dgawin
->changeMask
|= DGA_CHANGE_CURSOR
;
368 dgai_win_curs_update(dgawin
);
369 pLastSeqs
->curseq
= *dgawin
->s_curseq_p
;
370 dgawin
->pMbs
->curseq
[bufIndex
] = pLastSeqs
->curseq
;
373 /* Note: viewable multibuffers do not yet have backing store */
378 ** Current lock subject is a non-viewable multibuffer. Synchronize with changes.
382 dgai_nmbuf_syncChanges (_Dga_window dgawin
)
384 SHARED_PIXMAP_INFO
*infop
;
386 /* don't try to synchronize if multibuffer is a zombie */
387 if ((dgawin
->changeMask
& DGA_CHANGE_ZOMBIE
)) {
391 /* first, see if the shared info is still valid */
392 infop
= dgawin
->pMbs
->pNbShinfo
[dgawin
->eLockSubj
];
393 if (infop
->obsolete
) {
394 dgawin
->changeMask
|= DGA_CHANGE_ZOMBIE
;
398 /* Note: a non-viewable multibuffer never has a cursor
399 or backing store. And it's clip is always constant. The
400 only thing that can change is the cache or devinfo state */
402 /* Has the cache changed? */
403 dgai_nmbuf_cache_update(dgawin
);
405 /* Has the dev_info changed? */
406 dgai_nmbuf_devinfo_update(dgawin
);
411 dgai_nmbuf_cache_update (_Dga_window dgawin
)
417 s_cacheseq_p
= &(pMbs
->pNbShinfo
[dgawin
->eLockSubj
]->s_cacheseq
);
419 if (pMbs
->cacheSeqs
[dgawin
->eLockSubj
] != *s_cacheseq_p
) {
420 dgawin
->changeMask
|= DGA_CHANGE_CACHE
;
422 /* synchronize change counts */
423 pMbs
->cacheSeqs
[dgawin
->eLockSubj
] = *s_cacheseq_p
;
428 dgai_nmbuf_devinfo_update (_Dga_window dgawin
)
431 u_int
*s_devinfoseq_p
;
434 s_devinfoseq_p
= &(pMbs
->pNbShinfo
[dgawin
->eLockSubj
]->s_devinfoseq
);
436 if (pMbs
->devInfoSeqs
[dgawin
->eLockSubj
] != *s_devinfoseq_p
) {
437 dgawin
->changeMask
|= DGA_CHANGE_DEVINFO
;
439 /* synchronize change counts */
440 pMbs
->devInfoSeqs
[dgawin
->eLockSubj
] = *s_devinfoseq_p
;