dbe.c revision 6e78d31f
1/****************************************************************************** 2 * 3 * Copyright (c) 1994, 1995 Hewlett-Packard Company 4 * 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: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 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. 23 * 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. 28 * 29 * DIX DBE code 30 * 31 *****************************************************************************/ 32 33/* INCLUDES */ 34 35#ifdef HAVE_DIX_CONFIG_H 36#include <dix-config.h> 37#endif 38 39#include <string.h> 40#include <stdint.h> 41#include <X11/X.h> 42#include <X11/Xproto.h> 43#include "scrnintstr.h" 44#include "extnsionst.h" 45#include "extinit.h" 46#include "gcstruct.h" 47#include "dixstruct.h" 48#define NEED_DBE_PROTOCOL 49#include "dbestruct.h" 50#include "midbe.h" 51#include "xace.h" 52 53/* GLOBALS */ 54 55/* These are globals for use by DDX */ 56DevPrivateKeyRec dbeScreenPrivKeyRec; 57DevPrivateKeyRec dbeWindowPrivKeyRec; 58 59/* These are globals for use by DDX */ 60RESTYPE dbeDrawableResType; 61RESTYPE dbeWindowPrivResType; 62 63/* Used to generate DBE's BadBuffer error. */ 64static int dbeErrorBase; 65 66/****************************************************************************** 67 * 68 * DBE DIX Procedure: DbeStubScreen 69 * 70 * Description: 71 * 72 * This is function stubs the function pointers in the given DBE screen 73 * private and increments the number of stubbed screens. 74 * 75 *****************************************************************************/ 76 77static void 78DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv, int *nStubbedScreens) 79{ 80 /* Stub DIX. */ 81 pDbeScreenPriv->SetupBackgroundPainter = NULL; 82 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. 87 */ 88 89 /* Stub DDX. */ 90 pDbeScreenPriv->GetVisualInfo = NULL; 91 pDbeScreenPriv->AllocBackBufferName = NULL; 92 pDbeScreenPriv->SwapBuffers = NULL; 93 pDbeScreenPriv->WinPrivDelete = NULL; 94 95 (*nStubbedScreens)++; 96 97} /* DbeStubScreen() */ 98 99/****************************************************************************** 100 * 101 * DBE DIX Procedure: ProcDbeGetVersion 102 * 103 * Description: 104 * 105 * This function is for processing a DbeGetVersion request. 106 * This request returns the major and minor version numbers of this 107 * extension. 108 * 109 * Return Values: 110 * 111 * Success 112 * 113 *****************************************************************************/ 114 115static int 116ProcDbeGetVersion(ClientPtr client) 117{ 118 /* REQUEST(xDbeGetVersionReq); */ 119 xDbeGetVersionReply rep = { 120 .type = X_Reply, 121 .sequenceNumber = client->sequence, 122 .length = 0, 123 .majorVersion = DBE_MAJOR_VERSION, 124 .minorVersion = DBE_MINOR_VERSION 125 }; 126 127 REQUEST_SIZE_MATCH(xDbeGetVersionReq); 128 129 if (client->swapped) { 130 swaps(&rep.sequenceNumber); 131 } 132 133 WriteToClient(client, sizeof(xDbeGetVersionReply), &rep); 134 135 return Success; 136 137} /* ProcDbeGetVersion() */ 138 139/****************************************************************************** 140 * 141 * DBE DIX Procedure: ProcDbeAllocateBackBufferName 142 * 143 * Description: 144 * 145 * This function is for processing a DbeAllocateBackBufferName request. 146 * This request allocates a drawable ID used to refer to the back buffer 147 * of a window. 148 * 149 * Return Values: 150 * 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 155 * DBEGetVisualInfo; 156 * BadValue - invalid swap action is specified 157 * BadWindow - window is not a valid window 158 * Success 159 * 160 *****************************************************************************/ 161 162static int 163ProcDbeAllocateBackBufferName(ClientPtr client) 164{ 165 REQUEST(xDbeAllocateBackBufferNameReq); 166 WindowPtr pWin; 167 DbeScreenPrivPtr pDbeScreenPriv; 168 DbeWindowPrivPtr pDbeWindowPriv; 169 XdbeScreenVisualInfo scrVisInfo; 170 register int i; 171 Bool visualMatched = FALSE; 172 xDbeSwapAction swapAction; 173 VisualID visual; 174 int status; 175 int add_index; 176 177 REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); 178 179 /* The window must be valid. */ 180 status = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 181 if (status != Success) 182 return status; 183 184 /* The window must be InputOutput. */ 185 if (pWin->drawable.class != InputOutput) { 186 return BadMatch; 187 } 188 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)) { 194 return BadValue; 195 } 196 197 /* The id must be in range and not already in use. */ 198 LEGAL_NEW_RESOURCE(stuff->buffer, client); 199 200 /* The visual of the window must be in the list returned by 201 * GetVisualInfo. 202 */ 203 pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); 204 if (!pDbeScreenPriv->GetVisualInfo) 205 return BadMatch; /* screen doesn't support double buffering */ 206 207 if (!(*pDbeScreenPriv->GetVisualInfo) (pWin->drawable.pScreen, &scrVisInfo)) { 208 /* GetVisualInfo() failed to allocate visual info data. */ 209 return BadAlloc; 210 } 211 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; 217 } 218 } 219 220 /* Free what was allocated by the GetVisualInfo() call above. */ 221 free(scrVisInfo.visinfo); 222 223 if (!visualMatched) { 224 return BadMatch; 225 } 226 227 if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) == NULL) { 228 /* There is no buffer associated with the window. 229 * Allocate a window priv. 230 */ 231 232 pDbeWindowPriv = calloc(1, sizeof(DbeWindowPrivRec)); 233 if (!pDbeWindowPriv) 234 return BadAlloc; 235 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; 243 244 /* Set the buffer ID array pointer to the initial (static) array). */ 245 pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; 246 247 /* Initialize the buffer ID list. */ 248 pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; 249 pDbeWindowPriv->IDs[0] = stuff->buffer; 250 251 add_index = 0; 252 for (i = 0; i < DBE_INIT_MAX_IDS; i++) { 253 pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; 254 } 255 256 /* Actually connect the window priv to the window. */ 257 dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, pDbeWindowPriv); 258 259 } /* if -- There is no buffer associated with the window. */ 260 261 else { 262 /* A buffer is already associated with the window. 263 * Add the new buffer ID to the array, reallocating the array memory 264 * if necessary. 265 */ 266 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. */ 271 break; 272 } 273 } 274 275 if (i == pDbeWindowPriv->maxAvailableIDs) { 276 /* No more room in the ID array -- reallocate another array. */ 277 XID *pIDs; 278 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. */ 282 pIDs = NULL; 283 } 284 else { 285 /* We will realloc a new array. */ 286 pIDs = pDbeWindowPriv->IDs; 287 } 288 289 /* malloc/realloc a new array and initialize all elements to 0. */ 290 pDbeWindowPriv->IDs = 291 reallocarray(pIDs, 292 pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS, 293 sizeof(XID)); 294 if (!pDbeWindowPriv->IDs) { 295 return BadAlloc; 296 } 297 memset(&pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs], 0, 298 (pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS - 299 pDbeWindowPriv->nBufferIDs) * sizeof(XID)); 300 301 if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) { 302 /* We just went from using the initial (static) array to a 303 * newly allocated array. Copy the IDs from the initial array 304 * to the new array. 305 */ 306 memcpy(pDbeWindowPriv->IDs, pDbeWindowPriv->initIDs, 307 DBE_INIT_MAX_IDS * sizeof(XID)); 308 } 309 310 pDbeWindowPriv->maxAvailableIDs += DBE_INCR_MAX_IDS; 311 } 312 313 add_index = i; 314 315 } /* else -- A buffer is already associated with the window. */ 316 317 /* Call the DDX routine to allocate the back buffer. */ 318 status = (*pDbeScreenPriv->AllocBackBufferName) (pWin, stuff->buffer, 319 stuff->swapAction); 320 321 if (status == Success) { 322 pDbeWindowPriv->IDs[add_index] = stuff->buffer; 323 if (!AddResource(stuff->buffer, dbeWindowPrivResType, 324 (void *) pDbeWindowPriv)) { 325 pDbeWindowPriv->IDs[add_index] = DBE_FREE_ID_ELEMENT; 326 327 if (pDbeWindowPriv->nBufferIDs == 0) { 328 status = BadAlloc; 329 goto out_free; 330 } 331 } 332 } 333 else { 334 /* The DDX buffer allocation routine failed for the first buffer of 335 * this window. 336 */ 337 if (pDbeWindowPriv->nBufferIDs == 0) { 338 goto out_free; 339 } 340 } 341 342 /* Increment the number of buffers (XIDs) associated with this window. */ 343 pDbeWindowPriv->nBufferIDs++; 344 345 /* Set swap action on all calls. */ 346 pDbeWindowPriv->swapAction = stuff->swapAction; 347 348 return status; 349 350 out_free: 351 dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, NULL); 352 free(pDbeWindowPriv); 353 return status; 354 355} /* ProcDbeAllocateBackBufferName() */ 356 357/****************************************************************************** 358 * 359 * DBE DIX Procedure: ProcDbeDeallocateBackBufferName 360 * 361 * Description: 362 * 363 * This function is for processing a DbeDeallocateBackBufferName request. 364 * This request frees a drawable ID that was obtained by a 365 * DbeAllocateBackBufferName request. 366 * 367 * Return Values: 368 * 369 * BadBuffer - buffer to deallocate is not associated with a window 370 * Success 371 * 372 *****************************************************************************/ 373 374static int 375ProcDbeDeallocateBackBufferName(ClientPtr client) 376{ 377 REQUEST(xDbeDeallocateBackBufferNameReq); 378 DbeWindowPrivPtr pDbeWindowPriv; 379 int rc, i; 380 void *val; 381 382 REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); 383 384 /* Buffer name must be valid */ 385 rc = dixLookupResourceByType((void **) &pDbeWindowPriv, stuff->buffer, 386 dbeWindowPrivResType, client, 387 DixDestroyAccess); 388 if (rc != Success) 389 return rc; 390 391 rc = dixLookupResourceByType(&val, stuff->buffer, dbeDrawableResType, 392 client, DixDestroyAccess); 393 if (rc != Success) 394 return rc; 395 396 /* Make sure that the id is valid for the window. 397 * This is paranoid code since we already looked up the ID by type 398 * above. 399 */ 400 401 for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) { 402 /* Loop through the ID list to find the ID. */ 403 if (pDbeWindowPriv->IDs[i] == stuff->buffer) { 404 break; 405 } 406 } 407 408 if (i == pDbeWindowPriv->nBufferIDs) { 409 /* We did not find the ID in the ID list. */ 410 client->errorValue = stuff->buffer; 411 return dbeErrorBase + DbeBadBuffer; 412 } 413 414 FreeResource(stuff->buffer, RT_NONE); 415 416 return Success; 417 418} /* ProcDbeDeallocateBackBufferName() */ 419 420/****************************************************************************** 421 * 422 * DBE DIX Procedure: ProcDbeSwapBuffers 423 * 424 * Description: 425 * 426 * This function is for processing a DbeSwapBuffers request. 427 * This request swaps the buffers for all windows listed, applying the 428 * appropriate swap action for each window. 429 * 430 * Return Values: 431 * 432 * BadAlloc - local allocation failed; this return value is not defined 433 * by the protocol 434 * BadMatch - a window in request is not double-buffered; a window in 435 * request is listed more than once 436 * BadValue - invalid swap action is specified; no swap action is 437 * specified 438 * BadWindow - a window in request is not valid 439 * Success 440 * 441 *****************************************************************************/ 442 443static int 444ProcDbeSwapBuffers(ClientPtr client) 445{ 446 REQUEST(xDbeSwapBuffersReq); 447 WindowPtr pWin; 448 DbeScreenPrivPtr pDbeScreenPriv; 449 DbeSwapInfoPtr swapInfo; 450 xDbeSwapInfo *dbeSwapInfo; 451 int error; 452 unsigned int i, j; 453 unsigned int nStuff; 454 int nStuff_i; /* DDX API requires int for nStuff */ 455 456 REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); 457 nStuff = stuff->n; /* use local variable for performance. */ 458 459 if (nStuff == 0) { 460 REQUEST_SIZE_MATCH(xDbeSwapBuffersReq); 461 return Success; 462 } 463 464 if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) 465 return BadAlloc; 466 REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, nStuff * sizeof(xDbeSwapInfo)); 467 468 /* Get to the swap info appended to the end of the request. */ 469 dbeSwapInfo = (xDbeSwapInfo *) &stuff[1]; 470 471 /* Allocate array to record swap information. */ 472 swapInfo = xallocarray(nStuff, sizeof(DbeSwapInfoRec)); 473 if (swapInfo == NULL) { 474 return BadAlloc; 475 } 476 477 for (i = 0; i < nStuff; i++) { 478 /* Check all windows to swap. */ 479 480 /* Each window must be a valid window - BadWindow. */ 481 error = dixLookupWindow(&pWin, dbeSwapInfo[i].window, client, 482 DixWriteAccess); 483 if (error != Success) { 484 free(swapInfo); 485 return error; 486 } 487 488 /* Each window must be double-buffered - BadMatch. */ 489 if (DBE_WINDOW_PRIV(pWin) == NULL) { 490 free(swapInfo); 491 return BadMatch; 492 } 493 494 /* Each window must only be specified once - BadMatch. */ 495 for (j = i + 1; j < nStuff; j++) { 496 if (dbeSwapInfo[i].window == dbeSwapInfo[j].window) { 497 free(swapInfo); 498 return BadMatch; 499 } 500 } 501 502 /* Each swap action must be valid - BadValue. */ 503 if ((dbeSwapInfo[i].swapAction != XdbeUndefined) && 504 (dbeSwapInfo[i].swapAction != XdbeBackground) && 505 (dbeSwapInfo[i].swapAction != XdbeUntouched) && 506 (dbeSwapInfo[i].swapAction != XdbeCopied)) { 507 free(swapInfo); 508 return BadValue; 509 } 510 511 /* Everything checks out OK. Fill in the swap info array. */ 512 swapInfo[i].pWindow = pWin; 513 swapInfo[i].swapAction = dbeSwapInfo[i].swapAction; 514 515 } /* for (i = 0; i < nStuff; i++) */ 516 517 /* Call the DDX routine to perform the swap(s). The DDX routine should 518 * scan the swap list (swap info), swap any buffers that it knows how to 519 * handle, delete them from the list, and update nStuff to indicate how 520 * many windows it did not handle. 521 * 522 * This scheme allows a range of sophistication in the DDX SwapBuffers() 523 * implementation. Naive implementations could just swap the first buffer 524 * in the list, move the last buffer to the front, decrement nStuff, and 525 * return. The next level of sophistication could be to scan the whole 526 * list for windows on the same screen. Up another level, the DDX routine 527 * could deal with cross-screen synchronization. 528 */ 529 530 nStuff_i = nStuff; 531 while (nStuff_i > 0) { 532 pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow); 533 error = (*pDbeScreenPriv->SwapBuffers) (client, &nStuff_i, swapInfo); 534 if (error != Success) { 535 free(swapInfo); 536 return error; 537 } 538 } 539 540 free(swapInfo); 541 return Success; 542 543} /* ProcDbeSwapBuffers() */ 544 545/****************************************************************************** 546 * 547 * DBE DIX Procedure: ProcDbeGetVisualInfo 548 * 549 * Description: 550 * 551 * This function is for processing a ProcDbeGetVisualInfo request. 552 * This request returns information about which visuals support 553 * double buffering. 554 * 555 * Return Values: 556 * 557 * BadDrawable - value in screen specifiers is not a valid drawable 558 * Success 559 * 560 *****************************************************************************/ 561 562static int 563ProcDbeGetVisualInfo(ClientPtr client) 564{ 565 REQUEST(xDbeGetVisualInfoReq); 566 DbeScreenPrivPtr pDbeScreenPriv; 567 xDbeGetVisualInfoReply rep; 568 Drawable *drawables; 569 DrawablePtr *pDrawables = NULL; 570 register int i, j, rc; 571 register int count; /* number of visual infos in reply */ 572 register int length; /* length of reply */ 573 ScreenPtr pScreen; 574 XdbeScreenVisualInfo *pScrVisInfo; 575 576 REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); 577 if (stuff->n > UINT32_MAX / sizeof(CARD32)) 578 return BadLength; 579 REQUEST_FIXED_SIZE(xDbeGetVisualInfoReq, stuff->n * sizeof(CARD32)); 580 581 if (stuff->n > UINT32_MAX / sizeof(DrawablePtr)) 582 return BadAlloc; 583 /* Make sure any specified drawables are valid. */ 584 if (stuff->n != 0) { 585 if (!(pDrawables = xallocarray(stuff->n, sizeof(DrawablePtr)))) { 586 return BadAlloc; 587 } 588 589 drawables = (Drawable *) &stuff[1]; 590 591 for (i = 0; i < stuff->n; i++) { 592 rc = dixLookupDrawable(pDrawables + i, drawables[i], client, 0, 593 DixGetAttrAccess); 594 if (rc != Success) { 595 free(pDrawables); 596 return rc; 597 } 598 } 599 } 600 601 count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n; 602 if (!(pScrVisInfo = calloc(count, sizeof(XdbeScreenVisualInfo)))) { 603 free(pDrawables); 604 605 return BadAlloc; 606 } 607 608 length = 0; 609 610 for (i = 0; i < count; i++) { 611 pScreen = (stuff->n == 0) ? screenInfo.screens[i] : 612 pDrawables[i]->pScreen; 613 pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); 614 615 rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); 616 if (rc != Success) 617 goto freeScrVisInfo; 618 619 if (!(*pDbeScreenPriv->GetVisualInfo) (pScreen, &pScrVisInfo[i])) { 620 /* We failed to alloc pScrVisInfo[i].visinfo. */ 621 rc = BadAlloc; 622 623 /* Free visinfos that we allocated for previous screen infos. */ 624 goto freeScrVisInfo; 625 } 626 627 /* Account for n, number of xDbeVisInfo items in list. */ 628 length += sizeof(CARD32); 629 630 /* Account for n xDbeVisInfo items */ 631 length += pScrVisInfo[i].count * sizeof(xDbeVisInfo); 632 } 633 634 rep = (xDbeGetVisualInfoReply) { 635 .type = X_Reply, 636 .sequenceNumber = client->sequence, 637 .length = bytes_to_int32(length), 638 .m = count 639 }; 640 641 if (client->swapped) { 642 swaps(&rep.sequenceNumber); 643 swapl(&rep.length); 644 swapl(&rep.m); 645 } 646 647 /* Send off reply. */ 648 WriteToClient(client, sizeof(xDbeGetVisualInfoReply), &rep); 649 650 for (i = 0; i < count; i++) { 651 CARD32 data32; 652 653 /* For each screen in the reply, send off the visual info */ 654 655 /* Send off number of visuals. */ 656 data32 = (CARD32) pScrVisInfo[i].count; 657 658 if (client->swapped) { 659 swapl(&data32); 660 } 661 662 WriteToClient(client, sizeof(CARD32), &data32); 663 664 /* Now send off visual info items. */ 665 for (j = 0; j < pScrVisInfo[i].count; j++) { 666 xDbeVisInfo visInfo; 667 668 /* Copy the data in the client data structure to a protocol 669 * data structure. We will send data to the client from the 670 * protocol data structure. 671 */ 672 673 visInfo.visualID = (CARD32) pScrVisInfo[i].visinfo[j].visual; 674 visInfo.depth = (CARD8) pScrVisInfo[i].visinfo[j].depth; 675 visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel; 676 677 if (client->swapped) { 678 swapl(&visInfo.visualID); 679 680 /* We do not need to swap depth and perfLevel since they are 681 * already 1 byte quantities. 682 */ 683 } 684 685 /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */ 686 WriteToClient(client, 2 * sizeof(CARD32), &visInfo.visualID); 687 } 688 } 689 690 rc = Success; 691 692 freeScrVisInfo: 693 /* Clean up memory. */ 694 for (i = 0; i < count; i++) { 695 free(pScrVisInfo[i].visinfo); 696 } 697 free(pScrVisInfo); 698 699 free(pDrawables); 700 701 return rc; 702 703} /* ProcDbeGetVisualInfo() */ 704 705/****************************************************************************** 706 * 707 * DBE DIX Procedure: ProcDbeGetbackBufferAttributes 708 * 709 * Description: 710 * 711 * This function is for processing a ProcDbeGetbackBufferAttributes 712 * request. This request returns information about a back buffer. 713 * 714 * Return Values: 715 * 716 * Success 717 * 718 *****************************************************************************/ 719 720static int 721ProcDbeGetBackBufferAttributes(ClientPtr client) 722{ 723 REQUEST(xDbeGetBackBufferAttributesReq); 724 xDbeGetBackBufferAttributesReply rep = { 725 .type = X_Reply, 726 .sequenceNumber = client->sequence, 727 .length = 0 728 }; 729 DbeWindowPrivPtr pDbeWindowPriv; 730 int rc; 731 732 REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); 733 734 rc = dixLookupResourceByType((void **) &pDbeWindowPriv, stuff->buffer, 735 dbeWindowPrivResType, client, 736 DixGetAttrAccess); 737 if (rc == Success) { 738 rep.attributes = pDbeWindowPriv->pWindow->drawable.id; 739 } 740 else { 741 rep.attributes = None; 742 } 743 744 if (client->swapped) { 745 swaps(&rep.sequenceNumber); 746 swapl(&rep.length); 747 swapl(&rep.attributes); 748 } 749 750 WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply), &rep); 751 return Success; 752 753} /* ProcDbeGetbackBufferAttributes() */ 754 755/****************************************************************************** 756 * 757 * DBE DIX Procedure: ProcDbeDispatch 758 * 759 * Description: 760 * 761 * This function dispatches DBE requests. 762 * 763 *****************************************************************************/ 764 765static int 766ProcDbeDispatch(ClientPtr client) 767{ 768 REQUEST(xReq); 769 770 switch (stuff->data) { 771 case X_DbeGetVersion: 772 return (ProcDbeGetVersion(client)); 773 774 case X_DbeAllocateBackBufferName: 775 return (ProcDbeAllocateBackBufferName(client)); 776 777 case X_DbeDeallocateBackBufferName: 778 return (ProcDbeDeallocateBackBufferName(client)); 779 780 case X_DbeSwapBuffers: 781 return (ProcDbeSwapBuffers(client)); 782 783 case X_DbeBeginIdiom: 784 return Success; 785 786 case X_DbeEndIdiom: 787 return Success; 788 789 case X_DbeGetVisualInfo: 790 return (ProcDbeGetVisualInfo(client)); 791 792 case X_DbeGetBackBufferAttributes: 793 return (ProcDbeGetBackBufferAttributes(client)); 794 795 default: 796 return BadRequest; 797 } 798 799} /* ProcDbeDispatch() */ 800 801/****************************************************************************** 802 * 803 * DBE DIX Procedure: SProcDbeGetVersion 804 * 805 * Description: 806 * 807 * This function is for processing a DbeGetVersion request on a swapped 808 * server. This request returns the major and minor version numbers of 809 * this extension. 810 * 811 * Return Values: 812 * 813 * Success 814 * 815 *****************************************************************************/ 816 817static int 818SProcDbeGetVersion(ClientPtr client) 819{ 820 REQUEST(xDbeGetVersionReq); 821 822 swaps(&stuff->length); 823 return (ProcDbeGetVersion(client)); 824 825} /* SProcDbeGetVersion() */ 826 827/****************************************************************************** 828 * 829 * DBE DIX Procedure: SProcDbeAllocateBackBufferName 830 * 831 * Description: 832 * 833 * This function is for processing a DbeAllocateBackBufferName request on 834 * a swapped server. This request allocates a drawable ID used to refer 835 * to the back buffer of a window. 836 * 837 * Return Values: 838 * 839 * BadAlloc - server can not allocate resources 840 * BadIDChoice - id is out of range for client; id is already in use 841 * BadMatch - window is not an InputOutput window; 842 * visual of window is not on list returned by 843 * DBEGetVisualInfo; 844 * BadValue - invalid swap action is specified 845 * BadWindow - window is not a valid window 846 * Success 847 * 848 *****************************************************************************/ 849 850static int 851SProcDbeAllocateBackBufferName(ClientPtr client) 852{ 853 REQUEST(xDbeAllocateBackBufferNameReq); 854 855 swaps(&stuff->length); 856 REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); 857 858 swapl(&stuff->window); 859 swapl(&stuff->buffer); 860 /* stuff->swapAction is a byte. We do not need to swap this field. */ 861 862 return (ProcDbeAllocateBackBufferName(client)); 863 864} /* SProcDbeAllocateBackBufferName() */ 865 866/****************************************************************************** 867 * 868 * DBE DIX Procedure: SProcDbeDeallocateBackBufferName 869 * 870 * Description: 871 * 872 * This function is for processing a DbeDeallocateBackBufferName request 873 * on a swapped server. This request frees a drawable ID that was 874 * obtained by a DbeAllocateBackBufferName request. 875 * 876 * Return Values: 877 * 878 * BadBuffer - buffer to deallocate is not associated with a window 879 * Success 880 * 881 *****************************************************************************/ 882 883static int 884SProcDbeDeallocateBackBufferName(ClientPtr client) 885{ 886 REQUEST(xDbeDeallocateBackBufferNameReq); 887 888 swaps(&stuff->length); 889 REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); 890 891 swapl(&stuff->buffer); 892 893 return (ProcDbeDeallocateBackBufferName(client)); 894 895} /* SProcDbeDeallocateBackBufferName() */ 896 897/****************************************************************************** 898 * 899 * DBE DIX Procedure: SProcDbeSwapBuffers 900 * 901 * Description: 902 * 903 * This function is for processing a DbeSwapBuffers request on a swapped 904 * server. This request swaps the buffers for all windows listed, 905 * applying the appropriate swap action for each window. 906 * 907 * Return Values: 908 * 909 * BadMatch - a window in request is not double-buffered; a window in 910 * request is listed more than once; all windows in request do 911 * not have the same root 912 * BadValue - invalid swap action is specified 913 * BadWindow - a window in request is not valid 914 * Success 915 * 916 *****************************************************************************/ 917 918static int 919SProcDbeSwapBuffers(ClientPtr client) 920{ 921 REQUEST(xDbeSwapBuffersReq); 922 unsigned int i; 923 xDbeSwapInfo *pSwapInfo; 924 925 swaps(&stuff->length); 926 REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); 927 928 swapl(&stuff->n); 929 if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec)) 930 return BadLength; 931 REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo)); 932 933 if (stuff->n != 0) { 934 pSwapInfo = (xDbeSwapInfo *) stuff + 1; 935 936 /* The swap info following the fix part of this request is a window(32) 937 * followed by a 1 byte swap action and then 3 pad bytes. We only need 938 * to swap the window information. 939 */ 940 for (i = 0; i < stuff->n; i++) { 941 swapl(&pSwapInfo->window); 942 } 943 } 944 945 return (ProcDbeSwapBuffers(client)); 946 947} /* SProcDbeSwapBuffers() */ 948 949/****************************************************************************** 950 * 951 * DBE DIX Procedure: SProcDbeGetVisualInfo 952 * 953 * Description: 954 * 955 * This function is for processing a ProcDbeGetVisualInfo request on a 956 * swapped server. This request returns information about which visuals 957 * support double buffering. 958 * 959 * Return Values: 960 * 961 * BadDrawable - value in screen specifiers is not a valid drawable 962 * Success 963 * 964 *****************************************************************************/ 965 966static int 967SProcDbeGetVisualInfo(ClientPtr client) 968{ 969 REQUEST(xDbeGetVisualInfoReq); 970 971 swaps(&stuff->length); 972 REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); 973 974 swapl(&stuff->n); 975 SwapRestL(stuff); 976 977 return (ProcDbeGetVisualInfo(client)); 978 979} /* SProcDbeGetVisualInfo() */ 980 981/****************************************************************************** 982 * 983 * DBE DIX Procedure: SProcDbeGetbackBufferAttributes 984 * 985 * Description: 986 * 987 * This function is for processing a ProcDbeGetbackBufferAttributes 988 * request on a swapped server. This request returns information about a 989 * back buffer. 990 * 991 * Return Values: 992 * 993 * Success 994 * 995 *****************************************************************************/ 996 997static int 998SProcDbeGetBackBufferAttributes(ClientPtr client) 999{ 1000 REQUEST(xDbeGetBackBufferAttributesReq); 1001 1002 swaps(&stuff->length); 1003 REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); 1004 1005 swapl(&stuff->buffer); 1006 1007 return (ProcDbeGetBackBufferAttributes(client)); 1008 1009} /* SProcDbeGetBackBufferAttributes() */ 1010 1011/****************************************************************************** 1012 * 1013 * DBE DIX Procedure: SProcDbeDispatch 1014 * 1015 * Description: 1016 * 1017 * This function dispatches DBE requests on a swapped server. 1018 * 1019 *****************************************************************************/ 1020 1021static int 1022SProcDbeDispatch(ClientPtr client) 1023{ 1024 REQUEST(xReq); 1025 1026 switch (stuff->data) { 1027 case X_DbeGetVersion: 1028 return (SProcDbeGetVersion(client)); 1029 1030 case X_DbeAllocateBackBufferName: 1031 return (SProcDbeAllocateBackBufferName(client)); 1032 1033 case X_DbeDeallocateBackBufferName: 1034 return (SProcDbeDeallocateBackBufferName(client)); 1035 1036 case X_DbeSwapBuffers: 1037 return (SProcDbeSwapBuffers(client)); 1038 1039 case X_DbeBeginIdiom: 1040 return Success; 1041 1042 case X_DbeEndIdiom: 1043 return Success; 1044 1045 case X_DbeGetVisualInfo: 1046 return (SProcDbeGetVisualInfo(client)); 1047 1048 case X_DbeGetBackBufferAttributes: 1049 return (SProcDbeGetBackBufferAttributes(client)); 1050 1051 default: 1052 return BadRequest; 1053 } 1054 1055} /* SProcDbeDispatch() */ 1056 1057/****************************************************************************** 1058 * 1059 * DBE DIX Procedure: DbeSetupBackgroundPainter 1060 * 1061 * Description: 1062 * 1063 * This function sets up pGC to clear pixmaps. 1064 * 1065 * Return Values: 1066 * 1067 * TRUE - setup was successful 1068 * FALSE - the window's background state is NONE 1069 * 1070 *****************************************************************************/ 1071 1072static Bool 1073DbeSetupBackgroundPainter(WindowPtr pWin, GCPtr pGC) 1074{ 1075 ChangeGCVal gcvalues[4]; 1076 int ts_x_origin, ts_y_origin; 1077 PixUnion background; 1078 int backgroundState; 1079 Mask gcmask; 1080 1081 /* First take care of any ParentRelative stuff by altering the 1082 * tile/stipple origin to match the coordinates of the upper-left 1083 * corner of the first ancestor without a ParentRelative background. 1084 * This coordinate is, of course, negative. 1085 */ 1086 ts_x_origin = ts_y_origin = 0; 1087 while (pWin->backgroundState == ParentRelative) { 1088 ts_x_origin -= pWin->origin.x; 1089 ts_y_origin -= pWin->origin.y; 1090 1091 pWin = pWin->parent; 1092 } 1093 backgroundState = pWin->backgroundState; 1094 background = pWin->background; 1095 1096 switch (backgroundState) { 1097 case BackgroundPixel: 1098 gcvalues[0].val = background.pixel; 1099 gcvalues[1].val = FillSolid; 1100 gcmask = GCForeground | GCFillStyle; 1101 break; 1102 1103 case BackgroundPixmap: 1104 gcvalues[0].val = FillTiled; 1105 gcvalues[1].ptr = background.pixmap; 1106 gcvalues[2].val = ts_x_origin; 1107 gcvalues[3].val = ts_y_origin; 1108 gcmask = GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin; 1109 break; 1110 1111 default: 1112 /* pWin->backgroundState == None */ 1113 return FALSE; 1114 } 1115 1116 return ChangeGC(NullClient, pGC, gcmask, gcvalues) == 0; 1117} /* DbeSetupBackgroundPainter() */ 1118 1119/****************************************************************************** 1120 * 1121 * DBE DIX Procedure: DbeDrawableDelete 1122 * 1123 * Description: 1124 * 1125 * This is the resource delete function for dbeDrawableResType. 1126 * It is registered when the drawable resource type is created in 1127 * DbeExtensionInit(). 1128 * 1129 * To make resource deletion simple, we do not do anything in this function 1130 * and leave all resource deleteion to DbeWindowPrivDelete(), which will 1131 * eventually be called or already has been called. Deletion functions are 1132 * not guaranteed to be called in any particular order. 1133 * 1134 *****************************************************************************/ 1135static int 1136DbeDrawableDelete(void *pDrawable, XID id) 1137{ 1138 return Success; 1139 1140} /* DbeDrawableDelete() */ 1141 1142/****************************************************************************** 1143 * 1144 * DBE DIX Procedure: DbeWindowPrivDelete 1145 * 1146 * Description: 1147 * 1148 * This is the resource delete function for dbeWindowPrivResType. 1149 * It is registered when the drawable resource type is created in 1150 * DbeExtensionInit(). 1151 * 1152 *****************************************************************************/ 1153static int 1154DbeWindowPrivDelete(void *pDbeWinPriv, XID id) 1155{ 1156 DbeScreenPrivPtr pDbeScreenPriv; 1157 DbeWindowPrivPtr pDbeWindowPriv = (DbeWindowPrivPtr) pDbeWinPriv; 1158 int i; 1159 1160 /* 1161 ************************************************************************** 1162 ** Remove the buffer ID from the ID array. 1163 ************************************************************************** 1164 */ 1165 1166 /* Find the ID in the ID array. */ 1167 i = 0; 1168 while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id)) { 1169 i++; 1170 } 1171 1172 if (i == pDbeWindowPriv->nBufferIDs) { 1173 /* We did not find the ID in the array. We should never get here. */ 1174 return BadValue; 1175 } 1176 1177 /* Remove the ID from the array. */ 1178 1179 if (i < (pDbeWindowPriv->nBufferIDs - 1)) { 1180 /* Compress the buffer ID array, overwriting the ID in the process. */ 1181 memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i + 1], 1182 (pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID)); 1183 } 1184 else { 1185 /* We are removing the last ID in the array, in which case, the 1186 * assignement below is all that we need to do. 1187 */ 1188 } 1189 pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT; 1190 1191 pDbeWindowPriv->nBufferIDs--; 1192 1193 /* If an extended array was allocated, then check to see if the remaining 1194 * buffer IDs will fit in the static array. 1195 */ 1196 1197 if ((pDbeWindowPriv->maxAvailableIDs > DBE_INIT_MAX_IDS) && 1198 (pDbeWindowPriv->nBufferIDs == DBE_INIT_MAX_IDS)) { 1199 /* Copy the IDs back into the static array. */ 1200 memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs, 1201 DBE_INIT_MAX_IDS * sizeof(XID)); 1202 1203 /* Free the extended array; use the static array. */ 1204 free(pDbeWindowPriv->IDs); 1205 pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; 1206 pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; 1207 } 1208 1209 /* 1210 ************************************************************************** 1211 ** Perform DDX level tasks. 1212 ************************************************************************** 1213 */ 1214 1215 pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV((DbeWindowPrivPtr) 1216 pDbeWindowPriv); 1217 (*pDbeScreenPriv->WinPrivDelete) ((DbeWindowPrivPtr) pDbeWindowPriv, id); 1218 1219 /* 1220 ************************************************************************** 1221 ** Perform miscellaneous tasks if this is the last buffer associated 1222 ** with the window. 1223 ************************************************************************** 1224 */ 1225 1226 if (pDbeWindowPriv->nBufferIDs == 0) { 1227 /* Reset the DBE window priv pointer. */ 1228 dixSetPrivate(&pDbeWindowPriv->pWindow->devPrivates, dbeWindowPrivKey, 1229 NULL); 1230 1231 /* We are done with the window priv. */ 1232 free(pDbeWindowPriv); 1233 } 1234 1235 return Success; 1236 1237} /* DbeWindowPrivDelete() */ 1238 1239/****************************************************************************** 1240 * 1241 * DBE DIX Procedure: DbeResetProc 1242 * 1243 * Description: 1244 * 1245 * This routine is called at the end of every server generation. 1246 * It deallocates any memory reserved for the extension and performs any 1247 * other tasks related to shutting down the extension. 1248 * 1249 *****************************************************************************/ 1250static void 1251DbeResetProc(ExtensionEntry * extEntry) 1252{ 1253 int i; 1254 ScreenPtr pScreen; 1255 DbeScreenPrivPtr pDbeScreenPriv; 1256 1257 for (i = 0; i < screenInfo.numScreens; i++) { 1258 pScreen = screenInfo.screens[i]; 1259 pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); 1260 1261 if (pDbeScreenPriv) { 1262 /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit(). */ 1263 pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; 1264 pScreen->PositionWindow = pDbeScreenPriv->PositionWindow; 1265 free(pDbeScreenPriv); 1266 } 1267 } 1268} /* DbeResetProc() */ 1269 1270/****************************************************************************** 1271 * 1272 * DBE DIX Procedure: DbeDestroyWindow 1273 * 1274 * Description: 1275 * 1276 * This is the wrapper for pScreen->DestroyWindow. 1277 * This function frees buffer resources for a window before it is 1278 * destroyed. 1279 * 1280 *****************************************************************************/ 1281 1282static Bool 1283DbeDestroyWindow(WindowPtr pWin) 1284{ 1285 DbeScreenPrivPtr pDbeScreenPriv; 1286 DbeWindowPrivPtr pDbeWindowPriv; 1287 ScreenPtr pScreen; 1288 Bool ret; 1289 1290 /* 1291 ************************************************************************** 1292 ** 1. Unwrap the member routine. 1293 ************************************************************************** 1294 */ 1295 1296 pScreen = pWin->drawable.pScreen; 1297 pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); 1298 pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; 1299 1300 /* 1301 ************************************************************************** 1302 ** 2. Do any work necessary before the member routine is called. 1303 ** 1304 ** Call the window priv delete function for all buffer IDs associated 1305 ** with this window. 1306 ************************************************************************** 1307 */ 1308 1309 if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) { 1310 while (pDbeWindowPriv) { 1311 /* *DbeWinPrivDelete() will free the window private and set it to 1312 * NULL if there are no more buffer IDs associated with this 1313 * window. 1314 */ 1315 FreeResource(pDbeWindowPriv->IDs[0], RT_NONE); 1316 pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); 1317 } 1318 } 1319 1320 /* 1321 ************************************************************************** 1322 ** 3. Call the member routine, saving its result if necessary. 1323 ************************************************************************** 1324 */ 1325 1326 ret = (*pScreen->DestroyWindow) (pWin); 1327 1328 /* 1329 ************************************************************************** 1330 ** 4. Rewrap the member routine, restoring the wrapper value first in case 1331 ** the wrapper (or something that it wrapped) change this value. 1332 ************************************************************************** 1333 */ 1334 1335 pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; 1336 pScreen->DestroyWindow = DbeDestroyWindow; 1337 1338 /* 1339 ************************************************************************** 1340 ** 5. Do any work necessary after the member routine has been called. 1341 ** 1342 ** In this case we do not need to do anything. 1343 ************************************************************************** 1344 */ 1345 1346 return ret; 1347 1348} /* DbeDestroyWindow() */ 1349 1350/****************************************************************************** 1351 * 1352 * DBE DIX Procedure: DbeExtensionInit 1353 * 1354 * Description: 1355 * 1356 * Called from InitExtensions in main() 1357 * 1358 *****************************************************************************/ 1359 1360void 1361DbeExtensionInit(void) 1362{ 1363 ExtensionEntry *extEntry; 1364 register int i, j; 1365 ScreenPtr pScreen = NULL; 1366 DbeScreenPrivPtr pDbeScreenPriv; 1367 int nStubbedScreens = 0; 1368 Bool ddxInitSuccess; 1369 1370#ifdef PANORAMIX 1371 if (!noPanoramiXExtension) 1372 return; 1373#endif 1374 1375 /* Create the resource types. */ 1376 dbeDrawableResType = 1377 CreateNewResourceType(DbeDrawableDelete, "dbeDrawable"); 1378 if (!dbeDrawableResType) 1379 return; 1380 dbeDrawableResType |= RC_DRAWABLE; 1381 1382 dbeWindowPrivResType = 1383 CreateNewResourceType(DbeWindowPrivDelete, "dbeWindow"); 1384 if (!dbeWindowPrivResType) 1385 return; 1386 1387 if (!dixRegisterPrivateKey(&dbeScreenPrivKeyRec, PRIVATE_SCREEN, 0)) 1388 return; 1389 1390 if (!dixRegisterPrivateKey(&dbeWindowPrivKeyRec, PRIVATE_WINDOW, 0)) 1391 return; 1392 1393 for (i = 0; i < screenInfo.numScreens; i++) { 1394 /* For each screen, set up DBE screen privates and init DIX and DDX 1395 * interface. 1396 */ 1397 1398 pScreen = screenInfo.screens[i]; 1399 1400 if (!(pDbeScreenPriv = malloc(sizeof(DbeScreenPrivRec)))) { 1401 /* If we can not alloc a window or screen private, 1402 * then free any privates that we already alloc'ed and return 1403 */ 1404 1405 for (j = 0; j < i; j++) { 1406 free(dixLookupPrivate(&screenInfo.screens[j]->devPrivates, 1407 dbeScreenPrivKey)); 1408 dixSetPrivate(&screenInfo.screens[j]->devPrivates, 1409 dbeScreenPrivKey, NULL); 1410 } 1411 return; 1412 } 1413 1414 dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, pDbeScreenPriv); 1415 1416 { 1417 /* We don't have DDX support for DBE anymore */ 1418 1419#ifndef DISABLE_MI_DBE_BY_DEFAULT 1420 /* Setup DIX. */ 1421 pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; 1422 1423 /* Setup DDX. */ 1424 ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv); 1425 1426 /* DDX DBE initialization may have the side affect of 1427 * reallocating pDbeScreenPriv, so we need to update it. 1428 */ 1429 pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); 1430 1431 if (ddxInitSuccess) { 1432 /* Wrap DestroyWindow. The DDX initialization function 1433 * already wrapped PositionWindow for us. 1434 */ 1435 1436 pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; 1437 pScreen->DestroyWindow = DbeDestroyWindow; 1438 } 1439 else { 1440 /* DDX initialization failed. Stub the screen. */ 1441 DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); 1442 } 1443#else 1444 DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); 1445#endif 1446 1447 } 1448 1449 } /* for (i = 0; i < screenInfo.numScreens; i++) */ 1450 1451 if (nStubbedScreens == screenInfo.numScreens) { 1452 /* All screens stubbed. Clean up and return. */ 1453 1454 for (i = 0; i < screenInfo.numScreens; i++) { 1455 free(dixLookupPrivate(&screenInfo.screens[i]->devPrivates, 1456 dbeScreenPrivKey)); 1457 dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, NULL); 1458 } 1459 return; 1460 } 1461 1462 /* Now add the extension. */ 1463 extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents, 1464 DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch, 1465 DbeResetProc, StandardMinorOpcode); 1466 1467 dbeErrorBase = extEntry->errorBase; 1468 SetResourceTypeErrorValue(dbeWindowPrivResType, 1469 dbeErrorBase + DbeBadBuffer); 1470 SetResourceTypeErrorValue(dbeDrawableResType, dbeErrorBase + DbeBadBuffer); 1471 1472} /* DbeExtensionInit() */ 1473