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.
29 * Machine-independent DBE code
31 *****************************************************************************/
35 #ifdef HAVE_DIX_CONFIG_H
36 #include <dix-config.h>
40 #include <X11/Xproto.h>
43 #include "windowstr.h"
44 #include "scrnintstr.h"
45 #include "pixmapstr.h"
46 #include "extnsionst.h"
47 #include "dixstruct.h"
50 #include "dbestruct.h"
52 #include "regionstr.h"
60 static DevPrivateKeyRec miDbeWindowPrivPrivKeyRec
;
62 #define miDbeWindowPrivPrivKey (&miDbeWindowPrivPrivKeyRec)
64 /******************************************************************************
66 * DBE MI Procedure: miDbeGetVisualInfo
70 * This is the MI function for the DbeGetVisualInfo request. This function
71 * is called through pDbeScreenPriv->GetVisualInfo. This function is also
72 * called for the DbeAllocateBackBufferName request at the extension level;
73 * it is called by ProcDbeAllocateBackBufferName() in dbe.c.
75 * If memory allocation fails or we can not get the visual info, this
76 * function returns FALSE. Otherwise, it returns TRUE for success.
78 *****************************************************************************/
81 miDbeGetVisualInfo(ScreenPtr pScreen
, XdbeScreenVisualInfo
* pScrVisInfo
)
86 XdbeVisualInfo
*visInfo
;
88 /* Determine number of visuals for this screen. */
89 for (i
= 0, count
= 0; i
< pScreen
->numDepths
; i
++) {
90 count
+= pScreen
->allowedDepths
[i
].numVids
;
93 /* Allocate an array of XdbeVisualInfo items. */
94 if (!(visInfo
= (XdbeVisualInfo
*) malloc(count
* sizeof(XdbeVisualInfo
)))) {
95 return FALSE
; /* memory alloc failure */
98 for (i
= 0, k
= 0; i
< pScreen
->numDepths
; i
++) {
99 /* For each depth of this screen, get visual information. */
101 pDepth
= &pScreen
->allowedDepths
[i
];
103 for (j
= 0; j
< pDepth
->numVids
; j
++) {
104 /* For each visual for this depth of this screen, get visual ID
105 * and visual depth. Since this is MI code, we will always return
106 * the same performance level for all visuals (0). A higher
107 * performance level value indicates higher performance.
109 visInfo
[k
].visual
= pDepth
->vids
[j
];
110 visInfo
[k
].depth
= pDepth
->depth
;
111 visInfo
[k
].perflevel
= 0;
116 /* Record the number of visuals and point visual_depth to
117 * the array of visual info.
119 pScrVisInfo
->count
= count
;
120 pScrVisInfo
->visinfo
= visInfo
;
122 return TRUE
; /* success */
124 } /* miDbeGetVisualInfo() */
126 /******************************************************************************
128 * DBE MI Procedure: miAllocBackBufferName
132 * This is the MI function for the DbeAllocateBackBufferName request.
134 *****************************************************************************/
137 miDbeAllocBackBufferName(WindowPtr pWin
, XID bufId
, int swapAction
)
140 DbeWindowPrivPtr pDbeWindowPriv
;
141 MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv
;
142 DbeScreenPrivPtr pDbeScreenPriv
;
144 xRectangle clearRect
;
147 pScreen
= pWin
->drawable
.pScreen
;
148 pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
);
150 if (pDbeWindowPriv
->nBufferIDs
== 0) {
151 /* There is no buffer associated with the window.
152 * We have to create the window priv priv. Remember, the window
153 * priv was created at the DIX level, so all we need to do is
154 * create the priv priv and attach it to the priv.
157 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
159 /* Setup the window priv priv. */
160 pDbeWindowPrivPriv
= MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv
);
161 pDbeWindowPrivPriv
->pDbeWindowPriv
= pDbeWindowPriv
;
163 /* Get a front pixmap. */
164 if (!(pDbeWindowPrivPriv
->pFrontBuffer
=
165 (*pScreen
->CreatePixmap
) (pScreen
, pDbeWindowPriv
->width
,
166 pDbeWindowPriv
->height
,
167 pWin
->drawable
.depth
, 0))) {
171 /* Get a back pixmap. */
172 if (!(pDbeWindowPrivPriv
->pBackBuffer
=
173 (*pScreen
->CreatePixmap
) (pScreen
, pDbeWindowPriv
->width
,
174 pDbeWindowPriv
->height
,
175 pWin
->drawable
.depth
, 0))) {
176 (*pScreen
->DestroyPixmap
) (pDbeWindowPrivPriv
->pFrontBuffer
);
180 /* Security creation/labeling check. */
181 rc
= XaceHook(XACE_RESOURCE_ACCESS
, serverClient
, bufId
,
182 dbeDrawableResType
, pDbeWindowPrivPriv
->pBackBuffer
,
183 RT_WINDOW
, pWin
, DixCreateAccess
);
185 /* Make the back pixmap a DBE drawable resource. */
186 if (rc
!= Success
|| !AddResource(bufId
, dbeDrawableResType
,
187 pDbeWindowPrivPriv
->pBackBuffer
)) {
188 /* free the buffer and the drawable resource */
189 FreeResource(bufId
, RT_NONE
);
190 return (rc
== Success
) ? BadAlloc
: rc
;
193 /* Clear the back buffer. */
194 pGC
= GetScratchGC(pWin
->drawable
.depth
, pWin
->drawable
.pScreen
);
195 if ((*pDbeScreenPriv
->SetupBackgroundPainter
) (pWin
, pGC
)) {
196 ValidateGC((DrawablePtr
) pDbeWindowPrivPriv
->pBackBuffer
, pGC
);
197 clearRect
.x
= clearRect
.y
= 0;
198 clearRect
.width
= pDbeWindowPrivPriv
->pBackBuffer
->drawable
.width
;
199 clearRect
.height
= pDbeWindowPrivPriv
->pBackBuffer
->drawable
.height
;
200 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
) pDbeWindowPrivPriv
->
201 pBackBuffer
, pGC
, 1, &clearRect
);
205 } /* if no buffer associated with the window */
208 /* A buffer is already associated with the window.
209 * Place the new buffer ID information at the head of the ID list.
212 /* Associate the new ID with an existing pixmap. */
213 pDbeWindowPrivPriv
= MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv
);
214 if (!AddResource(bufId
, dbeDrawableResType
,
215 (pointer
) pDbeWindowPrivPriv
->pBackBuffer
)) {
223 } /* miDbeAllocBackBufferName() */
225 /******************************************************************************
227 * DBE MI Procedure: miDbeAliasBuffers
231 * This function associates all XIDs of a buffer with the back pixmap
232 * stored in the window priv.
234 *****************************************************************************/
237 miDbeAliasBuffers(DbeWindowPrivPtr pDbeWindowPriv
)
240 MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv
=
241 MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv
);
243 for (i
= 0; i
< pDbeWindowPriv
->nBufferIDs
; i
++) {
244 ChangeResourceValue(pDbeWindowPriv
->IDs
[i
], dbeDrawableResType
,
245 (pointer
) pDbeWindowPrivPriv
->pBackBuffer
);
248 } /* miDbeAliasBuffers() */
250 /******************************************************************************
252 * DBE MI Procedure: miDbeSwapBuffers
256 * This is the MI function for the DbeSwapBuffers request.
258 *****************************************************************************/
261 miDbeSwapBuffers(ClientPtr client
, int *pNumWindows
, DbeSwapInfoPtr swapInfo
)
263 DbeScreenPrivPtr pDbeScreenPriv
;
266 MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv
;
267 PixmapPtr pTmpBuffer
;
268 xRectangle clearRect
;
270 pWin
= swapInfo
[0].pWindow
;
271 pDbeScreenPriv
= DBE_SCREEN_PRIV_FROM_WINDOW(pWin
);
272 pDbeWindowPrivPriv
= MI_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin
);
273 pGC
= GetScratchGC(pWin
->drawable
.depth
, pWin
->drawable
.pScreen
);
276 **********************************************************************
277 ** Setup before swap.
278 **********************************************************************
281 switch (swapInfo
[0].swapAction
) {
289 ValidateGC((DrawablePtr
) pDbeWindowPrivPriv
->pFrontBuffer
, pGC
);
290 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pWin
,
291 (DrawablePtr
) pDbeWindowPrivPriv
->pFrontBuffer
,
292 pGC
, 0, 0, pWin
->drawable
.width
,
293 pWin
->drawable
.height
, 0, 0);
302 **********************************************************************
304 **********************************************************************
307 ValidateGC((DrawablePtr
) pWin
, pGC
);
308 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pDbeWindowPrivPriv
->pBackBuffer
,
309 (DrawablePtr
) pWin
, pGC
, 0, 0,
310 pWin
->drawable
.width
, pWin
->drawable
.height
, 0, 0);
313 **********************************************************************
315 **********************************************************************
318 switch (swapInfo
[0].swapAction
) {
323 if ((*pDbeScreenPriv
->SetupBackgroundPainter
) (pWin
, pGC
)) {
324 ValidateGC((DrawablePtr
) pDbeWindowPrivPriv
->pBackBuffer
, pGC
);
327 clearRect
.width
= pDbeWindowPrivPriv
->pBackBuffer
->drawable
.width
;
328 clearRect
.height
= pDbeWindowPrivPriv
->pBackBuffer
->drawable
.height
;
329 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
) pDbeWindowPrivPriv
->
330 pBackBuffer
, pGC
, 1, &clearRect
);
335 /* Swap pixmap pointers. */
336 pTmpBuffer
= pDbeWindowPrivPriv
->pBackBuffer
;
337 pDbeWindowPrivPriv
->pBackBuffer
= pDbeWindowPrivPriv
->pFrontBuffer
;
338 pDbeWindowPrivPriv
->pFrontBuffer
= pTmpBuffer
;
340 miDbeAliasBuffers(pDbeWindowPrivPriv
->pDbeWindowPriv
);
349 /* Remove the swapped window from the swap information array and decrement
350 * pNumWindows to indicate to the DIX level how many windows were actually
354 if (*pNumWindows
> 1) {
355 /* We were told to swap more than one window, but we only swapped the
356 * first one. Remove the first window in the list by moving the last
357 * window to the beginning.
359 swapInfo
[0].pWindow
= swapInfo
[*pNumWindows
- 1].pWindow
;
360 swapInfo
[0].swapAction
= swapInfo
[*pNumWindows
- 1].swapAction
;
362 /* Clear the last window information just to be safe. */
363 swapInfo
[*pNumWindows
- 1].pWindow
= (WindowPtr
) NULL
;
364 swapInfo
[*pNumWindows
- 1].swapAction
= 0;
367 /* Clear the window information just to be safe. */
368 swapInfo
[0].pWindow
= (WindowPtr
) NULL
;
369 swapInfo
[0].swapAction
= 0;
378 } /* miSwapBuffers() */
380 /******************************************************************************
382 * DBE MI Procedure: miDbeWinPrivDelete
386 * This is the MI function for deleting the dbeWindowPrivResType resource.
387 * This function is invoked indirectly by calling FreeResource() to free
388 * the resources associated with a DBE buffer ID. There are 5 ways that
389 * miDbeWinPrivDelete() can be called by FreeResource(). They are:
391 * - A DBE window is destroyed, in which case the DbeDestroyWindow()
392 * wrapper is invoked. The wrapper calls FreeResource() for all DBE
395 * - miDbeAllocBackBufferName() calls FreeResource() to clean up resources
396 * after a buffer allocation failure.
398 * - The PositionWindow wrapper, miDbePositionWindow(), calls
399 * FreeResource() when it fails to create buffers of the new size.
400 * FreeResource() is called for all DBE buffer IDs.
402 * - FreeClientResources() calls FreeResource() when a client dies or the
405 * When FreeResource() is called for a DBE buffer ID, the delete function
406 * for the only other type of DBE resource, dbeDrawableResType, is also
407 * invoked. This delete function (DbeDrawableDelete) is a NOOP to make
408 * resource deletion easier. It is not guaranteed which delete function is
409 * called first. Hence, we will let miDbeWinPrivDelete() free all DBE
412 * This function deletes/frees the following stuff associated with
413 * the window private:
415 * - the ID node in the ID list representing the passed in ID.
417 * In addition, pDbeWindowPriv->nBufferIDs is decremented.
419 * If this function is called for the last/only buffer ID for a window,
420 * these are additionally deleted/freed:
422 * - the front and back pixmaps
423 * - the window priv itself
425 *****************************************************************************/
428 miDbeWinPrivDelete(DbeWindowPrivPtr pDbeWindowPriv
, XID bufId
)
430 MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv
;
432 if (pDbeWindowPriv
->nBufferIDs
!= 0) {
433 /* We still have at least one more buffer ID associated with this
439 /* We have no more buffer IDs associated with this window. We need to
443 pDbeWindowPrivPriv
= MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv
);
445 /* Destroy the front and back pixmaps. */
446 if (pDbeWindowPrivPriv
->pFrontBuffer
) {
447 (*pDbeWindowPriv
->pWindow
->drawable
.pScreen
->
448 DestroyPixmap
) (pDbeWindowPrivPriv
->pFrontBuffer
);
450 if (pDbeWindowPrivPriv
->pBackBuffer
) {
451 (*pDbeWindowPriv
->pWindow
->drawable
.pScreen
->
452 DestroyPixmap
) (pDbeWindowPrivPriv
->pBackBuffer
);
455 } /* miDbeWinPrivDelete() */
457 /******************************************************************************
459 * DBE MI Procedure: miDbePositionWindow
463 * This function was cloned from miMbxPositionWindow() in mimultibuf.c.
464 * This function resizes the buffer when the window is resized.
466 *****************************************************************************/
469 miDbePositionWindow(WindowPtr pWin
, int x
, int y
)
472 DbeScreenPrivPtr pDbeScreenPriv
;
473 DbeWindowPrivPtr pDbeWindowPriv
;
476 int sourcex
, sourcey
;
478 int savewidth
, saveheight
;
479 PixmapPtr pFrontBuffer
;
480 PixmapPtr pBackBuffer
;
483 xRectangle clearRect
;
487 **************************************************************************
488 ** 1. Unwrap the member routine.
489 **************************************************************************
492 pScreen
= pWin
->drawable
.pScreen
;
493 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
494 pScreen
->PositionWindow
= pDbeScreenPriv
->PositionWindow
;
497 **************************************************************************
498 ** 2. Do any work necessary before the member routine is called.
500 ** In this case we do not need to do anything.
501 **************************************************************************
505 **************************************************************************
506 ** 3. Call the member routine, saving its result if necessary.
507 **************************************************************************
510 ret
= (*pScreen
->PositionWindow
) (pWin
, x
, y
);
513 **************************************************************************
514 ** 4. Rewrap the member routine, restoring the wrapper value first in case
515 ** the wrapper (or something that it wrapped) change this value.
516 **************************************************************************
519 pDbeScreenPriv
->PositionWindow
= pScreen
->PositionWindow
;
520 pScreen
->PositionWindow
= miDbePositionWindow
;
523 **************************************************************************
524 ** 5. Do any work necessary after the member routine has been called.
525 **************************************************************************
528 if (!(pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
))) {
532 if (pDbeWindowPriv
->width
== pWin
->drawable
.width
&&
533 pDbeWindowPriv
->height
== pWin
->drawable
.height
) {
537 width
= pWin
->drawable
.width
;
538 height
= pWin
->drawable
.height
;
540 dx
= pWin
->drawable
.x
- pDbeWindowPriv
->x
;
541 dy
= pWin
->drawable
.y
- pDbeWindowPriv
->y
;
542 dw
= width
- pDbeWindowPriv
->width
;
543 dh
= height
- pDbeWindowPriv
->height
;
545 GravityTranslate(0, 0, -dx
, -dy
, dw
, dh
, pWin
->bitGravity
, &destx
, &desty
);
547 clear
= ((pDbeWindowPriv
->width
< (unsigned short) width
) ||
548 (pDbeWindowPriv
->height
< (unsigned short) height
) ||
549 (pWin
->bitGravity
== ForgetGravity
));
553 savewidth
= pDbeWindowPriv
->width
;
554 saveheight
= pDbeWindowPriv
->height
;
556 /* Clip rectangle to source and destination. */
563 if (destx
+ savewidth
> width
) {
564 savewidth
= width
- destx
;
573 if (desty
+ saveheight
> height
) {
574 saveheight
= height
- desty
;
577 pDbeWindowPriv
->width
= width
;
578 pDbeWindowPriv
->height
= height
;
579 pDbeWindowPriv
->x
= pWin
->drawable
.x
;
580 pDbeWindowPriv
->y
= pWin
->drawable
.y
;
582 pGC
= GetScratchGC(pWin
->drawable
.depth
, pScreen
);
585 if ((*pDbeScreenPriv
->SetupBackgroundPainter
) (pWin
, pGC
)) {
588 clearRect
.width
= width
;
589 clearRect
.height
= height
;
596 /* Create DBE buffer pixmaps equal to size of resized window. */
597 pFrontBuffer
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
,
598 pWin
->drawable
.depth
, 0);
600 pBackBuffer
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
,
601 pWin
->drawable
.depth
, 0);
603 if (!pFrontBuffer
|| !pBackBuffer
) {
604 /* We failed at creating 1 or 2 of the pixmaps. */
607 (*pScreen
->DestroyPixmap
) (pFrontBuffer
);
611 (*pScreen
->DestroyPixmap
) (pBackBuffer
);
614 /* Destroy all buffers for this window. */
615 while (pDbeWindowPriv
) {
616 /* DbeWindowPrivDelete() will free the window private if there no
617 * more buffer IDs associated with this window.
619 FreeResource(pDbeWindowPriv
->IDs
[0], RT_NONE
);
620 pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
);
628 /* Clear out the new DBE buffer pixmaps. */
630 MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv
;
632 pDbeWindowPrivPriv
= MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv
);
634 /* I suppose this could avoid quite a bit of work if
635 * it computed the minimal area required.
637 ValidateGC(&pFrontBuffer
->drawable
, pGC
);
639 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
) pFrontBuffer
, pGC
, 1,
642 /* Copy the contents of the old front pixmap to the new one. */
643 if (pWin
->bitGravity
!= ForgetGravity
) {
644 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pDbeWindowPrivPriv
->
645 pFrontBuffer
, (DrawablePtr
) pFrontBuffer
,
646 pGC
, sourcex
, sourcey
, savewidth
, saveheight
,
650 ValidateGC(&pBackBuffer
->drawable
, pGC
);
652 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
) pBackBuffer
, pGC
, 1,
655 /* Copy the contents of the old back pixmap to the new one. */
656 if (pWin
->bitGravity
!= ForgetGravity
) {
657 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pDbeWindowPrivPriv
->
658 pBackBuffer
, (DrawablePtr
) pBackBuffer
, pGC
,
659 sourcex
, sourcey
, savewidth
, saveheight
,
663 /* Destroy the old pixmaps, and point the DBE window priv to the new
667 (*pScreen
->DestroyPixmap
) (pDbeWindowPrivPriv
->pFrontBuffer
);
668 (*pScreen
->DestroyPixmap
) (pDbeWindowPrivPriv
->pBackBuffer
);
670 pDbeWindowPrivPriv
->pFrontBuffer
= pFrontBuffer
;
671 pDbeWindowPrivPriv
->pBackBuffer
= pBackBuffer
;
673 /* Make sure all XID are associated with the new back pixmap. */
674 miDbeAliasBuffers(pDbeWindowPriv
);
681 } /* miDbePositionWindow() */
683 /******************************************************************************
685 * DBE MI Procedure: miDbeResetProc
689 * This function is called from DbeResetProc(), which is called at the end
690 * of every server generation. This function peforms any MI-specific
693 *****************************************************************************/
696 miDbeResetProc(ScreenPtr pScreen
)
698 DbeScreenPrivPtr pDbeScreenPriv
;
700 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
702 /* Unwrap wrappers */
703 pScreen
->PositionWindow
= pDbeScreenPriv
->PositionWindow
;
705 } /* miDbeResetProc() */
707 /******************************************************************************
709 * DBE MI Procedure: miDbeInit
713 * This is the MI initialization function called by DbeExtensionInit().
715 *****************************************************************************/
718 miDbeInit(ScreenPtr pScreen
, DbeScreenPrivPtr pDbeScreenPriv
)
720 if (!dixRegisterPrivateKey(&miDbeWindowPrivPrivKeyRec
, PRIVATE_DBE_WINDOW
,
721 sizeof(MiDbeWindowPrivPrivRec
)))
724 /* Wrap functions. */
725 pDbeScreenPriv
->PositionWindow
= pScreen
->PositionWindow
;
726 pScreen
->PositionWindow
= miDbePositionWindow
;
728 /* Initialize the per-screen DBE function pointers. */
729 pDbeScreenPriv
->GetVisualInfo
= miDbeGetVisualInfo
;
730 pDbeScreenPriv
->AllocBackBufferName
= miDbeAllocBackBufferName
;
731 pDbeScreenPriv
->SwapBuffers
= miDbeSwapBuffers
;
732 pDbeScreenPriv
->BeginIdiom
= 0;
733 pDbeScreenPriv
->EndIdiom
= 0;
734 pDbeScreenPriv
->ResetProc
= miDbeResetProc
;
735 pDbeScreenPriv
->WinPrivDelete
= miDbeWinPrivDelete
;