rust/cargo-c: update to 0.10.7+cargo-0.84.0
[oi-userland.git] / components / x11 / libdga / src / mbuf_update.c
blob6739459200edf85ac42c24dc41e447dc3a81aef9
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
12 * Software.
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.
25 ** mbuf_update.c
27 ** Routines of the update phase for multibuffers.
30 #include <assert.h>
31 #ifdef SERVER_DGA
32 #include <X11/Xlib.h>
33 #endif /* SERVER_DGA */
34 #include "dga_incls.h"
35 #include "pix_grab.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.
49 ** site
50 ** clip
51 ** curs
52 ** bstore
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
68 int
69 dgai_mbuf_update (_Dga_window dgawin, short bufIndex)
71 DgaLastSeqs lastSeqs;
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
91 ** process over.
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 */
102 do {
104 /* first, see if the window shared info is still valid */
105 if (dgai_mbsmemb_syncZombie(dgawin)) {
106 break;
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);
127 } else {
128 /* should never happen */
129 assert(0);
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,
148 ** if possible.
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
160 shared info */
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);
172 static void
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;
182 } else {
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
195 static int
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) {
200 return (1);
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)) {
207 return (0);
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 */
213 return (0);
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
219 when we get here */
220 return (0);
223 /* we're now all synchronized */
224 return (1);
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.
234 static void
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 */
241 if (dgawin->pMbs) {
242 WXINFO *infop;
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;
252 return;
255 /* synchronize with any display buffer change */
256 dgai_mbuf_syncLockSubj(dgawin);
258 /* synchronize render buffer state (if necessary) */
259 dgai_mbsmemb_syncRendBuf(dgawin);
261 } else {
262 /* The window is no longer multibuffered. This multibuffer is a zombie */
263 dgawin->changeMask |= DGA_CHANGE_ZOMBIE;
264 return;
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;
273 } else {
274 reportChanges = DGA_NMBUF_CHANGEABLE_ATTRS;
276 dgawin->changeMask |= (DGA_CHANGE_MBUFSET | reportChanges);
281 ** Determine effective lock subject for a multibuffered window.
284 static void
285 dgai_mbuf_syncLockSubj (_Dga_window dgawin)
287 WXINFO *infop;
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.
317 static void
318 dgai_mbuf_figureDerivChgs (_Dga_window dgawin)
320 int curViewable;
321 int prevViewable;
323 /* common changes */
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.
351 void
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.
381 void
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)) {
388 return;
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;
395 return;
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);
410 void
411 dgai_nmbuf_cache_update (_Dga_window dgawin)
413 DgaMbufSetPtr pMbs;
414 u_int *s_cacheseq_p;
416 pMbs = dgawin->pMbs;
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;
427 void
428 dgai_nmbuf_devinfo_update (_Dga_window dgawin)
430 DgaMbufSetPtr pMbs;
431 u_int *s_devinfoseq_p;
433 pMbs = dgawin->pMbs;
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;