1 /******************************************************************************
3 * Copyright (c) 1994, 1995 Hewlett-Packard Company
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * Except as contained in this notice, the name of the Hewlett-Packard
25 * Company shall not be used in advertising or otherwise to promote the
26 * sale, use or other dealings in this Software without prior written
27 * authorization from the Hewlett-Packard Company.
31 *****************************************************************************/
35 #ifdef HAVE_DIX_CONFIG_H
36 #include <dix-config.h>
42 #include <X11/Xproto.h>
43 #include "scrnintstr.h"
44 #include "extnsionst.h"
47 #include "dixstruct.h"
48 #define NEED_DBE_PROTOCOL
49 #include "dbestruct.h"
55 /* These are globals for use by DDX */
56 DevPrivateKeyRec dbeScreenPrivKeyRec
;
57 DevPrivateKeyRec dbeWindowPrivKeyRec
;
59 /* These are globals for use by DDX */
60 RESTYPE dbeDrawableResType
;
61 RESTYPE dbeWindowPrivResType
;
63 /* Used to generate DBE's BadBuffer error. */
64 static int dbeErrorBase
;
66 /******************************************************************************
68 * DBE DIX Procedure: DbeStubScreen
72 * This is function stubs the function pointers in the given DBE screen
73 * private and increments the number of stubbed screens.
75 *****************************************************************************/
78 DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv
, int *nStubbedScreens
)
81 pDbeScreenPriv
->SetupBackgroundPainter
= NULL
;
83 /* Do not unwrap PositionWindow nor DestroyWindow. If the DDX
84 * initialization function failed, we assume that it did not wrap
85 * PositionWindow. Also, DestroyWindow is only wrapped if the DDX
86 * initialization function succeeded.
90 pDbeScreenPriv
->GetVisualInfo
= NULL
;
91 pDbeScreenPriv
->AllocBackBufferName
= NULL
;
92 pDbeScreenPriv
->SwapBuffers
= NULL
;
93 pDbeScreenPriv
->WinPrivDelete
= NULL
;
97 } /* DbeStubScreen() */
99 /******************************************************************************
101 * DBE DIX Procedure: ProcDbeGetVersion
105 * This function is for processing a DbeGetVersion request.
106 * This request returns the major and minor version numbers of this
113 *****************************************************************************/
116 ProcDbeGetVersion(ClientPtr client
)
118 /* REQUEST(xDbeGetVersionReq); */
119 xDbeGetVersionReply rep
= {
121 .sequenceNumber
= client
->sequence
,
123 .majorVersion
= DBE_MAJOR_VERSION
,
124 .minorVersion
= DBE_MINOR_VERSION
127 REQUEST_SIZE_MATCH(xDbeGetVersionReq
);
129 if (client
->swapped
) {
130 swaps(&rep
.sequenceNumber
);
133 WriteToClient(client
, sizeof(xDbeGetVersionReply
), &rep
);
137 } /* ProcDbeGetVersion() */
139 /******************************************************************************
141 * DBE DIX Procedure: ProcDbeAllocateBackBufferName
145 * This function is for processing a DbeAllocateBackBufferName request.
146 * This request allocates a drawable ID used to refer to the back buffer
151 * BadAlloc - server can not allocate resources
152 * BadIDChoice - id is out of range for client; id is already in use
153 * BadMatch - window is not an InputOutput window;
154 * visual of window is not on list returned by
156 * BadValue - invalid swap action is specified
157 * BadWindow - window is not a valid window
160 *****************************************************************************/
163 ProcDbeAllocateBackBufferName(ClientPtr client
)
165 REQUEST(xDbeAllocateBackBufferNameReq
);
167 DbeScreenPrivPtr pDbeScreenPriv
;
168 DbeWindowPrivPtr pDbeWindowPriv
;
169 XdbeScreenVisualInfo scrVisInfo
;
171 Bool visualMatched
= FALSE
;
172 xDbeSwapAction swapAction
;
177 REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq
);
179 /* The window must be valid. */
180 status
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixManageAccess
);
181 if (status
!= Success
)
184 /* The window must be InputOutput. */
185 if (pWin
->drawable
.class != InputOutput
) {
189 /* The swap action must be valid. */
190 swapAction
= stuff
->swapAction
; /* use local var for performance. */
191 if ((swapAction
!= XdbeUndefined
) &&
192 (swapAction
!= XdbeBackground
) &&
193 (swapAction
!= XdbeUntouched
) && (swapAction
!= XdbeCopied
)) {
197 /* The id must be in range and not already in use. */
198 LEGAL_NEW_RESOURCE(stuff
->buffer
, client
);
200 /* The visual of the window must be in the list returned by
203 pDbeScreenPriv
= DBE_SCREEN_PRIV_FROM_WINDOW(pWin
);
204 if (!pDbeScreenPriv
->GetVisualInfo
)
205 return BadMatch
; /* screen doesn't support double buffering */
207 if (!(*pDbeScreenPriv
->GetVisualInfo
) (pWin
->drawable
.pScreen
, &scrVisInfo
)) {
208 /* GetVisualInfo() failed to allocate visual info data. */
212 /* See if the window's visual is on the list. */
213 visual
= wVisual(pWin
);
214 for (i
= 0; (i
< scrVisInfo
.count
) && !visualMatched
; i
++) {
215 if (scrVisInfo
.visinfo
[i
].visual
== visual
) {
216 visualMatched
= TRUE
;
220 /* Free what was allocated by the GetVisualInfo() call above. */
221 free(scrVisInfo
.visinfo
);
223 if (!visualMatched
) {
227 if ((pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
)) == NULL
) {
228 /* There is no buffer associated with the window.
229 * Allocate a window priv.
232 pDbeWindowPriv
= calloc(1, sizeof(DbeWindowPrivRec
));
236 /* Fill out window priv information. */
237 pDbeWindowPriv
->pWindow
= pWin
;
238 pDbeWindowPriv
->width
= pWin
->drawable
.width
;
239 pDbeWindowPriv
->height
= pWin
->drawable
.height
;
240 pDbeWindowPriv
->x
= pWin
->drawable
.x
;
241 pDbeWindowPriv
->y
= pWin
->drawable
.y
;
242 pDbeWindowPriv
->nBufferIDs
= 0;
244 /* Set the buffer ID array pointer to the initial (static) array). */
245 pDbeWindowPriv
->IDs
= pDbeWindowPriv
->initIDs
;
247 /* Initialize the buffer ID list. */
248 pDbeWindowPriv
->maxAvailableIDs
= DBE_INIT_MAX_IDS
;
249 pDbeWindowPriv
->IDs
[0] = stuff
->buffer
;
252 for (i
= 0; i
< DBE_INIT_MAX_IDS
; i
++) {
253 pDbeWindowPriv
->IDs
[i
] = DBE_FREE_ID_ELEMENT
;
256 /* Actually connect the window priv to the window. */
257 dixSetPrivate(&pWin
->devPrivates
, dbeWindowPrivKey
, pDbeWindowPriv
);
259 } /* if -- There is no buffer associated with the window. */
262 /* A buffer is already associated with the window.
263 * Add the new buffer ID to the array, reallocating the array memory
267 /* Determine if there is a free element in the ID array. */
268 for (i
= 0; i
< pDbeWindowPriv
->maxAvailableIDs
; i
++) {
269 if (pDbeWindowPriv
->IDs
[i
] == DBE_FREE_ID_ELEMENT
) {
270 /* There is still room in the ID array. */
275 if (i
== pDbeWindowPriv
->maxAvailableIDs
) {
276 /* No more room in the ID array -- reallocate another array. */
279 /* Setup an array pointer for the realloc operation below. */
280 if (pDbeWindowPriv
->maxAvailableIDs
== DBE_INIT_MAX_IDS
) {
281 /* We will malloc a new array. */
285 /* We will realloc a new array. */
286 pIDs
= pDbeWindowPriv
->IDs
;
289 /* malloc/realloc a new array and initialize all elements to 0. */
290 pDbeWindowPriv
->IDs
= (XID
*) realloc(pIDs
,
295 if (!pDbeWindowPriv
->IDs
) {
298 memset(&pDbeWindowPriv
->IDs
[pDbeWindowPriv
->nBufferIDs
], 0,
299 (pDbeWindowPriv
->maxAvailableIDs
+ DBE_INCR_MAX_IDS
-
300 pDbeWindowPriv
->nBufferIDs
) * sizeof(XID
));
302 if (pDbeWindowPriv
->maxAvailableIDs
== DBE_INIT_MAX_IDS
) {
303 /* We just went from using the initial (static) array to a
304 * newly allocated array. Copy the IDs from the initial array
307 memcpy(pDbeWindowPriv
->IDs
, pDbeWindowPriv
->initIDs
,
308 DBE_INIT_MAX_IDS
* sizeof(XID
));
311 pDbeWindowPriv
->maxAvailableIDs
+= DBE_INCR_MAX_IDS
;
316 } /* else -- A buffer is already associated with the window. */
318 /* Call the DDX routine to allocate the back buffer. */
319 status
= (*pDbeScreenPriv
->AllocBackBufferName
) (pWin
, stuff
->buffer
,
322 if (status
== Success
) {
323 pDbeWindowPriv
->IDs
[add_index
] = stuff
->buffer
;
324 if (!AddResource(stuff
->buffer
, dbeWindowPrivResType
,
325 (pointer
) pDbeWindowPriv
)) {
326 pDbeWindowPriv
->IDs
[add_index
] = DBE_FREE_ID_ELEMENT
;
328 if (pDbeWindowPriv
->nBufferIDs
== 0) {
335 /* The DDX buffer allocation routine failed for the first buffer of
338 if (pDbeWindowPriv
->nBufferIDs
== 0) {
343 /* Increment the number of buffers (XIDs) associated with this window. */
344 pDbeWindowPriv
->nBufferIDs
++;
346 /* Set swap action on all calls. */
347 pDbeWindowPriv
->swapAction
= stuff
->swapAction
;
352 dixSetPrivate(&pWin
->devPrivates
, dbeWindowPrivKey
, NULL
);
353 free(pDbeWindowPriv
);
356 } /* ProcDbeAllocateBackBufferName() */
358 /******************************************************************************
360 * DBE DIX Procedure: ProcDbeDeallocateBackBufferName
364 * This function is for processing a DbeDeallocateBackBufferName request.
365 * This request frees a drawable ID that was obtained by a
366 * DbeAllocateBackBufferName request.
370 * BadBuffer - buffer to deallocate is not associated with a window
373 *****************************************************************************/
376 ProcDbeDeallocateBackBufferName(ClientPtr client
)
378 REQUEST(xDbeDeallocateBackBufferNameReq
);
379 DbeWindowPrivPtr pDbeWindowPriv
;
383 REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq
);
385 /* Buffer name must be valid */
386 rc
= dixLookupResourceByType((pointer
*) &pDbeWindowPriv
, stuff
->buffer
,
387 dbeWindowPrivResType
, client
,
392 rc
= dixLookupResourceByType(&val
, stuff
->buffer
, dbeDrawableResType
,
393 client
, DixDestroyAccess
);
397 /* Make sure that the id is valid for the window.
398 * This is paranoid code since we already looked up the ID by type
402 for (i
= 0; i
< pDbeWindowPriv
->nBufferIDs
; i
++) {
403 /* Loop through the ID list to find the ID. */
404 if (pDbeWindowPriv
->IDs
[i
] == stuff
->buffer
) {
409 if (i
== pDbeWindowPriv
->nBufferIDs
) {
410 /* We did not find the ID in the ID list. */
411 client
->errorValue
= stuff
->buffer
;
412 return dbeErrorBase
+ DbeBadBuffer
;
415 FreeResource(stuff
->buffer
, RT_NONE
);
419 } /* ProcDbeDeallocateBackBufferName() */
421 /******************************************************************************
423 * DBE DIX Procedure: ProcDbeSwapBuffers
427 * This function is for processing a DbeSwapBuffers request.
428 * This request swaps the buffers for all windows listed, applying the
429 * appropriate swap action for each window.
433 * BadAlloc - local allocation failed; this return value is not defined
435 * BadMatch - a window in request is not double-buffered; a window in
436 * request is listed more than once
437 * BadValue - invalid swap action is specified; no swap action is
439 * BadWindow - a window in request is not valid
442 *****************************************************************************/
445 ProcDbeSwapBuffers(ClientPtr client
)
447 REQUEST(xDbeSwapBuffersReq
);
449 DbeScreenPrivPtr pDbeScreenPriv
;
450 DbeSwapInfoPtr swapInfo
;
451 xDbeSwapInfo
*dbeSwapInfo
;
456 REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq
);
457 nStuff
= stuff
->n
; /* use local variable for performance. */
463 if (nStuff
> UINT32_MAX
/ sizeof(DbeSwapInfoRec
))
466 /* Get to the swap info appended to the end of the request. */
467 dbeSwapInfo
= (xDbeSwapInfo
*) &stuff
[1];
469 /* Allocate array to record swap information. */
470 swapInfo
= (DbeSwapInfoPtr
) malloc(nStuff
* sizeof(DbeSwapInfoRec
));
471 if (swapInfo
== NULL
) {
475 for (i
= 0; i
< nStuff
; i
++) {
476 /* Check all windows to swap. */
478 /* Each window must be a valid window - BadWindow. */
479 error
= dixLookupWindow(&pWin
, dbeSwapInfo
[i
].window
, client
,
481 if (error
!= Success
) {
486 /* Each window must be double-buffered - BadMatch. */
487 if (DBE_WINDOW_PRIV(pWin
) == NULL
) {
492 /* Each window must only be specified once - BadMatch. */
493 for (j
= i
+ 1; j
< nStuff
; j
++) {
494 if (dbeSwapInfo
[i
].window
== dbeSwapInfo
[j
].window
) {
500 /* Each swap action must be valid - BadValue. */
501 if ((dbeSwapInfo
[i
].swapAction
!= XdbeUndefined
) &&
502 (dbeSwapInfo
[i
].swapAction
!= XdbeBackground
) &&
503 (dbeSwapInfo
[i
].swapAction
!= XdbeUntouched
) &&
504 (dbeSwapInfo
[i
].swapAction
!= XdbeCopied
)) {
509 /* Everything checks out OK. Fill in the swap info array. */
510 swapInfo
[i
].pWindow
= pWin
;
511 swapInfo
[i
].swapAction
= dbeSwapInfo
[i
].swapAction
;
513 } /* for (i = 0; i < nStuff; i++) */
515 /* Call the DDX routine to perform the swap(s). The DDX routine should
516 * scan the swap list (swap info), swap any buffers that it knows how to
517 * handle, delete them from the list, and update nStuff to indicate how
518 * many windows it did not handle.
520 * This scheme allows a range of sophistication in the DDX SwapBuffers()
521 * implementation. Naive implementations could just swap the first buffer
522 * in the list, move the last buffer to the front, decrement nStuff, and
523 * return. The next level of sophistication could be to scan the whole
524 * list for windows on the same screen. Up another level, the DDX routine
525 * could deal with cross-screen synchronization.
529 pDbeScreenPriv
= DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo
[0].pWindow
);
530 error
= (*pDbeScreenPriv
->SwapBuffers
) (client
, &nStuff
, swapInfo
);
531 if (error
!= Success
) {
540 } /* ProcDbeSwapBuffers() */
542 /******************************************************************************
544 * DBE DIX Procedure: ProcDbeGetVisualInfo
548 * This function is for processing a ProcDbeGetVisualInfo request.
549 * This request returns information about which visuals support
554 * BadDrawable - value in screen specifiers is not a valid drawable
557 *****************************************************************************/
560 ProcDbeGetVisualInfo(ClientPtr client
)
562 REQUEST(xDbeGetVisualInfoReq
);
563 DbeScreenPrivPtr pDbeScreenPriv
;
564 xDbeGetVisualInfoReply rep
;
566 DrawablePtr
*pDrawables
= NULL
;
567 register int i
, j
, rc
;
568 register int count
; /* number of visual infos in reply */
569 register int length
; /* length of reply */
571 XdbeScreenVisualInfo
*pScrVisInfo
;
573 REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq
);
575 if (stuff
->n
> UINT32_MAX
/ sizeof(DrawablePtr
))
577 /* Make sure any specified drawables are valid. */
579 if (!(pDrawables
= (DrawablePtr
*) malloc(stuff
->n
*
580 sizeof(DrawablePtr
)))) {
584 drawables
= (Drawable
*) &stuff
[1];
586 for (i
= 0; i
< stuff
->n
; i
++) {
587 rc
= dixLookupDrawable(pDrawables
+ i
, drawables
[i
], client
, 0,
596 count
= (stuff
->n
== 0) ? screenInfo
.numScreens
: stuff
->n
;
597 if (!(pScrVisInfo
= calloc(count
, sizeof(XdbeScreenVisualInfo
)))) {
605 for (i
= 0; i
< count
; i
++) {
606 pScreen
= (stuff
->n
== 0) ? screenInfo
.screens
[i
] :
607 pDrawables
[i
]->pScreen
;
608 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
610 rc
= XaceHook(XACE_SCREEN_ACCESS
, client
, pScreen
, DixGetAttrAccess
);
614 if (!(*pDbeScreenPriv
->GetVisualInfo
) (pScreen
, &pScrVisInfo
[i
])) {
615 /* We failed to alloc pScrVisInfo[i].visinfo. */
618 /* Free visinfos that we allocated for previous screen infos. */
622 /* Account for n, number of xDbeVisInfo items in list. */
623 length
+= sizeof(CARD32
);
625 /* Account for n xDbeVisInfo items */
626 length
+= pScrVisInfo
[i
].count
* sizeof(xDbeVisInfo
);
629 rep
= (xDbeGetVisualInfoReply
) {
631 .sequenceNumber
= client
->sequence
,
632 .length
= bytes_to_int32(length
),
636 if (client
->swapped
) {
637 swaps(&rep
.sequenceNumber
);
642 /* Send off reply. */
643 WriteToClient(client
, sizeof(xDbeGetVisualInfoReply
), &rep
);
645 for (i
= 0; i
< count
; i
++) {
648 /* For each screen in the reply, send off the visual info */
650 /* Send off number of visuals. */
651 data32
= (CARD32
) pScrVisInfo
[i
].count
;
653 if (client
->swapped
) {
657 WriteToClient(client
, sizeof(CARD32
), &data32
);
659 /* Now send off visual info items. */
660 for (j
= 0; j
< pScrVisInfo
[i
].count
; j
++) {
663 /* Copy the data in the client data structure to a protocol
664 * data structure. We will send data to the client from the
665 * protocol data structure.
668 visInfo
.visualID
= (CARD32
) pScrVisInfo
[i
].visinfo
[j
].visual
;
669 visInfo
.depth
= (CARD8
) pScrVisInfo
[i
].visinfo
[j
].depth
;
670 visInfo
.perfLevel
= (CARD8
) pScrVisInfo
[i
].visinfo
[j
].perflevel
;
672 if (client
->swapped
) {
673 swapl(&visInfo
.visualID
);
675 /* We do not need to swap depth and perfLevel since they are
676 * already 1 byte quantities.
680 /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */
681 WriteToClient(client
, 2 * sizeof(CARD32
), &visInfo
.visualID
);
688 /* Clean up memory. */
689 for (i
= 0; i
< count
; i
++) {
690 free(pScrVisInfo
[i
].visinfo
);
698 } /* ProcDbeGetVisualInfo() */
700 /******************************************************************************
702 * DBE DIX Procedure: ProcDbeGetbackBufferAttributes
706 * This function is for processing a ProcDbeGetbackBufferAttributes
707 * request. This request returns information about a back buffer.
713 *****************************************************************************/
716 ProcDbeGetBackBufferAttributes(ClientPtr client
)
718 REQUEST(xDbeGetBackBufferAttributesReq
);
719 xDbeGetBackBufferAttributesReply rep
= {
721 .sequenceNumber
= client
->sequence
,
724 DbeWindowPrivPtr pDbeWindowPriv
;
727 REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq
);
729 rc
= dixLookupResourceByType((pointer
*) &pDbeWindowPriv
, stuff
->buffer
,
730 dbeWindowPrivResType
, client
,
733 rep
.attributes
= pDbeWindowPriv
->pWindow
->drawable
.id
;
736 rep
.attributes
= None
;
739 if (client
->swapped
) {
740 swaps(&rep
.sequenceNumber
);
742 swapl(&rep
.attributes
);
745 WriteToClient(client
, sizeof(xDbeGetBackBufferAttributesReply
), &rep
);
748 } /* ProcDbeGetbackBufferAttributes() */
750 /******************************************************************************
752 * DBE DIX Procedure: ProcDbeDispatch
756 * This function dispatches DBE requests.
758 *****************************************************************************/
761 ProcDbeDispatch(ClientPtr client
)
765 switch (stuff
->data
) {
766 case X_DbeGetVersion
:
767 return (ProcDbeGetVersion(client
));
769 case X_DbeAllocateBackBufferName
:
770 return (ProcDbeAllocateBackBufferName(client
));
772 case X_DbeDeallocateBackBufferName
:
773 return (ProcDbeDeallocateBackBufferName(client
));
775 case X_DbeSwapBuffers
:
776 return (ProcDbeSwapBuffers(client
));
778 case X_DbeBeginIdiom
:
784 case X_DbeGetVisualInfo
:
785 return (ProcDbeGetVisualInfo(client
));
787 case X_DbeGetBackBufferAttributes
:
788 return (ProcDbeGetBackBufferAttributes(client
));
794 } /* ProcDbeDispatch() */
796 /******************************************************************************
798 * DBE DIX Procedure: SProcDbeGetVersion
802 * This function is for processing a DbeGetVersion request on a swapped
803 * server. This request returns the major and minor version numbers of
810 *****************************************************************************/
813 SProcDbeGetVersion(ClientPtr client
)
815 REQUEST(xDbeGetVersionReq
);
817 swaps(&stuff
->length
);
818 return (ProcDbeGetVersion(client
));
820 } /* SProcDbeGetVersion() */
822 /******************************************************************************
824 * DBE DIX Procedure: SProcDbeAllocateBackBufferName
828 * This function is for processing a DbeAllocateBackBufferName request on
829 * a swapped server. This request allocates a drawable ID used to refer
830 * to the back buffer of a window.
834 * BadAlloc - server can not allocate resources
835 * BadIDChoice - id is out of range for client; id is already in use
836 * BadMatch - window is not an InputOutput window;
837 * visual of window is not on list returned by
839 * BadValue - invalid swap action is specified
840 * BadWindow - window is not a valid window
843 *****************************************************************************/
846 SProcDbeAllocateBackBufferName(ClientPtr client
)
848 REQUEST(xDbeAllocateBackBufferNameReq
);
850 swaps(&stuff
->length
);
851 REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq
);
853 swapl(&stuff
->window
);
854 swapl(&stuff
->buffer
);
855 /* stuff->swapAction is a byte. We do not need to swap this field. */
857 return (ProcDbeAllocateBackBufferName(client
));
859 } /* SProcDbeAllocateBackBufferName() */
861 /******************************************************************************
863 * DBE DIX Procedure: SProcDbeDeallocateBackBufferName
867 * This function is for processing a DbeDeallocateBackBufferName request
868 * on a swapped server. This request frees a drawable ID that was
869 * obtained by a DbeAllocateBackBufferName request.
873 * BadBuffer - buffer to deallocate is not associated with a window
876 *****************************************************************************/
879 SProcDbeDeallocateBackBufferName(ClientPtr client
)
881 REQUEST(xDbeDeallocateBackBufferNameReq
);
883 swaps(&stuff
->length
);
884 REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq
);
886 swapl(&stuff
->buffer
);
888 return (ProcDbeDeallocateBackBufferName(client
));
890 } /* SProcDbeDeallocateBackBufferName() */
892 /******************************************************************************
894 * DBE DIX Procedure: SProcDbeSwapBuffers
898 * This function is for processing a DbeSwapBuffers request on a swapped
899 * server. This request swaps the buffers for all windows listed,
900 * applying the appropriate swap action for each window.
904 * BadMatch - a window in request is not double-buffered; a window in
905 * request is listed more than once; all windows in request do
906 * not have the same root
907 * BadValue - invalid swap action is specified
908 * BadWindow - a window in request is not valid
911 *****************************************************************************/
914 SProcDbeSwapBuffers(ClientPtr client
)
916 REQUEST(xDbeSwapBuffersReq
);
918 xDbeSwapInfo
*pSwapInfo
;
920 swaps(&stuff
->length
);
921 REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq
);
926 pSwapInfo
= (xDbeSwapInfo
*) stuff
+ 1;
928 /* The swap info following the fix part of this request is a window(32)
929 * followed by a 1 byte swap action and then 3 pad bytes. We only need
930 * to swap the window information.
932 for (i
= 0; i
< stuff
->n
; i
++) {
933 swapl(&pSwapInfo
->window
);
937 return (ProcDbeSwapBuffers(client
));
939 } /* SProcDbeSwapBuffers() */
941 /******************************************************************************
943 * DBE DIX Procedure: SProcDbeGetVisualInfo
947 * This function is for processing a ProcDbeGetVisualInfo request on a
948 * swapped server. This request returns information about which visuals
949 * support double buffering.
953 * BadDrawable - value in screen specifiers is not a valid drawable
956 *****************************************************************************/
959 SProcDbeGetVisualInfo(ClientPtr client
)
961 REQUEST(xDbeGetVisualInfoReq
);
963 swaps(&stuff
->length
);
964 REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq
);
969 return (ProcDbeGetVisualInfo(client
));
971 } /* SProcDbeGetVisualInfo() */
973 /******************************************************************************
975 * DBE DIX Procedure: SProcDbeGetbackBufferAttributes
979 * This function is for processing a ProcDbeGetbackBufferAttributes
980 * request on a swapped server. This request returns information about a
987 *****************************************************************************/
990 SProcDbeGetBackBufferAttributes(ClientPtr client
)
992 REQUEST(xDbeGetBackBufferAttributesReq
);
994 swaps(&stuff
->length
);
995 REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq
);
997 swapl(&stuff
->buffer
);
999 return (ProcDbeGetBackBufferAttributes(client
));
1001 } /* SProcDbeGetBackBufferAttributes() */
1003 /******************************************************************************
1005 * DBE DIX Procedure: SProcDbeDispatch
1009 * This function dispatches DBE requests on a swapped server.
1011 *****************************************************************************/
1014 SProcDbeDispatch(ClientPtr client
)
1018 switch (stuff
->data
) {
1019 case X_DbeGetVersion
:
1020 return (SProcDbeGetVersion(client
));
1022 case X_DbeAllocateBackBufferName
:
1023 return (SProcDbeAllocateBackBufferName(client
));
1025 case X_DbeDeallocateBackBufferName
:
1026 return (SProcDbeDeallocateBackBufferName(client
));
1028 case X_DbeSwapBuffers
:
1029 return (SProcDbeSwapBuffers(client
));
1031 case X_DbeBeginIdiom
:
1037 case X_DbeGetVisualInfo
:
1038 return (SProcDbeGetVisualInfo(client
));
1040 case X_DbeGetBackBufferAttributes
:
1041 return (SProcDbeGetBackBufferAttributes(client
));
1047 } /* SProcDbeDispatch() */
1049 /******************************************************************************
1051 * DBE DIX Procedure: DbeSetupBackgroundPainter
1055 * This function sets up pGC to clear pixmaps.
1059 * TRUE - setup was successful
1060 * FALSE - the window's background state is NONE
1062 *****************************************************************************/
1065 DbeSetupBackgroundPainter(WindowPtr pWin
, GCPtr pGC
)
1067 ChangeGCVal gcvalues
[4];
1068 int ts_x_origin
, ts_y_origin
;
1069 PixUnion background
;
1070 int backgroundState
;
1073 /* First take care of any ParentRelative stuff by altering the
1074 * tile/stipple origin to match the coordinates of the upper-left
1075 * corner of the first ancestor without a ParentRelative background.
1076 * This coordinate is, of course, negative.
1078 ts_x_origin
= ts_y_origin
= 0;
1079 while (pWin
->backgroundState
== ParentRelative
) {
1080 ts_x_origin
-= pWin
->origin
.x
;
1081 ts_y_origin
-= pWin
->origin
.y
;
1083 pWin
= pWin
->parent
;
1085 backgroundState
= pWin
->backgroundState
;
1086 background
= pWin
->background
;
1088 switch (backgroundState
) {
1089 case BackgroundPixel
:
1090 gcvalues
[0].val
= background
.pixel
;
1091 gcvalues
[1].val
= FillSolid
;
1092 gcmask
= GCForeground
| GCFillStyle
;
1095 case BackgroundPixmap
:
1096 gcvalues
[0].val
= FillTiled
;
1097 gcvalues
[1].ptr
= background
.pixmap
;
1098 gcvalues
[2].val
= ts_x_origin
;
1099 gcvalues
[3].val
= ts_y_origin
;
1100 gcmask
= GCFillStyle
| GCTile
| GCTileStipXOrigin
| GCTileStipYOrigin
;
1104 /* pWin->backgroundState == None */
1108 return ChangeGC(NullClient
, pGC
, gcmask
, gcvalues
) == 0;
1109 } /* DbeSetupBackgroundPainter() */
1111 /******************************************************************************
1113 * DBE DIX Procedure: DbeDrawableDelete
1117 * This is the resource delete function for dbeDrawableResType.
1118 * It is registered when the drawable resource type is created in
1119 * DbeExtensionInit().
1121 * To make resource deletion simple, we do not do anything in this function
1122 * and leave all resource deleteion to DbeWindowPrivDelete(), which will
1123 * eventually be called or already has been called. Deletion functions are
1124 * not guaranteed to be called in any particular order.
1126 *****************************************************************************/
1128 DbeDrawableDelete(pointer pDrawable
, XID id
)
1132 } /* DbeDrawableDelete() */
1134 /******************************************************************************
1136 * DBE DIX Procedure: DbeWindowPrivDelete
1140 * This is the resource delete function for dbeWindowPrivResType.
1141 * It is registered when the drawable resource type is created in
1142 * DbeExtensionInit().
1144 *****************************************************************************/
1146 DbeWindowPrivDelete(pointer pDbeWinPriv
, XID id
)
1148 DbeScreenPrivPtr pDbeScreenPriv
;
1149 DbeWindowPrivPtr pDbeWindowPriv
= (DbeWindowPrivPtr
) pDbeWinPriv
;
1153 **************************************************************************
1154 ** Remove the buffer ID from the ID array.
1155 **************************************************************************
1158 /* Find the ID in the ID array. */
1160 while ((i
< pDbeWindowPriv
->nBufferIDs
) && (pDbeWindowPriv
->IDs
[i
] != id
)) {
1164 if (i
== pDbeWindowPriv
->nBufferIDs
) {
1165 /* We did not find the ID in the array. We should never get here. */
1169 /* Remove the ID from the array. */
1171 if (i
< (pDbeWindowPriv
->nBufferIDs
- 1)) {
1172 /* Compress the buffer ID array, overwriting the ID in the process. */
1173 memmove(&pDbeWindowPriv
->IDs
[i
], &pDbeWindowPriv
->IDs
[i
+ 1],
1174 (pDbeWindowPriv
->nBufferIDs
- i
- 1) * sizeof(XID
));
1177 /* We are removing the last ID in the array, in which case, the
1178 * assignement below is all that we need to do.
1181 pDbeWindowPriv
->IDs
[pDbeWindowPriv
->nBufferIDs
- 1] = DBE_FREE_ID_ELEMENT
;
1183 pDbeWindowPriv
->nBufferIDs
--;
1185 /* If an extended array was allocated, then check to see if the remaining
1186 * buffer IDs will fit in the static array.
1189 if ((pDbeWindowPriv
->maxAvailableIDs
> DBE_INIT_MAX_IDS
) &&
1190 (pDbeWindowPriv
->nBufferIDs
== DBE_INIT_MAX_IDS
)) {
1191 /* Copy the IDs back into the static array. */
1192 memcpy(pDbeWindowPriv
->initIDs
, pDbeWindowPriv
->IDs
,
1193 DBE_INIT_MAX_IDS
* sizeof(XID
));
1195 /* Free the extended array; use the static array. */
1196 free(pDbeWindowPriv
->IDs
);
1197 pDbeWindowPriv
->IDs
= pDbeWindowPriv
->initIDs
;
1198 pDbeWindowPriv
->maxAvailableIDs
= DBE_INIT_MAX_IDS
;
1202 **************************************************************************
1203 ** Perform DDX level tasks.
1204 **************************************************************************
1207 pDbeScreenPriv
= DBE_SCREEN_PRIV_FROM_WINDOW_PRIV((DbeWindowPrivPtr
)
1209 (*pDbeScreenPriv
->WinPrivDelete
) ((DbeWindowPrivPtr
) pDbeWindowPriv
, id
);
1212 **************************************************************************
1213 ** Perform miscellaneous tasks if this is the last buffer associated
1215 **************************************************************************
1218 if (pDbeWindowPriv
->nBufferIDs
== 0) {
1219 /* Reset the DBE window priv pointer. */
1220 dixSetPrivate(&pDbeWindowPriv
->pWindow
->devPrivates
, dbeWindowPrivKey
,
1223 /* We are done with the window priv. */
1224 free(pDbeWindowPriv
);
1229 } /* DbeWindowPrivDelete() */
1231 /******************************************************************************
1233 * DBE DIX Procedure: DbeResetProc
1237 * This routine is called at the end of every server generation.
1238 * It deallocates any memory reserved for the extension and performs any
1239 * other tasks related to shutting down the extension.
1241 *****************************************************************************/
1243 DbeResetProc(ExtensionEntry
* extEntry
)
1247 DbeScreenPrivPtr pDbeScreenPriv
;
1249 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1250 pScreen
= screenInfo
.screens
[i
];
1251 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
1253 if (pDbeScreenPriv
) {
1254 /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit(). */
1255 pScreen
->DestroyWindow
= pDbeScreenPriv
->DestroyWindow
;
1256 pScreen
->PositionWindow
= pDbeScreenPriv
->PositionWindow
;
1257 free(pDbeScreenPriv
);
1260 } /* DbeResetProc() */
1262 /******************************************************************************
1264 * DBE DIX Procedure: DbeDestroyWindow
1268 * This is the wrapper for pScreen->DestroyWindow.
1269 * This function frees buffer resources for a window before it is
1272 *****************************************************************************/
1275 DbeDestroyWindow(WindowPtr pWin
)
1277 DbeScreenPrivPtr pDbeScreenPriv
;
1278 DbeWindowPrivPtr pDbeWindowPriv
;
1283 **************************************************************************
1284 ** 1. Unwrap the member routine.
1285 **************************************************************************
1288 pScreen
= pWin
->drawable
.pScreen
;
1289 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
1290 pScreen
->DestroyWindow
= pDbeScreenPriv
->DestroyWindow
;
1293 **************************************************************************
1294 ** 2. Do any work necessary before the member routine is called.
1296 ** Call the window priv delete function for all buffer IDs associated
1297 ** with this window.
1298 **************************************************************************
1301 if ((pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
))) {
1302 while (pDbeWindowPriv
) {
1303 /* *DbeWinPrivDelete() will free the window private and set it to
1304 * NULL if there are no more buffer IDs associated with this
1307 FreeResource(pDbeWindowPriv
->IDs
[0], RT_NONE
);
1308 pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
);
1313 **************************************************************************
1314 ** 3. Call the member routine, saving its result if necessary.
1315 **************************************************************************
1318 ret
= (*pScreen
->DestroyWindow
) (pWin
);
1321 **************************************************************************
1322 ** 4. Rewrap the member routine, restoring the wrapper value first in case
1323 ** the wrapper (or something that it wrapped) change this value.
1324 **************************************************************************
1327 pDbeScreenPriv
->DestroyWindow
= pScreen
->DestroyWindow
;
1328 pScreen
->DestroyWindow
= DbeDestroyWindow
;
1331 **************************************************************************
1332 ** 5. Do any work necessary after the member routine has been called.
1334 ** In this case we do not need to do anything.
1335 **************************************************************************
1340 } /* DbeDestroyWindow() */
1342 /******************************************************************************
1344 * DBE DIX Procedure: DbeExtensionInit
1348 * Called from InitExtensions in main()
1350 *****************************************************************************/
1353 DbeExtensionInit(void)
1355 ExtensionEntry
*extEntry
;
1357 ScreenPtr pScreen
= NULL
;
1358 DbeScreenPrivPtr pDbeScreenPriv
;
1359 int nStubbedScreens
= 0;
1360 Bool ddxInitSuccess
;
1363 if (!noPanoramiXExtension
)
1367 /* Create the resource types. */
1368 dbeDrawableResType
=
1369 CreateNewResourceType(DbeDrawableDelete
, "dbeDrawable");
1370 if (!dbeDrawableResType
)
1372 dbeDrawableResType
|= RC_DRAWABLE
;
1374 dbeWindowPrivResType
=
1375 CreateNewResourceType(DbeWindowPrivDelete
, "dbeWindow");
1376 if (!dbeWindowPrivResType
)
1379 if (!dixRegisterPrivateKey(&dbeScreenPrivKeyRec
, PRIVATE_SCREEN
, 0))
1382 if (!dixRegisterPrivateKey(&dbeWindowPrivKeyRec
, PRIVATE_WINDOW
, 0))
1385 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1386 /* For each screen, set up DBE screen privates and init DIX and DDX
1390 pScreen
= screenInfo
.screens
[i
];
1392 if (!(pDbeScreenPriv
= malloc(sizeof(DbeScreenPrivRec
)))) {
1393 /* If we can not alloc a window or screen private,
1394 * then free any privates that we already alloc'ed and return
1397 for (j
= 0; j
< i
; j
++) {
1398 free(dixLookupPrivate(&screenInfo
.screens
[j
]->devPrivates
,
1400 dixSetPrivate(&screenInfo
.screens
[j
]->devPrivates
,
1401 dbeScreenPrivKey
, NULL
);
1406 dixSetPrivate(&pScreen
->devPrivates
, dbeScreenPrivKey
, pDbeScreenPriv
);
1409 /* We don't have DDX support for DBE anymore */
1411 #ifndef DISABLE_MI_DBE_BY_DEFAULT
1413 pDbeScreenPriv
->SetupBackgroundPainter
= DbeSetupBackgroundPainter
;
1416 ddxInitSuccess
= miDbeInit(pScreen
, pDbeScreenPriv
);
1418 /* DDX DBE initialization may have the side affect of
1419 * reallocating pDbeScreenPriv, so we need to update it.
1421 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
1423 if (ddxInitSuccess
) {
1424 /* Wrap DestroyWindow. The DDX initialization function
1425 * already wrapped PositionWindow for us.
1428 pDbeScreenPriv
->DestroyWindow
= pScreen
->DestroyWindow
;
1429 pScreen
->DestroyWindow
= DbeDestroyWindow
;
1432 /* DDX initialization failed. Stub the screen. */
1433 DbeStubScreen(pDbeScreenPriv
, &nStubbedScreens
);
1436 DbeStubScreen(pDbeScreenPriv
, &nStubbedScreens
);
1441 } /* for (i = 0; i < screenInfo.numScreens; i++) */
1443 if (nStubbedScreens
== screenInfo
.numScreens
) {
1444 /* All screens stubbed. Clean up and return. */
1446 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1447 free(dixLookupPrivate(&screenInfo
.screens
[i
]->devPrivates
,
1449 dixSetPrivate(&pScreen
->devPrivates
, dbeScreenPrivKey
, NULL
);
1454 /* Now add the extension. */
1455 extEntry
= AddExtension(DBE_PROTOCOL_NAME
, DbeNumberEvents
,
1456 DbeNumberErrors
, ProcDbeDispatch
, SProcDbeDispatch
,
1457 DbeResetProc
, StandardMinorOpcode
);
1459 dbeErrorBase
= extEntry
->errorBase
;
1460 SetResourceTypeErrorValue(dbeWindowPrivResType
,
1461 dbeErrorBase
+ DbeBadBuffer
);
1462 SetResourceTypeErrorValue(dbeDrawableResType
, dbeErrorBase
+ DbeBadBuffer
);
1464 } /* DbeExtensionInit() */