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"
51 #include "regionstr.h"
60 /******************************************************************************
62 * DBE MI Procedure: miDbeGetVisualInfo
66 * This is the MI function for the DbeGetVisualInfo request. This function
67 * is called through pDbeScreenPriv->GetVisualInfo. This function is also
68 * called for the DbeAllocateBackBufferName request at the extension level;
69 * it is called by ProcDbeAllocateBackBufferName() in dbe.c.
71 * If memory allocation fails or we can not get the visual info, this
72 * function returns FALSE. Otherwise, it returns TRUE for success.
74 *****************************************************************************/
77 miDbeGetVisualInfo(ScreenPtr pScreen
, XdbeScreenVisualInfo
* pScrVisInfo
)
82 XdbeVisualInfo
*visInfo
;
84 /* Determine number of visuals for this screen. */
85 for (i
= 0, count
= 0; i
< pScreen
->numDepths
; i
++) {
86 count
+= pScreen
->allowedDepths
[i
].numVids
;
89 /* Allocate an array of XdbeVisualInfo items. */
90 if (!(visInfo
= (XdbeVisualInfo
*) malloc(count
* sizeof(XdbeVisualInfo
)))) {
91 return FALSE
; /* memory alloc failure */
94 for (i
= 0, k
= 0; i
< pScreen
->numDepths
; i
++) {
95 /* For each depth of this screen, get visual information. */
97 pDepth
= &pScreen
->allowedDepths
[i
];
99 for (j
= 0; j
< pDepth
->numVids
; j
++) {
100 /* For each visual for this depth of this screen, get visual ID
101 * and visual depth. Since this is MI code, we will always return
102 * the same performance level for all visuals (0). A higher
103 * performance level value indicates higher performance.
105 visInfo
[k
].visual
= pDepth
->vids
[j
];
106 visInfo
[k
].depth
= pDepth
->depth
;
107 visInfo
[k
].perflevel
= 0;
112 /* Record the number of visuals and point visual_depth to
113 * the array of visual info.
115 pScrVisInfo
->count
= count
;
116 pScrVisInfo
->visinfo
= visInfo
;
118 return TRUE
; /* success */
120 } /* miDbeGetVisualInfo() */
122 /******************************************************************************
124 * DBE MI Procedure: miAllocBackBufferName
128 * This is the MI function for the DbeAllocateBackBufferName request.
130 *****************************************************************************/
133 miDbeAllocBackBufferName(WindowPtr pWin
, XID bufId
, int swapAction
)
136 DbeWindowPrivPtr pDbeWindowPriv
;
137 DbeScreenPrivPtr pDbeScreenPriv
;
139 xRectangle clearRect
;
142 pScreen
= pWin
->drawable
.pScreen
;
143 pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
);
145 if (pDbeWindowPriv
->nBufferIDs
== 0) {
146 /* There is no buffer associated with the window.
147 * We have to create the window priv priv. Remember, the window
148 * priv was created at the DIX level, so all we need to do is
149 * create the priv priv and attach it to the priv.
152 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
154 /* Get a front pixmap. */
155 if (!(pDbeWindowPriv
->pFrontBuffer
=
156 (*pScreen
->CreatePixmap
) (pScreen
, pDbeWindowPriv
->width
,
157 pDbeWindowPriv
->height
,
158 pWin
->drawable
.depth
, 0))) {
162 /* Get a back pixmap. */
163 if (!(pDbeWindowPriv
->pBackBuffer
=
164 (*pScreen
->CreatePixmap
) (pScreen
, pDbeWindowPriv
->width
,
165 pDbeWindowPriv
->height
,
166 pWin
->drawable
.depth
, 0))) {
167 (*pScreen
->DestroyPixmap
) (pDbeWindowPriv
->pFrontBuffer
);
171 /* Security creation/labeling check. */
172 rc
= XaceHook(XACE_RESOURCE_ACCESS
, serverClient
, bufId
,
173 dbeDrawableResType
, pDbeWindowPriv
->pBackBuffer
,
174 RT_WINDOW
, pWin
, DixCreateAccess
);
176 /* Make the back pixmap a DBE drawable resource. */
177 if (rc
!= Success
|| !AddResource(bufId
, dbeDrawableResType
,
178 pDbeWindowPriv
->pBackBuffer
)) {
179 /* free the buffer and the drawable resource */
180 FreeResource(bufId
, RT_NONE
);
181 return (rc
== Success
) ? BadAlloc
: rc
;
184 /* Clear the back buffer. */
185 pGC
= GetScratchGC(pWin
->drawable
.depth
, pWin
->drawable
.pScreen
);
186 if ((*pDbeScreenPriv
->SetupBackgroundPainter
) (pWin
, pGC
)) {
187 ValidateGC((DrawablePtr
) pDbeWindowPriv
->pBackBuffer
, pGC
);
188 clearRect
.x
= clearRect
.y
= 0;
189 clearRect
.width
= pDbeWindowPriv
->pBackBuffer
->drawable
.width
;
190 clearRect
.height
= pDbeWindowPriv
->pBackBuffer
->drawable
.height
;
191 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
) pDbeWindowPriv
->
192 pBackBuffer
, pGC
, 1, &clearRect
);
196 } /* if no buffer associated with the window */
199 /* A buffer is already associated with the window.
200 * Place the new buffer ID information at the head of the ID list.
203 /* Associate the new ID with an existing pixmap. */
204 if (!AddResource(bufId
, dbeDrawableResType
,
205 (pointer
) pDbeWindowPriv
->pBackBuffer
)) {
213 } /* miDbeAllocBackBufferName() */
215 /******************************************************************************
217 * DBE MI Procedure: miDbeAliasBuffers
221 * This function associates all XIDs of a buffer with the back pixmap
222 * stored in the window priv.
224 *****************************************************************************/
227 miDbeAliasBuffers(DbeWindowPrivPtr pDbeWindowPriv
)
231 for (i
= 0; i
< pDbeWindowPriv
->nBufferIDs
; i
++) {
232 ChangeResourceValue(pDbeWindowPriv
->IDs
[i
], dbeDrawableResType
,
233 (pointer
) pDbeWindowPriv
->pBackBuffer
);
236 } /* miDbeAliasBuffers() */
238 /******************************************************************************
240 * DBE MI Procedure: miDbeSwapBuffers
244 * This is the MI function for the DbeSwapBuffers request.
246 *****************************************************************************/
249 miDbeSwapBuffers(ClientPtr client
, int *pNumWindows
, DbeSwapInfoPtr swapInfo
)
251 DbeScreenPrivPtr pDbeScreenPriv
;
252 DbeWindowPrivPtr pDbeWindowPriv
;
255 PixmapPtr pTmpBuffer
;
256 xRectangle clearRect
;
258 pWin
= swapInfo
[0].pWindow
;
259 pDbeScreenPriv
= DBE_SCREEN_PRIV_FROM_WINDOW(pWin
);
260 pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
);
261 pGC
= GetScratchGC(pWin
->drawable
.depth
, pWin
->drawable
.pScreen
);
264 **********************************************************************
265 ** Setup before swap.
266 **********************************************************************
269 switch (swapInfo
[0].swapAction
) {
277 ValidateGC((DrawablePtr
) pDbeWindowPriv
->pFrontBuffer
, pGC
);
278 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pWin
,
279 (DrawablePtr
) pDbeWindowPriv
->pFrontBuffer
,
280 pGC
, 0, 0, pWin
->drawable
.width
,
281 pWin
->drawable
.height
, 0, 0);
290 **********************************************************************
292 **********************************************************************
295 ValidateGC((DrawablePtr
) pWin
, pGC
);
296 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pDbeWindowPriv
->pBackBuffer
,
297 (DrawablePtr
) pWin
, pGC
, 0, 0,
298 pWin
->drawable
.width
, pWin
->drawable
.height
, 0, 0);
301 **********************************************************************
303 **********************************************************************
306 switch (swapInfo
[0].swapAction
) {
311 if ((*pDbeScreenPriv
->SetupBackgroundPainter
) (pWin
, pGC
)) {
312 ValidateGC((DrawablePtr
) pDbeWindowPriv
->pBackBuffer
, pGC
);
315 clearRect
.width
= pDbeWindowPriv
->pBackBuffer
->drawable
.width
;
316 clearRect
.height
= pDbeWindowPriv
->pBackBuffer
->drawable
.height
;
317 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
) pDbeWindowPriv
->
318 pBackBuffer
, pGC
, 1, &clearRect
);
323 /* Swap pixmap pointers. */
324 pTmpBuffer
= pDbeWindowPriv
->pBackBuffer
;
325 pDbeWindowPriv
->pBackBuffer
= pDbeWindowPriv
->pFrontBuffer
;
326 pDbeWindowPriv
->pFrontBuffer
= pTmpBuffer
;
328 miDbeAliasBuffers(pDbeWindowPriv
);
337 /* Remove the swapped window from the swap information array and decrement
338 * pNumWindows to indicate to the DIX level how many windows were actually
342 if (*pNumWindows
> 1) {
343 /* We were told to swap more than one window, but we only swapped the
344 * first one. Remove the first window in the list by moving the last
345 * window to the beginning.
347 swapInfo
[0].pWindow
= swapInfo
[*pNumWindows
- 1].pWindow
;
348 swapInfo
[0].swapAction
= swapInfo
[*pNumWindows
- 1].swapAction
;
350 /* Clear the last window information just to be safe. */
351 swapInfo
[*pNumWindows
- 1].pWindow
= (WindowPtr
) NULL
;
352 swapInfo
[*pNumWindows
- 1].swapAction
= 0;
355 /* Clear the window information just to be safe. */
356 swapInfo
[0].pWindow
= (WindowPtr
) NULL
;
357 swapInfo
[0].swapAction
= 0;
366 } /* miSwapBuffers() */
368 /******************************************************************************
370 * DBE MI Procedure: miDbeWinPrivDelete
374 * This is the MI function for deleting the dbeWindowPrivResType resource.
375 * This function is invoked indirectly by calling FreeResource() to free
376 * the resources associated with a DBE buffer ID. There are 5 ways that
377 * miDbeWinPrivDelete() can be called by FreeResource(). They are:
379 * - A DBE window is destroyed, in which case the DbeDestroyWindow()
380 * wrapper is invoked. The wrapper calls FreeResource() for all DBE
383 * - miDbeAllocBackBufferName() calls FreeResource() to clean up resources
384 * after a buffer allocation failure.
386 * - The PositionWindow wrapper, miDbePositionWindow(), calls
387 * FreeResource() when it fails to create buffers of the new size.
388 * FreeResource() is called for all DBE buffer IDs.
390 * - FreeClientResources() calls FreeResource() when a client dies or the
393 * When FreeResource() is called for a DBE buffer ID, the delete function
394 * for the only other type of DBE resource, dbeDrawableResType, is also
395 * invoked. This delete function (DbeDrawableDelete) is a NOOP to make
396 * resource deletion easier. It is not guaranteed which delete function is
397 * called first. Hence, we will let miDbeWinPrivDelete() free all DBE
400 * This function deletes/frees the following stuff associated with
401 * the window private:
403 * - the ID node in the ID list representing the passed in ID.
405 * In addition, pDbeWindowPriv->nBufferIDs is decremented.
407 * If this function is called for the last/only buffer ID for a window,
408 * these are additionally deleted/freed:
410 * - the front and back pixmaps
411 * - the window priv itself
413 *****************************************************************************/
416 miDbeWinPrivDelete(DbeWindowPrivPtr pDbeWindowPriv
, XID bufId
)
418 if (pDbeWindowPriv
->nBufferIDs
!= 0) {
419 /* We still have at least one more buffer ID associated with this
425 /* We have no more buffer IDs associated with this window. We need to
429 /* Destroy the front and back pixmaps. */
430 if (pDbeWindowPriv
->pFrontBuffer
) {
431 (*pDbeWindowPriv
->pWindow
->drawable
.pScreen
->
432 DestroyPixmap
) (pDbeWindowPriv
->pFrontBuffer
);
434 if (pDbeWindowPriv
->pBackBuffer
) {
435 (*pDbeWindowPriv
->pWindow
->drawable
.pScreen
->
436 DestroyPixmap
) (pDbeWindowPriv
->pBackBuffer
);
438 } /* miDbeWinPrivDelete() */
440 /******************************************************************************
442 * DBE MI Procedure: miDbePositionWindow
446 * This function was cloned from miMbxPositionWindow() in mimultibuf.c.
447 * This function resizes the buffer when the window is resized.
449 *****************************************************************************/
452 miDbePositionWindow(WindowPtr pWin
, int x
, int y
)
455 DbeScreenPrivPtr pDbeScreenPriv
;
456 DbeWindowPrivPtr pDbeWindowPriv
;
459 int sourcex
, sourcey
;
461 int savewidth
, saveheight
;
462 PixmapPtr pFrontBuffer
;
463 PixmapPtr pBackBuffer
;
466 xRectangle clearRect
;
470 **************************************************************************
471 ** 1. Unwrap the member routine.
472 **************************************************************************
475 pScreen
= pWin
->drawable
.pScreen
;
476 pDbeScreenPriv
= DBE_SCREEN_PRIV(pScreen
);
477 pScreen
->PositionWindow
= pDbeScreenPriv
->PositionWindow
;
480 **************************************************************************
481 ** 2. Do any work necessary before the member routine is called.
483 ** In this case we do not need to do anything.
484 **************************************************************************
488 **************************************************************************
489 ** 3. Call the member routine, saving its result if necessary.
490 **************************************************************************
493 ret
= (*pScreen
->PositionWindow
) (pWin
, x
, y
);
496 **************************************************************************
497 ** 4. Rewrap the member routine, restoring the wrapper value first in case
498 ** the wrapper (or something that it wrapped) change this value.
499 **************************************************************************
502 pDbeScreenPriv
->PositionWindow
= pScreen
->PositionWindow
;
503 pScreen
->PositionWindow
= miDbePositionWindow
;
506 **************************************************************************
507 ** 5. Do any work necessary after the member routine has been called.
508 **************************************************************************
511 if (!(pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
))) {
515 if (pDbeWindowPriv
->width
== pWin
->drawable
.width
&&
516 pDbeWindowPriv
->height
== pWin
->drawable
.height
) {
520 width
= pWin
->drawable
.width
;
521 height
= pWin
->drawable
.height
;
523 dx
= pWin
->drawable
.x
- pDbeWindowPriv
->x
;
524 dy
= pWin
->drawable
.y
- pDbeWindowPriv
->y
;
525 dw
= width
- pDbeWindowPriv
->width
;
526 dh
= height
- pDbeWindowPriv
->height
;
528 GravityTranslate(0, 0, -dx
, -dy
, dw
, dh
, pWin
->bitGravity
, &destx
, &desty
);
530 clear
= ((pDbeWindowPriv
->width
< (unsigned short) width
) ||
531 (pDbeWindowPriv
->height
< (unsigned short) height
) ||
532 (pWin
->bitGravity
== ForgetGravity
));
536 savewidth
= pDbeWindowPriv
->width
;
537 saveheight
= pDbeWindowPriv
->height
;
539 /* Clip rectangle to source and destination. */
546 if (destx
+ savewidth
> width
) {
547 savewidth
= width
- destx
;
556 if (desty
+ saveheight
> height
) {
557 saveheight
= height
- desty
;
560 pDbeWindowPriv
->width
= width
;
561 pDbeWindowPriv
->height
= height
;
562 pDbeWindowPriv
->x
= pWin
->drawable
.x
;
563 pDbeWindowPriv
->y
= pWin
->drawable
.y
;
565 pGC
= GetScratchGC(pWin
->drawable
.depth
, pScreen
);
568 if ((*pDbeScreenPriv
->SetupBackgroundPainter
) (pWin
, pGC
)) {
571 clearRect
.width
= width
;
572 clearRect
.height
= height
;
579 /* Create DBE buffer pixmaps equal to size of resized window. */
580 pFrontBuffer
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
,
581 pWin
->drawable
.depth
, 0);
583 pBackBuffer
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
,
584 pWin
->drawable
.depth
, 0);
586 if (!pFrontBuffer
|| !pBackBuffer
) {
587 /* We failed at creating 1 or 2 of the pixmaps. */
590 (*pScreen
->DestroyPixmap
) (pFrontBuffer
);
594 (*pScreen
->DestroyPixmap
) (pBackBuffer
);
597 /* Destroy all buffers for this window. */
598 while (pDbeWindowPriv
) {
599 /* DbeWindowPrivDelete() will free the window private if there no
600 * more buffer IDs associated with this window.
602 FreeResource(pDbeWindowPriv
->IDs
[0], RT_NONE
);
603 pDbeWindowPriv
= DBE_WINDOW_PRIV(pWin
);
611 /* Clear out the new DBE buffer pixmaps. */
613 /* I suppose this could avoid quite a bit of work if
614 * it computed the minimal area required.
616 ValidateGC(&pFrontBuffer
->drawable
, pGC
);
618 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
) pFrontBuffer
, pGC
, 1,
621 /* Copy the contents of the old front pixmap to the new one. */
622 if (pWin
->bitGravity
!= ForgetGravity
) {
623 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pDbeWindowPriv
->pFrontBuffer
,
624 (DrawablePtr
) pFrontBuffer
, pGC
,
625 sourcex
, sourcey
, savewidth
, saveheight
,
629 ValidateGC(&pBackBuffer
->drawable
, pGC
);
631 (*pGC
->ops
->PolyFillRect
) ((DrawablePtr
) pBackBuffer
, pGC
, 1,
634 /* Copy the contents of the old back pixmap to the new one. */
635 if (pWin
->bitGravity
!= ForgetGravity
) {
636 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pDbeWindowPriv
->pBackBuffer
,
637 (DrawablePtr
) pBackBuffer
, pGC
,
638 sourcex
, sourcey
, savewidth
, saveheight
,
642 /* Destroy the old pixmaps, and point the DBE window priv to the new
646 (*pScreen
->DestroyPixmap
) (pDbeWindowPriv
->pFrontBuffer
);
647 (*pScreen
->DestroyPixmap
) (pDbeWindowPriv
->pBackBuffer
);
649 pDbeWindowPriv
->pFrontBuffer
= pFrontBuffer
;
650 pDbeWindowPriv
->pBackBuffer
= pBackBuffer
;
652 /* Make sure all XID are associated with the new back pixmap. */
653 miDbeAliasBuffers(pDbeWindowPriv
);
660 } /* miDbePositionWindow() */
662 /******************************************************************************
664 * DBE MI Procedure: miDbeInit
668 * This is the MI initialization function called by DbeExtensionInit().
670 *****************************************************************************/
673 miDbeInit(ScreenPtr pScreen
, DbeScreenPrivPtr pDbeScreenPriv
)
675 /* Wrap functions. */
676 pDbeScreenPriv
->PositionWindow
= pScreen
->PositionWindow
;
677 pScreen
->PositionWindow
= miDbePositionWindow
;
679 /* Initialize the per-screen DBE function pointers. */
680 pDbeScreenPriv
->GetVisualInfo
= miDbeGetVisualInfo
;
681 pDbeScreenPriv
->AllocBackBufferName
= miDbeAllocBackBufferName
;
682 pDbeScreenPriv
->SwapBuffers
= miDbeSwapBuffers
;
683 pDbeScreenPriv
->WinPrivDelete
= miDbeWinPrivDelete
;