wsfb_driver.c revision 3e8a0de0
1/* 2 * Copyright © 2001-2012 Matthieu Herrb 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following 13 * disclaimer in the documentation and/or other materials provided 14 * with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 * 29 */ 30 31/* 32 * Based on fbdev.c written by: 33 * 34 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> 35 * Michel Dänzer, <michdaen@iiic.ethz.ch> 36 */ 37 38#ifdef HAVE_CONFIG_H 39#include "config.h" 40#endif 41 42#include <errno.h> 43#include <fcntl.h> 44#include <unistd.h> 45#include <sys/ioctl.h> 46#include <sys/types.h> 47#include <sys/mman.h> 48#include <sys/time.h> 49#include <errno.h> 50#include <dev/wscons/wsconsio.h> 51 52/* All drivers need this. */ 53#include "xf86.h" 54#include "xf86_OSproc.h" 55#include "xf86_OSlib.h" 56 57#include "mipointer.h" 58#include "micmap.h" 59#include "colormapst.h" 60#include "xf86cmap.h" 61#include "shadow.h" 62#include "dgaproc.h" 63 64/* For visuals */ 65#include "fb.h" 66 67#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 68#include "xf86Resources.h" 69#include "xf86RAC.h" 70#endif 71 72#ifdef XvExtension 73#include "xf86xv.h" 74#endif 75 76#include "wsfb.h" 77 78/* #include "wsconsio.h" */ 79 80#include <sys/mman.h> 81 82#ifdef X_PRIVSEP 83extern int priv_open_device(const char *); 84#else 85#define priv_open_device(n) open(n,O_RDWR|O_NONBLOCK|O_EXCL) 86#endif 87 88#if defined(__NetBSD__) 89#define WSFB_DEFAULT_DEV "/dev/ttyE0" 90#else 91#define WSFB_DEFAULT_DEV "/dev/ttyC0" 92#endif 93 94#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) > 6 95#define xf86LoaderReqSymLists(...) do {} while (0) 96#define LoaderRefSymLists(...) do {} while (0) 97#define xf86LoaderReqSymbols(...) do {} while (0) 98#endif 99 100#define DEBUG 0 101 102#if DEBUG 103# define TRACE_ENTER(str) ErrorF("wsfb: " str " %d\n",pScrn->scrnIndex) 104# define TRACE_EXIT(str) ErrorF("wsfb: " str " done\n") 105# define TRACE(str) ErrorF("wsfb trace: " str "\n") 106#else 107# define TRACE_ENTER(str) 108# define TRACE_EXIT(str) 109# define TRACE(str) 110#endif 111 112/* Prototypes */ 113static pointer WsfbSetup(pointer, pointer, int *, int *); 114static Bool WsfbGetRec(ScrnInfoPtr); 115static void WsfbFreeRec(ScrnInfoPtr); 116static const OptionInfoRec * WsfbAvailableOptions(int, int); 117static void WsfbIdentify(int); 118static Bool WsfbProbe(DriverPtr, int); 119static Bool WsfbPreInit(ScrnInfoPtr, int); 120static Bool WsfbScreenInit(SCREEN_INIT_ARGS_DECL); 121static Bool WsfbCloseScreen(CLOSE_SCREEN_ARGS_DECL); 122static void *WsfbWindowLinear(ScreenPtr, CARD32, CARD32, int, CARD32 *, 123 void *); 124#ifdef HAVE_SHADOW_AFB 125static void *WsfbWindowAfb(ScreenPtr, CARD32, CARD32, int, CARD32 *, 126 void *); 127#endif 128static void WsfbPointerMoved(SCRN_ARG_TYPE, int, int); 129static Bool WsfbEnterVT(VT_FUNC_ARGS_DECL); 130static void WsfbLeaveVT(VT_FUNC_ARGS_DECL); 131static Bool WsfbSwitchMode(SWITCH_MODE_ARGS_DECL); 132static int WsfbValidMode(SCRN_ARG_TYPE, DisplayModePtr, Bool, int); 133static void WsfbLoadPalette(ScrnInfoPtr, int, int *, LOCO *, VisualPtr); 134static Bool WsfbSaveScreen(ScreenPtr, int); 135static void WsfbSave(ScrnInfoPtr); 136static void WsfbRestore(ScrnInfoPtr); 137 138/* DGA stuff */ 139#ifdef XFreeXDGA 140static Bool WsfbDGAOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, 141 int *, int *, int *); 142static Bool WsfbDGASetMode(ScrnInfoPtr, DGAModePtr); 143static void WsfbDGASetViewport(ScrnInfoPtr, int, int, int); 144static Bool WsfbDGAInit(ScrnInfoPtr, ScreenPtr); 145#endif 146 147static void WsfbShadowUpdateSwap32(ScreenPtr, shadowBufPtr); 148static void WsfbShadowUpdateSplit(ScreenPtr, shadowBufPtr); 149 150static Bool WsfbDriverFunc(ScrnInfoPtr, xorgDriverFuncOp, pointer); 151 152/* Helper functions */ 153static int wsfb_open(const char *); 154static pointer wsfb_mmap(size_t, off_t, int); 155 156enum { WSFB_ROTATE_NONE = 0, 157 WSFB_ROTATE_CCW = 90, 158 WSFB_ROTATE_UD = 180, 159 WSFB_ROTATE_CW = 270 160}; 161 162/* 163 * This is intentionally screen-independent. 164 * It indicates the binding choice made in the first PreInit. 165 */ 166static int pix24bpp = 0; 167 168#define WSFB_VERSION 4000 169#define WSFB_NAME "wsfb" 170#define WSFB_DRIVER_NAME "wsfb" 171 172_X_EXPORT DriverRec WSFB = { 173 WSFB_VERSION, 174 WSFB_DRIVER_NAME, 175 WsfbIdentify, 176 WsfbProbe, 177 WsfbAvailableOptions, 178 NULL, 179 0, 180 WsfbDriverFunc 181}; 182 183/* Supported "chipsets" */ 184static SymTabRec WsfbChipsets[] = { 185 { 0, "wsfb" }, 186 { -1, NULL } 187}; 188 189/* Supported options */ 190typedef enum { 191 OPTION_SHADOW_FB, 192 OPTION_ROTATE, 193 OPTION_HW_CURSOR, 194 OPTION_SW_CURSOR 195} WsfbOpts; 196 197static const OptionInfoRec WsfbOptions[] = { 198 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, 199 { OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE}, 200 { OPTION_HW_CURSOR, "HWCursor", OPTV_BOOLEAN, {1}, FALSE}, 201 { -1, NULL, OPTV_NONE, {0}, FALSE} 202}; 203 204#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) <= 6 205/* Symbols needed from other modules */ 206static const char *fbSymbols[] = { 207 "fbPictureInit", 208 "fbScreenInit", 209 NULL 210}; 211static const char *shadowSymbols[] = { 212 "shadowAdd", 213 "shadowSetup", 214 "shadowUpdatePacked", 215 "shadowUpdatePackedWeak", 216 "shadowUpdateRotatePacked", 217 "shadowUpdateRotatePackedWeak", 218#ifdef HAVE_SHADOW_AFB 219 "shadowUpdateAfb8", 220#endif 221 NULL 222}; 223 224static const char *ramdacSymbols[] = { 225 "xf86CreateCursorInfoRec", 226 "xf86DestroyCursorInfoRec", 227 "xf86InitCursor", 228 NULL 229}; 230#endif 231 232static XF86ModuleVersionInfo WsfbVersRec = { 233 "wsfb", 234 MODULEVENDORSTRING, 235 MODINFOSTRING1, 236 MODINFOSTRING2, 237 XORG_VERSION_CURRENT, 238 PACKAGE_VERSION_MAJOR, 239 PACKAGE_VERSION_MINOR, 240 PACKAGE_VERSION_PATCHLEVEL, 241 ABI_CLASS_VIDEODRV, 242 ABI_VIDEODRV_VERSION, 243 NULL, 244 {0, 0, 0, 0} 245}; 246 247_X_EXPORT XF86ModuleData wsfbModuleData = { &WsfbVersRec, WsfbSetup, NULL }; 248 249static pointer 250WsfbSetup(pointer module, pointer opts, int *errmaj, int *errmin) 251{ 252 static Bool setupDone = FALSE; 253 254#if !(defined __NetBSD__ || defined __OpenBSD__) 255 /* Check that we're being loaded on a OpenBSD or NetBSD system. */ 256 if (errmaj) 257 *errmaj = LDR_BADOS; 258 if (errmin) 259 *errmin = 0; 260 return NULL; 261#endif 262 if (!setupDone) { 263 setupDone = TRUE; 264 xf86AddDriver(&WSFB, module, HaveDriverFuncs); 265 LoaderRefSymLists(fbSymbols, shadowSymbols, ramdacSymbols, 266 NULL); 267 return (pointer)1; 268 } else { 269 if (errmaj != NULL) 270 *errmaj = LDR_ONCEONLY; 271 return NULL; 272 } 273} 274 275static Bool 276WsfbGetRec(ScrnInfoPtr pScrn) 277{ 278 279 if (pScrn->driverPrivate != NULL) 280 return TRUE; 281 282 pScrn->driverPrivate = xnfcalloc(sizeof(WsfbRec), 1); 283 return TRUE; 284} 285 286static void 287WsfbFreeRec(ScrnInfoPtr pScrn) 288{ 289 290 if (pScrn->driverPrivate == NULL) 291 return; 292 free(pScrn->driverPrivate); 293 pScrn->driverPrivate = NULL; 294} 295 296static const OptionInfoRec * 297WsfbAvailableOptions(int chipid, int busid) 298{ 299 return WsfbOptions; 300} 301 302static void 303WsfbIdentify(int flags) 304{ 305 xf86PrintChipsets(WSFB_NAME, "driver for wsdisplay framebuffer", 306 WsfbChipsets); 307} 308 309/* Open the framebuffer device. */ 310static int 311wsfb_open(const char *dev) 312{ 313 int fd = -1; 314 315 /* Try argument from xorg.conf first. */ 316 if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) { 317 /* Second: environment variable. */ 318 dev = getenv("XDEVICE"); 319 if (dev == NULL || ((fd = priv_open_device(dev)) == -1)) { 320 /* Last try: default device. */ 321 dev = WSFB_DEFAULT_DEV; 322 if ((fd = priv_open_device(dev)) == -1) { 323 return -1; 324 } 325 } 326 } 327 return fd; 328} 329 330/* Map the framebuffer's memory. */ 331static pointer 332wsfb_mmap(size_t len, off_t off, int fd) 333{ 334 int pagemask, mapsize; 335 caddr_t addr; 336 pointer mapaddr; 337 338 pagemask = getpagesize() - 1; 339 mapsize = ((int) len + pagemask) & ~pagemask; 340 addr = 0; 341 342 /* 343 * Try and make it private first, that way once we get it, an 344 * interloper, e.g. another server, can't get this frame buffer, 345 * and if another server already has it, this one won't. 346 */ 347 mapaddr = (pointer) mmap(addr, mapsize, 348 PROT_READ | PROT_WRITE, MAP_SHARED, 349 fd, off); 350 if (mapaddr == MAP_FAILED) { 351 mapaddr = NULL; 352 } 353#if DEBUG 354 ErrorF("mmap returns: addr %p len 0x%x\n", mapaddr, mapsize); 355#endif 356 return mapaddr; 357} 358 359static Bool 360WsfbProbe(DriverPtr drv, int flags) 361{ 362 int i, fd, entity; 363 GDevPtr *devSections; 364 int numDevSections; 365 const char *dev; 366 Bool foundScreen = FALSE; 367 368 TRACE("probe start"); 369 370 /* For now, just bail out for PROBE_DETECT. */ 371 if (flags & PROBE_DETECT) 372 return FALSE; 373 374 if ((numDevSections = xf86MatchDevice(WSFB_DRIVER_NAME, 375 &devSections)) <= 0) 376 return FALSE; 377 378 /* Do not attach if the modesetting driver is active */ 379 if (fbSlotClaimed == TRUE) { 380 DriverPtr fbSlotDrv = xf86GetEntityInfo(0)->driver; 381 if (strcmp(fbSlotDrv->driverName, "modesetting") == 0) 382 return FALSE; 383 } 384 385 for (i = 0; i < numDevSections; i++) { 386 ScrnInfoPtr pScrn = NULL; 387 388 dev = xf86FindOptionValue(devSections[i]->options, "device"); 389 if ((fd = wsfb_open(dev)) >= 0) { 390 entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE); 391 pScrn = xf86ConfigFbEntity(NULL,0,entity, 392 NULL,NULL,NULL,NULL); 393 if (pScrn != NULL) { 394 foundScreen = TRUE; 395 pScrn->driverVersion = WSFB_VERSION; 396 pScrn->driverName = WSFB_DRIVER_NAME; 397 pScrn->name = WSFB_NAME; 398 pScrn->Probe = WsfbProbe; 399 pScrn->PreInit = WsfbPreInit; 400 pScrn->ScreenInit = WsfbScreenInit; 401 pScrn->SwitchMode = WsfbSwitchMode; 402 pScrn->AdjustFrame = NULL; 403 pScrn->EnterVT = WsfbEnterVT; 404 pScrn->LeaveVT = WsfbLeaveVT; 405 pScrn->ValidMode = WsfbValidMode; 406 407 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 408 "using %s\n", dev != NULL ? dev : 409 "default device"); 410 } 411 } 412 } 413 free(devSections); 414 TRACE("probe done"); 415 return foundScreen; 416} 417 418static Bool 419WsfbPreInit(ScrnInfoPtr pScrn, int flags) 420{ 421 WsfbPtr fPtr; 422 int default_depth, bitsperpixel, wstype; 423 const char *dev, *s; 424 char *mod = NULL; 425 const char *reqSym = NULL; 426 Gamma zeros = {0.0, 0.0, 0.0}; 427 DisplayModePtr mode; 428 MessageType from; 429 430 if (flags & PROBE_DETECT) return FALSE; 431 432 TRACE_ENTER("PreInit"); 433 434 if (pScrn->numEntities != 1) return FALSE; 435 436 pScrn->monitor = pScrn->confScreen->monitor; 437 438 WsfbGetRec(pScrn); 439 fPtr = WSFBPTR(pScrn); 440 441 fPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 442 443#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 444 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT; 445 pScrn->racIoFlags = pScrn->racMemFlags; 446#endif 447 448 dev = xf86FindOptionValue(fPtr->pEnt->device->options, "device"); 449 fPtr->fd = wsfb_open(dev); 450 if (fPtr->fd == -1) { 451 return FALSE; 452 } 453 454 if (ioctl(fPtr->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) { 455 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 456 "ioctl WSDISPLAY_GTYPE: %s\n", 457 strerror(errno)); 458 wstype = WSDISPLAY_TYPE_UNKNOWN; 459 } 460 461 if (ioctl(fPtr->fd, WSDISPLAYIO_GET_FBINFO, &fPtr->fbi) != 0) { 462 struct wsdisplay_fbinfo info; 463 struct wsdisplayio_fbinfo *fbi = &fPtr->fbi; 464 int lb; 465 466 xf86Msg(X_WARNING, "ioctl(WSDISPLAYIO_GET_FBINFO) failed, " \ 467 "falling back to old method\n"); 468 if (ioctl(fPtr->fd, WSDISPLAYIO_GINFO, &info) == -1) { 469 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 470 "ioctl WSDISPLAY_GINFO: %s\n", 471 strerror(errno)); 472 return FALSE; 473 } 474 if (ioctl(fPtr->fd, WSDISPLAYIO_LINEBYTES, &lb) == -1) { 475 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 476 "ioctl WSDISPLAYIO_LINEBYTES: %s\n", 477 strerror(errno)); 478 return FALSE; 479 } 480 /* ok, fake up a new style fbinfo */ 481 fbi->fbi_width = info.width; 482 fbi->fbi_height = info.height; 483 fbi->fbi_stride = lb; 484 fbi->fbi_bitsperpixel = info.depth; 485 if (info.depth > 16) { 486 fbi->fbi_pixeltype = WSFB_RGB; 487 if (wstype == WSDISPLAY_TYPE_SUN24 || 488 wstype == WSDISPLAY_TYPE_SUNCG12 || 489 wstype == WSDISPLAY_TYPE_SUNCG14 || 490 wstype == WSDISPLAY_TYPE_SUNTCX || 491 wstype == WSDISPLAY_TYPE_SUNFFB || 492 wstype == WSDISPLAY_TYPE_XVR1000 || 493 wstype == WSDISPLAY_TYPE_VC4) { 494 fbi->fbi_subtype.fbi_rgbmasks.red_offset = 0; 495 fbi->fbi_subtype.fbi_rgbmasks.red_size = 8; 496 fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8; 497 fbi->fbi_subtype.fbi_rgbmasks.green_size = 8; 498 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 16; 499 fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8; 500 } else { 501 fbi->fbi_subtype.fbi_rgbmasks.red_offset = 16; 502 fbi->fbi_subtype.fbi_rgbmasks.red_size = 8; 503 fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8; 504 fbi->fbi_subtype.fbi_rgbmasks.green_size = 8; 505 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0; 506 fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8; 507 } 508 fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0; 509 fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0; 510 } else if (info.depth <= 8) { 511 fbi->fbi_pixeltype = WSFB_CI; 512 fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = info.cmsize; 513 } 514 fbi->fbi_flags = 0; 515 fbi->fbi_fbsize = lb * info.height; 516#ifdef WSDISPLAY_TYPE_LUNA 517 if (wstype == WSDISPLAY_TYPE_LUNA) { 518 /* 519 * XXX 520 * LUNA's FB seems to have 64 dot (8 byte) offset. 521 * This might be able to be changed in kernel 522 * lunafb driver, but current setting was pulled 523 * from 4.4BSD-Lite2/luna68k. 524 */ 525 fbi->fbi_fboffset = 8; 526 } else 527#endif 528 fbi->fbi_fboffset = 0; 529 } 530 xf86Msg(X_INFO, "fboffset %x\n", (int)fPtr->fbi.fbi_fboffset); 531 /* 532 * Allocate room for saving the colormap. 533 */ 534 if (fPtr->fbi.fbi_pixeltype == WSFB_CI && 535 fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries > 0) { 536 fPtr->saved_cmap.red = 537 (unsigned char *)malloc(fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries); 538 if (fPtr->saved_cmap.red == NULL) { 539 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 540 "Cannot malloc %d bytes\n", 541 fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries); 542 return FALSE; 543 } 544 fPtr->saved_cmap.green = 545 (unsigned char *)malloc(fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries); 546 if (fPtr->saved_cmap.green == NULL) { 547 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 548 "Cannot malloc %d bytes\n", 549 fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries); 550 free(fPtr->saved_cmap.red); 551 return FALSE; 552 } 553 fPtr->saved_cmap.blue = 554 (unsigned char *)malloc(fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries); 555 if (fPtr->saved_cmap.blue == NULL) { 556 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 557 "Cannot malloc %d bytes\n", 558 fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries); 559 free(fPtr->saved_cmap.red); 560 free(fPtr->saved_cmap.green); 561 return FALSE; 562 } 563 } 564 565 /* Handle depth */ 566 default_depth = fPtr->fbi.fbi_bitsperpixel <= 24 ? fPtr->fbi.fbi_bitsperpixel : 24; 567 bitsperpixel = fPtr->fbi.fbi_bitsperpixel == 15 ? 16 : fPtr->fbi.fbi_bitsperpixel; 568#if defined(__NetBSD__) && defined(WSDISPLAY_TYPE_LUNA) 569 if (wstype == WSDISPLAY_TYPE_LUNA) { 570 /* 571 * XXX 572 * LUNA's color framebuffers support 4bpp or 8bpp 573 * but they have multiple 1bpp VRAM planes like ancient VGA. 574 * For now, Xorg server supports only the first one plane 575 * as 1bpp monochrome server. 576 * 577 * Note OpenBSD/luna88k workarounds this by switching depth 578 * and palette settings by WSDISPLAYIO_SETGFXMODE ioctl. 579 */ 580 default_depth = 1; 581 bitsperpixel = 1; 582 } 583#endif 584#ifdef WSDISPLAY_TYPE_AMIGACC 585 if (wstype == WSDISPLAY_TYPE_AMIGACC) { 586 /* 587 * Video memory is organized in bitplanes. 588 * 8bpp or 1bpp supported in this driver. 589 * With 8bpp conversion to bitplane format 590 * is done in shadow update proc. 591 * With 1bpp no conversion needed. 592 */ 593#ifdef HAVE_SHADOW_AFB 594 if (bitsperpixel == 8) { 595 fPtr->planarAfb = TRUE; 596 } else 597#endif 598 { 599 default_depth = 1; 600 bitsperpixel = 1; 601 } 602 } 603#endif 604 605 if (!xf86SetDepthBpp(pScrn, default_depth, default_depth, 606 bitsperpixel, 607 bitsperpixel >= 24 ? Support24bppFb|Support32bppFb : 0)) 608 return FALSE; 609 610 /* Check consistency. */ 611 if (pScrn->bitsPerPixel != bitsperpixel) { 612 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 613 "specified depth (%d) or bpp (%d) doesn't match " 614 "framebuffer depth (%d)\n", pScrn->depth, 615 pScrn->bitsPerPixel, bitsperpixel); 616 return FALSE; 617 } 618 xf86PrintDepthBpp(pScrn); 619 620 /* Get the depth24 pixmap format. */ 621 if (pScrn->depth == 24 && pix24bpp == 0) 622 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 623 624 /* Handle options. */ 625 xf86CollectOptions(pScrn, NULL); 626 fPtr->Options = (OptionInfoRec *)malloc(sizeof(WsfbOptions)); 627 if (fPtr->Options == NULL) 628 return FALSE; 629 memcpy(fPtr->Options, WsfbOptions, sizeof(WsfbOptions)); 630 xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options, 631 fPtr->Options); 632 633 /* Use shadow framebuffer by default, on depth >= 8 */ 634 xf86Msg(X_INFO, "fbi_flags: %x\n", fPtr->fbi.fbi_flags); 635 if ((pScrn->depth >= 8) && 636 ((fPtr->fbi.fbi_flags & WSFB_VRAM_IS_RAM) == 0)) { 637 fPtr->shadowFB = xf86ReturnOptValBool(fPtr->Options, 638 OPTION_SHADOW_FB, TRUE); 639 } else 640 if (xf86ReturnOptValBool(fPtr->Options, 641 OPTION_SHADOW_FB, FALSE)) { 642 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 643 "Shadow FB option ignored on depth < 8\n"); 644 } 645 if (fPtr->fbi.fbi_flags & WSFB_VRAM_IS_SPLIT) { 646 if (!fPtr->shadowFB) { 647 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 648 "Shadow FB forced on for split framebuffer\n"); 649 fPtr->shadowFB = TRUE; 650 } 651 } 652 /* Rotation */ 653 fPtr->rotate = WSFB_ROTATE_NONE; 654 if ((s = xf86GetOptValString(fPtr->Options, OPTION_ROTATE))) { 655 if (pScrn->depth >= 8) { 656 if (!xf86NameCmp(s, "CW")) { 657 fPtr->shadowFB = TRUE; 658 fPtr->rotate = WSFB_ROTATE_CW; 659 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 660 "Rotating screen clockwise\n"); 661 } else if (!xf86NameCmp(s, "CCW")) { 662 fPtr->shadowFB = TRUE; 663 fPtr->rotate = WSFB_ROTATE_CCW; 664 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 665 "Rotating screen counter clockwise\n"); 666 } else if (!xf86NameCmp(s, "UD")) { 667 fPtr->shadowFB = TRUE; 668 fPtr->rotate = WSFB_ROTATE_UD; 669 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 670 "Rotating screen upside down\n"); 671 } else { 672 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 673 "\"%s\" is not a valid value for Option " 674 "\"Rotate\"\n", s); 675 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 676 "Valid options are \"CW\", \"CCW\"," 677 " or \"UD\"\n"); 678 } 679 } else { 680 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 681 "Option \"Rotate\" ignored on depth < 8\n"); 682 } 683 } 684 685 686 fPtr->useSwap32 = FALSE; 687 /* Color weight */ 688 if (fPtr->fbi.fbi_pixeltype == WSFB_RGB) { 689 rgb zeros = { 0, 0, 0 }, masks; 690 691 if (fPtr->fbi.fbi_subtype.fbi_rgbmasks.red_size > 0) { 692 uint32_t msk; 693 694 /* 695 * see if we need to byte-swap pixels 696 * XXX this requires a shadow FB and is incompatible 697 * (for now ) with rotation 698 */ 699 if ((fPtr->fbi.fbi_bitsperpixel == 32) && 700 (fPtr->fbi.fbi_subtype.fbi_rgbmasks.blue_offset == 24) && 701 (fPtr->rotate == WSFB_ROTATE_NONE) && 702 (fPtr->shadowFB == TRUE)) { 703 /* 704 * looks like BGRA - set the swap flag and flip 705 * the offsets 706 */ 707 xf86Msg(X_INFO, "endian-flipped RGB framebuffer " 708 "detected, using WsfbShadowUpdateSwap32()\n"); 709 fPtr->fbi.fbi_subtype.fbi_rgbmasks.blue_offset = 0; 710 fPtr->fbi.fbi_subtype.fbi_rgbmasks.green_offset = 8; 711 fPtr->fbi.fbi_subtype.fbi_rgbmasks.red_offset = 16; 712 fPtr->fbi.fbi_subtype.fbi_rgbmasks.alpha_offset = 24; 713 fPtr->useSwap32 = TRUE; 714 } 715 716 msk = 0xffffffff; 717 msk = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.red_size; 718 msk = ~msk; 719 masks.red = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.red_offset; 720 721 msk = 0xffffffff; 722 msk = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.green_size; 723 msk = ~msk; 724 masks.green = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.green_offset; 725 726 msk = 0xffffffff; 727 msk = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.blue_size; 728 msk = ~msk; 729 masks.blue = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.blue_offset; 730 xf86Msg(X_INFO, "masks generated: %08lx %08lx %08lx\n", 731 (unsigned long)masks.red, 732 (unsigned long)masks.green, 733 (unsigned long)masks.blue); 734 } else { 735 masks.red = 0; 736 masks.green = 0; 737 masks.blue = 0; 738 } 739 740 if (!xf86SetWeight(pScrn, zeros, masks)) 741 return FALSE; 742 } 743 744 /* Visual init */ 745 if (!xf86SetDefaultVisual(pScrn, -1)) 746 return FALSE; 747 748 /* We don't currently support DirectColor at > 8bpp . */ 749 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 750 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 751 " (%s) is not supported at depth %d\n", 752 xf86GetVisualName(pScrn->defaultVisual), 753 pScrn->depth); 754 return FALSE; 755 } 756 757 xf86SetGamma(pScrn,zeros); 758 759 pScrn->progClock = TRUE; 760 pScrn->rgbBits = (pScrn->depth >= 8) ? 8 : pScrn->depth; 761 pScrn->chipset = "wsfb"; 762 pScrn->videoRam = fPtr->fbi.fbi_fbsize; 763 764 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Vidmem: %dk\n", 765 pScrn->videoRam/1024); 766 767 /* Fake video mode struct. */ 768 mode = (DisplayModePtr)malloc(sizeof(DisplayModeRec)); 769 mode->prev = mode; 770 mode->next = mode; 771 mode->name = "wsfb current mode"; 772 mode->status = MODE_OK; 773 mode->type = M_T_BUILTIN; 774 mode->Clock = 0; 775 mode->HDisplay = fPtr->fbi.fbi_width; 776 mode->HSyncStart = 0; 777 mode->HSyncEnd = 0; 778 mode->HTotal = 0; 779 mode->HSkew = 0; 780 mode->VDisplay = fPtr->fbi.fbi_height; 781 mode->VSyncStart = 0; 782 mode->VSyncEnd = 0; 783 mode->VTotal = 0; 784 mode->VScan = 0; 785 mode->Flags = 0; 786 if (pScrn->modes != NULL) { 787 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 788 "Ignoring mode specification from screen section\n"); 789 } 790 pScrn->currentMode = pScrn->modes = mode; 791 pScrn->virtualX = fPtr->fbi.fbi_width; 792 pScrn->virtualY = fPtr->fbi.fbi_height; 793 pScrn->displayWidth = pScrn->virtualX; 794 795 /* Set the display resolution. */ 796 xf86SetDpi(pScrn, 0, 0); 797 798 from = X_DEFAULT; 799 fPtr->HWCursor = TRUE; 800 if (xf86GetOptValBool(fPtr->Options, OPTION_HW_CURSOR, &fPtr->HWCursor)) 801 from = X_CONFIG; 802 if (xf86ReturnOptValBool(fPtr->Options, OPTION_SW_CURSOR, FALSE)) { 803 from = X_CONFIG; 804 fPtr->HWCursor = FALSE; 805 } 806 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 807 fPtr->HWCursor ? "HW" : "SW"); 808 809 /* Load bpp-specific modules. */ 810 switch(pScrn->bitsPerPixel) { 811 case 1: 812 case 4: 813 default: 814 mod = "fb"; 815 break; 816 } 817 818 819 /* Load shadow if needed. */ 820 if (fPtr->shadowFB) { 821 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 822 "Using \"Shadow Framebuffer\"\n"); 823 if (xf86LoadSubModule(pScrn, "shadow") == NULL) { 824 WsfbFreeRec(pScrn); 825 return FALSE; 826 } 827 } 828 829 if (mod && xf86LoadSubModule(pScrn, mod) == NULL) { 830 WsfbFreeRec(pScrn); 831 return FALSE; 832 } 833 834 if (xf86LoadSubModule(pScrn, "ramdac") == NULL) { 835 WsfbFreeRec(pScrn); 836 return FALSE; 837 } 838 839 if (mod) { 840 if (reqSym) { 841 xf86LoaderReqSymbols(reqSym, NULL); 842 } else { 843 xf86LoaderReqSymLists(fbSymbols, NULL); 844 } 845 } 846 TRACE_EXIT("PreInit"); 847 return TRUE; 848} 849 850static Bool 851WsfbCreateScreenResources(ScreenPtr pScreen) 852{ 853 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 854 WsfbPtr fPtr = WSFBPTR(pScrn); 855 PixmapPtr pPixmap; 856 Bool ret; 857 void (*shadowproc)(ScreenPtr, shadowBufPtr); 858 ShadowWindowProc windowproc = WsfbWindowLinear; 859 860 pScreen->CreateScreenResources = fPtr->CreateScreenResources; 861 ret = pScreen->CreateScreenResources(pScreen); 862 pScreen->CreateScreenResources = WsfbCreateScreenResources; 863 864 if (!ret) 865 return FALSE; 866 867 pPixmap = pScreen->GetScreenPixmap(pScreen); 868 if (fPtr->fbi.fbi_flags & WSFB_VRAM_IS_SPLIT) { 869 shadowproc = WsfbShadowUpdateSplit; 870 } else if (fPtr->useSwap32) { 871 shadowproc = WsfbShadowUpdateSwap32; 872 } else if (fPtr->rotate) { 873 shadowproc = shadowUpdateRotatePacked; 874 } else 875#ifdef HAVE_SHADOW_AFB 876 if (fPtr->planarAfb) { 877 shadowproc = shadowUpdateAfb8; 878 windowproc = WsfbWindowAfb; 879 } else 880#endif 881 { 882 shadowproc = shadowUpdatePacked; 883 } 884 885 if (!shadowAdd(pScreen, pPixmap, shadowproc, 886 windowproc, fPtr->rotate, NULL)) { 887 return FALSE; 888 } 889 return TRUE; 890} 891 892 893static Bool 894WsfbShadowInit(ScreenPtr pScreen) 895{ 896 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 897 WsfbPtr fPtr = WSFBPTR(pScrn); 898 899 if (!shadowSetup(pScreen)) 900 return FALSE; 901 fPtr->CreateScreenResources = pScreen->CreateScreenResources; 902 pScreen->CreateScreenResources = WsfbCreateScreenResources; 903 904 return TRUE; 905} 906 907static Bool 908WsfbScreenInit(SCREEN_INIT_ARGS_DECL) 909{ 910 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 911 WsfbPtr fPtr = WSFBPTR(pScrn); 912 VisualPtr visual; 913 int ret, flags, ncolors; 914 int wsmode = WSDISPLAYIO_MODE_DUMBFB; 915 int wstype; 916 int width; 917 size_t len; 918 919 TRACE_ENTER("WsfbScreenInit"); 920#if DEBUG 921 ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n" 922 "\tmask: %x,%x,%x, offset: %u,%u,%u\n", 923 pScrn->bitsPerPixel, 924 pScrn->depth, 925 xf86GetVisualName(pScrn->defaultVisual), 926 pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue, 927 pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue); 928#endif 929 switch (fPtr->fbi.fbi_bitsperpixel) { 930 case 1: 931 case 4: 932 case 8: 933 len = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 934#ifdef HAVE_SHADOW_AFB 935 if (fPtr->planarAfb) { 936 /* 937 * stride is "bytes per line" for each plane so 938 * we need a number of planes to mmap in planar case. 939 */ 940 len *= fPtr->fbi.fbi_bitsperpixel; 941 } 942#endif 943 944 break; 945 case 15: 946 case 16: 947 if (fPtr->fbi.fbi_stride == fPtr->fbi.fbi_width) { 948 xf86Msg(X_ERROR, "Bogus stride == width in 16bit colour\n"); 949 len = fPtr->fbi.fbi_width * fPtr->fbi.fbi_height * sizeof(short); 950 } else { 951 len = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 952 } 953 break; 954 case 24: 955 if (fPtr->fbi.fbi_stride == fPtr->fbi.fbi_width) { 956 xf86Msg(X_ERROR, "Bogus stride == width in 24bit colour\n"); 957 len = fPtr->fbi.fbi_width * fPtr->fbi.fbi_height * 3; 958 } else { 959 len = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 960 } 961 break; 962 case 32: 963 if (fPtr->fbi.fbi_stride == fPtr->fbi.fbi_width) { 964 xf86Msg(X_ERROR, "Bogus stride == width in 32bit colour\n"); 965 len = fPtr->fbi.fbi_width * fPtr->fbi.fbi_height * sizeof(int); 966 } else { 967 len = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 968 } 969 break; 970 default: 971 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 972 "unsupported depth %d\n", fPtr->fbi.fbi_bitsperpixel); 973 return FALSE; 974 } 975 /* Switch to graphics mode - required before mmap. */ 976 if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) { 977 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 978 "ioctl WSDISPLAYIO_SMODE: %s\n", 979 strerror(errno)); 980 return FALSE; 981 } 982 /* Get wsdisplay type to handle quirks */ 983 if (ioctl(fPtr->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) { 984 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 985 "ioctl WSDISPLAY_GTYPE: %s\n", 986 strerror(errno)); 987 return FALSE; 988 } 989 len = max(len, fPtr->fbi.fbi_fbsize); 990 fPtr->fbmem = wsfb_mmap(len + fPtr->fbi.fbi_fboffset, 0, fPtr->fd); 991 992 if (fPtr->fbmem == NULL) { 993 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 994 "wsfb_mmap: %s\n", strerror(errno)); 995 return FALSE; 996 } 997 fPtr->fbmem_len = len; 998 999 WsfbSave(pScrn); 1000 pScrn->vtSema = TRUE; 1001 1002 /* MI layer */ 1003 miClearVisualTypes(); 1004 if (pScrn->bitsPerPixel > 8) { 1005 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 1006 pScrn->rgbBits, TrueColor)) 1007 return FALSE; 1008 } else { 1009 if (!miSetVisualTypes(pScrn->depth, 1010 miGetDefaultVisualMask(pScrn->depth), 1011 pScrn->rgbBits, pScrn->defaultVisual)) 1012 return FALSE; 1013 } 1014 if (!miSetPixmapDepths()) 1015 return FALSE; 1016 1017 if (fPtr->rotate == WSFB_ROTATE_CW 1018 || fPtr->rotate == WSFB_ROTATE_CCW) { 1019 int tmp = pScrn->virtualX; 1020 pScrn->virtualX = pScrn->displayWidth = pScrn->virtualY; 1021 pScrn->virtualY = tmp; 1022 } 1023 if (fPtr->rotate && !fPtr->PointerMoved) { 1024 fPtr->PointerMoved = pScrn->PointerMoved; 1025 pScrn->PointerMoved = WsfbPointerMoved; 1026 } 1027 1028 fPtr->fbstart = fPtr->fbmem + fPtr->fbi.fbi_fboffset; 1029 1030 if (fPtr->shadowFB) { 1031 if (fPtr->rotate) { 1032 /* 1033 * Note Rotate and Shadow FB options are valid 1034 * only on depth >= 8. 1035 */ 1036 len = pScrn->virtualX * pScrn->virtualY * 1037 (pScrn->bitsPerPixel >> 3); 1038 } else 1039#ifdef HAVE_SHADOW_AFB 1040 if (fPtr->planarAfb) { 1041 /* always 8bpp */ 1042 len = pScrn->virtualX * pScrn->virtualY; 1043 } else 1044#endif 1045 { 1046 len = fPtr->fbi.fbi_stride * pScrn->virtualY; 1047 } 1048 fPtr->shadow = calloc(1, len); 1049 1050 if (!fPtr->shadow) { 1051 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1052 "Failed to allocate shadow framebuffer\n"); 1053 return FALSE; 1054 } 1055 } 1056 1057 /* 1058 * fbScreenInit() seems to require "pixel width of frame buffer" 1059 * but it is actually "stride in pixel" of frame buffer, 1060 * per xorg/xserver/tree/fb/fbscreen.c. 1061 */ 1062 if (fPtr->rotate) { 1063 width = pScrn->displayWidth; 1064 } else 1065#ifdef HAVE_SHADOW_AFB 1066 if (fPtr->planarAfb) { 1067 width = pScrn->displayWidth; 1068 } else 1069#endif 1070 { 1071 if (pScrn->bitsPerPixel > 8) { 1072 width = 1073 fPtr->fbi.fbi_stride / (pScrn->bitsPerPixel >> 3); 1074 } else { 1075 width = 1076 fPtr->fbi.fbi_stride * (8 / pScrn->bitsPerPixel); 1077 } 1078 } 1079 switch (pScrn->bitsPerPixel) { 1080 case 1: 1081 ret = fbScreenInit(pScreen, 1082 fPtr->fbstart, 1083 pScrn->virtualX, pScrn->virtualY, 1084 pScrn->xDpi, pScrn->yDpi, 1085 width, pScrn->bitsPerPixel); 1086 break; 1087 case 4: 1088 case 8: 1089 case 16: 1090 case 24: 1091 case 32: 1092 ret = fbScreenInit(pScreen, 1093 fPtr->shadowFB ? fPtr->shadow : fPtr->fbstart, 1094 pScrn->virtualX, pScrn->virtualY, 1095 pScrn->xDpi, pScrn->yDpi, 1096 width, 1097 pScrn->bitsPerPixel); 1098 break; 1099 default: 1100 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1101 "Unsupported bpp: %d\n", pScrn->bitsPerPixel); 1102 return FALSE; 1103 } /* case */ 1104 1105 if (!ret) 1106 return FALSE; 1107 1108 if (pScrn->bitsPerPixel > 8) { 1109 /* Fixup RGB ordering. */ 1110 visual = pScreen->visuals + pScreen->numVisuals; 1111 while (--visual >= pScreen->visuals) { 1112 if ((visual->class | DynamicClass) == DirectColor) { 1113 visual->offsetRed = pScrn->offset.red; 1114 visual->offsetGreen = pScrn->offset.green; 1115 visual->offsetBlue = pScrn->offset.blue; 1116 visual->redMask = pScrn->mask.red; 1117 visual->greenMask = pScrn->mask.green; 1118 visual->blueMask = pScrn->mask.blue; 1119 } 1120 } 1121 } 1122 1123 if (pScrn->bitsPerPixel >= 8) { 1124 if (!fbPictureInit(pScreen, NULL, 0)) 1125 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1126 "RENDER extension initialisation failed.\n"); 1127 } 1128 if (fPtr->shadowFB && !WsfbShadowInit(pScreen)) { 1129 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1130 "shadow framebuffer initialization failed\n"); 1131 return FALSE; 1132 } 1133 1134#ifdef XFreeXDGA 1135 if (!fPtr->rotate) 1136 WsfbDGAInit(pScrn, pScreen); 1137 else 1138 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotated display, " 1139 "disabling DGA\n"); 1140#endif 1141 if (fPtr->rotate) { 1142 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Driver Rotation, " 1143 "disabling RandR\n"); 1144#if 0 1145 xf86DisableRandR(); 1146#endif 1147 if (pScrn->bitsPerPixel == 24) 1148 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1149 "Rotation might be broken in 24 bpp\n"); 1150 } 1151 1152 xf86SetBlackWhitePixels(pScreen); 1153 xf86SetBackingStore(pScreen); 1154 1155 /* Software cursor. */ 1156 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1157 1158 /* check for hardware cursor support */ 1159 if (fPtr->HWCursor) 1160 WsfbSetupCursor(pScreen); 1161 1162 /* 1163 * Colormap 1164 * 1165 * Note that, even on less than 8 bit depth frame buffers, we 1166 * expect the colormap to be programmable with 8 bit values. 1167 * As of now, this is indeed the case on all OpenBSD supported 1168 * graphics hardware. 1169 */ 1170 if (!miCreateDefColormap(pScreen)) 1171 return FALSE; 1172 flags = CMAP_RELOAD_ON_MODE_SWITCH; 1173 1174 ncolors = 0; 1175 if (fPtr->fbi.fbi_pixeltype == WSFB_CI) { 1176 ncolors = fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries; 1177 } 1178 1179 /* On StaticGray visuals, fake a 256 entries colormap. */ 1180 if (ncolors == 0) 1181 ncolors = 256; 1182 1183 if(!xf86HandleColormaps(pScreen, ncolors, 8, WsfbLoadPalette, 1184 NULL, flags)) 1185 return FALSE; 1186 1187#if defined(__NetBSD__) && defined(WSDISPLAY_TYPE_LUNA) 1188 if (wstype == WSDISPLAY_TYPE_LUNA) { 1189 ncolors = fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries; 1190 if (ncolors > 0) { 1191 /* 1192 * Override palette to use 4bpp/8bpp framebuffers as 1193 * monochrome server by using only the first plane. 1194 * See also comment in WsfbPreInit(). 1195 */ 1196 struct wsdisplay_cmap cmap; 1197 uint8_t r[256], g[256], b[256]; 1198 int p; 1199 1200 for (p = 0; p < ncolors; p++) 1201 r[p] = g[p] = b[p] = (p & 1) ? 0xff : 0; 1202 cmap.index = 0; 1203 cmap.count = ncolors; 1204 cmap.red = r; 1205 cmap.green = g; 1206 cmap.blue = b; 1207 if (ioctl(fPtr->fd, WSDISPLAYIO_PUTCMAP, &cmap) == -1) { 1208 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1209 "ioctl WSDISPLAYIO_PUTCMAP: %s\n", 1210 strerror(errno)); 1211 } 1212 } 1213 } 1214#endif 1215 1216 pScreen->SaveScreen = WsfbSaveScreen; 1217 1218#ifdef XvExtension 1219 { 1220 XF86VideoAdaptorPtr *ptr; 1221 1222 int n = xf86XVListGenericAdaptors(pScrn,&ptr); 1223 if (n) { 1224 xf86XVScreenInit(pScreen,ptr,n); 1225 } 1226 } 1227#endif 1228 1229 /* Wrap the current CloseScreen function. */ 1230 fPtr->CloseScreen = pScreen->CloseScreen; 1231 pScreen->CloseScreen = WsfbCloseScreen; 1232 1233 TRACE_EXIT("WsfbScreenInit"); 1234 return TRUE; 1235} 1236 1237static Bool 1238WsfbCloseScreen(CLOSE_SCREEN_ARGS_DECL) 1239{ 1240 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1241 PixmapPtr pPixmap; 1242 WsfbPtr fPtr = WSFBPTR(pScrn); 1243 1244 1245 TRACE_ENTER("WsfbCloseScreen"); 1246 1247 pPixmap = pScreen->GetScreenPixmap(pScreen); 1248 if (fPtr->shadowFB) 1249 shadowRemove(pScreen, pPixmap); 1250 1251 if (pScrn->vtSema) { 1252 WsfbRestore(pScrn); 1253 if (munmap(fPtr->fbmem, fPtr->fbmem_len + fPtr->fbi.fbi_fboffset) == -1) { 1254 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1255 "munmap: %s\n", strerror(errno)); 1256 } 1257 1258 fPtr->fbmem = NULL; 1259 } 1260#ifdef XFreeXDGA 1261 if (fPtr->pDGAMode) { 1262 free(fPtr->pDGAMode); 1263 fPtr->pDGAMode = NULL; 1264 fPtr->nDGAMode = 0; 1265 } 1266#endif 1267 pScrn->vtSema = FALSE; 1268 1269 /* Unwrap CloseScreen. */ 1270 pScreen->CloseScreen = fPtr->CloseScreen; 1271 TRACE_EXIT("WsfbCloseScreen"); 1272 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1273} 1274 1275static void * 1276WsfbWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1277 CARD32 *size, void *closure) 1278{ 1279 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1280 WsfbPtr fPtr = WSFBPTR(pScrn); 1281 1282 /* 1283 * XXX 1284 * This should never happen. Is it really necessary? 1285 */ 1286 if (fPtr->fbi.fbi_stride) 1287 *size = fPtr->fbi.fbi_stride; 1288 else { 1289 if (ioctl(fPtr->fd, WSDISPLAYIO_LINEBYTES, size) == -1) 1290 return NULL; 1291 fPtr->fbi.fbi_stride = *size; 1292 } 1293 return ((CARD8 *)fPtr->fbstart + row * fPtr->fbi.fbi_stride + offset); 1294} 1295 1296#ifdef HAVE_SHADOW_AFB 1297/* 1298 * For use with shadowUpdateAfb8 1299 * 1300 * For video memory layout with non-interleaved bitplanes. 1301 */ 1302static void * 1303WsfbWindowAfb(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1304 CARD32 *size, void *closure) 1305{ 1306 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1307 WsfbPtr fPtr = WSFBPTR(pScrn); 1308 1309 /* size is offset from start of bitplane to next bitplane */ 1310 *size = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 1311 return ((CARD8 *)fPtr->fbstart + row * fPtr->fbi.fbi_stride + offset); 1312} 1313#endif 1314 1315static void 1316WsfbPointerMoved(SCRN_ARG_TYPE arg, int x, int y) 1317{ 1318 SCRN_INFO_PTR(arg); 1319 WsfbPtr fPtr = WSFBPTR(pScrn); 1320 int newX, newY; 1321 1322 switch (fPtr->rotate) 1323 { 1324 case WSFB_ROTATE_CW: 1325 /* 90 degrees CW rotation. */ 1326 newX = pScrn->pScreen->height - y - 1; 1327 newY = x; 1328 break; 1329 1330 case WSFB_ROTATE_CCW: 1331 /* 90 degrees CCW rotation. */ 1332 newX = y; 1333 newY = pScrn->pScreen->width - x - 1; 1334 break; 1335 1336 case WSFB_ROTATE_UD: 1337 /* 180 degrees UD rotation. */ 1338 newX = pScrn->pScreen->width - x - 1; 1339 newY = pScrn->pScreen->height - y - 1; 1340 break; 1341 1342 default: 1343 /* No rotation. */ 1344 newX = x; 1345 newY = y; 1346 break; 1347 } 1348 1349 /* Pass adjusted pointer coordinates to wrapped PointerMoved function. */ 1350 (*fPtr->PointerMoved)(arg, newX, newY); 1351} 1352 1353static Bool 1354WsfbEnterVT(VT_FUNC_ARGS_DECL) 1355{ 1356 SCRN_INFO_PTR(arg); 1357 WsfbPtr fPtr = WSFBPTR(pScrn); 1358 int mode; 1359 1360 TRACE_ENTER("EnterVT"); 1361 pScrn->vtSema = TRUE; 1362 1363 /* Restore the graphics mode. */ 1364 mode = WSDISPLAYIO_MODE_DUMBFB; 1365 if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) { 1366 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1367 "error setting graphics mode %s\n", strerror(errno)); 1368 } 1369 1370 TRACE_EXIT("EnterVT"); 1371 return TRUE; 1372} 1373 1374static void 1375WsfbLeaveVT(VT_FUNC_ARGS_DECL) 1376{ 1377 SCRN_INFO_PTR(arg); 1378 WsfbPtr fPtr = WSFBPTR(pScrn); 1379 int mode; 1380 1381 TRACE_ENTER("LeaveVT"); 1382 1383 /* 1384 * stuff to do: 1385 * - turn off hw cursor 1386 * - restore colour map if WSFB_CI 1387 * - ioctl(WSDISPLAYIO_MODE_EMUL) to notify the kernel driver that 1388 * we're backing off 1389 */ 1390 1391 if (fPtr->fbi.fbi_pixeltype == WSFB_CI && 1392 fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries > 0) { 1393 /* reset colormap for text mode */ 1394 if (ioctl(fPtr->fd, WSDISPLAYIO_PUTCMAP, 1395 &(fPtr->saved_cmap)) == -1) { 1396 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1397 "error restoring colormap %s\n", 1398 strerror(errno)); 1399 } 1400 } 1401 1402 /* Restore the text mode. */ 1403 mode = WSDISPLAYIO_MODE_EMUL; 1404 if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) { 1405 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1406 "error setting text mode %s\n", strerror(errno)); 1407 } 1408 1409 pScrn->vtSema = FALSE; 1410 TRACE_EXIT("LeaveVT"); 1411} 1412 1413static Bool 1414WsfbSwitchMode(SWITCH_MODE_ARGS_DECL) 1415{ 1416 TRACE_ENTER("SwitchMode"); 1417 /* Nothing else to do. */ 1418 return TRUE; 1419} 1420 1421static int 1422WsfbValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1423{ 1424 TRACE_ENTER("ValidMode"); 1425 return MODE_OK; 1426} 1427 1428static void 1429WsfbLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 1430 LOCO *colors, VisualPtr pVisual) 1431{ 1432 WsfbPtr fPtr = WSFBPTR(pScrn); 1433 struct wsdisplay_cmap cmap; 1434 unsigned char red[256],green[256],blue[256]; 1435 int i, indexMin=256, indexMax=0; 1436 1437 TRACE_ENTER("LoadPalette"); 1438 1439 /* nothing to do if there is no color palette support */ 1440 if (fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries == 0) 1441 return; 1442 1443 cmap.count = 1; 1444 cmap.red = red; 1445 cmap.green = green; 1446 cmap.blue = blue; 1447 1448 if (numColors == 1) { 1449 /* Optimisation */ 1450 cmap.index = indices[0]; 1451 red[0] = colors[indices[0]].red; 1452 green[0] = colors[indices[0]].green; 1453 blue[0] = colors[indices[0]].blue; 1454 if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1) 1455 ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno)); 1456 } else { 1457 /* 1458 * Change all colors in 2 ioctls 1459 * and limit the data to be transfered. 1460 */ 1461 for (i = 0; i < numColors; i++) { 1462 if (indices[i] < indexMin) 1463 indexMin = indices[i]; 1464 if (indices[i] > indexMax) 1465 indexMax = indices[i]; 1466 } 1467 cmap.index = indexMin; 1468 cmap.count = indexMax - indexMin + 1; 1469 cmap.red = &red[indexMin]; 1470 cmap.green = &green[indexMin]; 1471 cmap.blue = &blue[indexMin]; 1472 /* Get current map. */ 1473 if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, &cmap) == -1) 1474 ErrorF("ioctl FBIOGETCMAP: %s\n", strerror(errno)); 1475 /* Change the colors that require updating. */ 1476 for (i = 0; i < numColors; i++) { 1477 red[indices[i]] = colors[indices[i]].red; 1478 green[indices[i]] = colors[indices[i]].green; 1479 blue[indices[i]] = colors[indices[i]].blue; 1480 } 1481 /* Write the colormap back. */ 1482 if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1) 1483 ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno)); 1484 } 1485 TRACE_EXIT("LoadPalette"); 1486} 1487 1488static Bool 1489WsfbSaveScreen(ScreenPtr pScreen, int mode) 1490{ 1491 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1492 WsfbPtr fPtr = WSFBPTR(pScrn); 1493 int state; 1494 1495 TRACE_ENTER("SaveScreen"); 1496 1497 if (!pScrn->vtSema) 1498 return TRUE; 1499 1500 if (mode != SCREEN_SAVER_FORCER) { 1501 state = xf86IsUnblank(mode)?WSDISPLAYIO_VIDEO_ON: 1502 WSDISPLAYIO_VIDEO_OFF; 1503 ioctl(fPtr->fd, 1504 WSDISPLAYIO_SVIDEO, &state); 1505 } 1506 TRACE_EXIT("SaveScreen"); 1507 return TRUE; 1508} 1509 1510 1511static void 1512WsfbSave(ScrnInfoPtr pScrn) 1513{ 1514 WsfbPtr fPtr = WSFBPTR(pScrn); 1515 1516 TRACE_ENTER("WsfbSave"); 1517 1518 /* nothing to save if we don't run in colour-indexed mode */ 1519 if (fPtr->fbi.fbi_pixeltype != WSFB_CI) 1520 return; 1521 1522 /* nothing to do if no color palette support */ 1523 if (fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries == 0) 1524 return; 1525 1526 fPtr->saved_cmap.index = 0; 1527 fPtr->saved_cmap.count = fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries; 1528 if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, 1529 &(fPtr->saved_cmap)) == -1) { 1530 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1531 "error saving colormap %s\n", strerror(errno)); 1532 } 1533 TRACE_EXIT("WsfbSave"); 1534 1535} 1536 1537static void 1538WsfbRestore(ScrnInfoPtr pScrn) 1539{ 1540 WsfbPtr fPtr = WSFBPTR(pScrn); 1541 int mode; 1542 1543 TRACE_ENTER("WsfbRestore"); 1544 1545 if (fPtr->fbi.fbi_pixeltype == WSFB_CI && 1546 fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries > 0) { 1547 /* reset colormap for text mode */ 1548 if (ioctl(fPtr->fd, WSDISPLAYIO_PUTCMAP, 1549 &(fPtr->saved_cmap)) == -1) { 1550 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1551 "error restoring colormap %s\n", 1552 strerror(errno)); 1553 } 1554 } 1555 1556 /* Clear the screen. */ 1557 memset(fPtr->fbstart, 0, fPtr->fbmem_len); 1558 1559 /* Restore the text mode. */ 1560 mode = WSDISPLAYIO_MODE_EMUL; 1561 if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) { 1562 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1563 "error setting text mode %s\n", strerror(errno)); 1564 } 1565 TRACE_EXIT("WsfbRestore"); 1566} 1567 1568#ifdef XFreeXDGA 1569/*********************************************************************** 1570 * DGA stuff 1571 ***********************************************************************/ 1572 1573static Bool 1574WsfbDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 1575 unsigned char **ApertureBase, int *ApertureSize, 1576 int *ApertureOffset, int *flags) 1577{ 1578 *DeviceName = NULL; /* No special device */ 1579 *ApertureBase = (unsigned char *)(pScrn->memPhysBase); 1580 *ApertureSize = pScrn->videoRam; 1581 *ApertureOffset = pScrn->fbOffset; 1582 *flags = 0; 1583 1584 return TRUE; 1585} 1586 1587static Bool 1588WsfbDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode) 1589{ 1590 DisplayModePtr pMode; 1591 int scrnIdx = pScrn->pScreen->myNum; 1592 int frameX0, frameY0; 1593 1594 if (pDGAMode) { 1595 pMode = pDGAMode->mode; 1596 frameX0 = frameY0 = 0; 1597 } else { 1598 if (!(pMode = pScrn->currentMode)) 1599 return TRUE; 1600 1601 frameX0 = pScrn->frameX0; 1602 frameY0 = pScrn->frameY0; 1603 } 1604 1605 if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode))) 1606 return FALSE; 1607 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0)); 1608 1609 return TRUE; 1610} 1611 1612static void 1613WsfbDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 1614{ 1615 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 1616} 1617 1618static int 1619WsfbDGAGetViewport(ScrnInfoPtr pScrn) 1620{ 1621 return (0); 1622} 1623 1624static DGAFunctionRec WsfbDGAFunctions = 1625{ 1626 WsfbDGAOpenFramebuffer, 1627 NULL, /* CloseFramebuffer */ 1628 WsfbDGASetMode, 1629 WsfbDGASetViewport, 1630 WsfbDGAGetViewport, 1631 NULL, /* Sync */ 1632 NULL, /* FillRect */ 1633 NULL, /* BlitRect */ 1634 NULL, /* BlitTransRect */ 1635}; 1636 1637static void 1638WsfbDGAAddModes(ScrnInfoPtr pScrn) 1639{ 1640 WsfbPtr fPtr = WSFBPTR(pScrn); 1641 DisplayModePtr pMode = pScrn->modes; 1642 DGAModePtr pDGAMode; 1643 1644 do { 1645 pDGAMode = realloc(fPtr->pDGAMode, 1646 (fPtr->nDGAMode + 1) * sizeof(DGAModeRec)); 1647 if (!pDGAMode) 1648 break; 1649 1650 fPtr->pDGAMode = pDGAMode; 1651 pDGAMode += fPtr->nDGAMode; 1652 (void)memset(pDGAMode, 0, sizeof(DGAModeRec)); 1653 1654 ++fPtr->nDGAMode; 1655 pDGAMode->mode = pMode; 1656 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 1657 pDGAMode->byteOrder = pScrn->imageByteOrder; 1658 pDGAMode->depth = pScrn->depth; 1659 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel; 1660 pDGAMode->red_mask = pScrn->mask.red; 1661 pDGAMode->green_mask = pScrn->mask.green; 1662 pDGAMode->blue_mask = pScrn->mask.blue; 1663 pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ? 1664 TrueColor : PseudoColor; 1665 pDGAMode->xViewportStep = 1; 1666 pDGAMode->yViewportStep = 1; 1667 pDGAMode->viewportWidth = pMode->HDisplay; 1668 pDGAMode->viewportHeight = pMode->VDisplay; 1669 1670 if (fPtr->fbi.fbi_stride) 1671 pDGAMode->bytesPerScanline = fPtr->fbi.fbi_stride; 1672 else { 1673 ioctl(fPtr->fd, WSDISPLAYIO_LINEBYTES, 1674 &fPtr->fbi.fbi_stride); 1675 pDGAMode->bytesPerScanline = fPtr->fbi.fbi_stride; 1676 } 1677 1678 pDGAMode->imageWidth = pMode->HDisplay; 1679 pDGAMode->imageHeight = pMode->VDisplay; 1680 pDGAMode->pixmapWidth = pDGAMode->imageWidth; 1681 pDGAMode->pixmapHeight = pDGAMode->imageHeight; 1682 pDGAMode->maxViewportX = pScrn->virtualX - 1683 pDGAMode->viewportWidth; 1684 pDGAMode->maxViewportY = pScrn->virtualY - 1685 pDGAMode->viewportHeight; 1686 1687 pDGAMode->address = fPtr->fbstart; 1688 1689 pMode = pMode->next; 1690 } while (pMode != pScrn->modes); 1691} 1692 1693static Bool 1694WsfbDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) 1695{ 1696 WsfbPtr fPtr = WSFBPTR(pScrn); 1697 1698 if (pScrn->depth < 8) 1699 return FALSE; 1700 1701 if (!fPtr->nDGAMode) 1702 WsfbDGAAddModes(pScrn); 1703 1704 return (DGAInit(pScreen, &WsfbDGAFunctions, 1705 fPtr->pDGAMode, fPtr->nDGAMode)); 1706} 1707#endif 1708 1709static Bool 1710WsfbDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, 1711 pointer ptr) 1712{ 1713 xorgHWFlags *flag; 1714 1715 switch (op) { 1716 case GET_REQUIRED_HW_INTERFACES: 1717 flag = (CARD32*)ptr; 1718 (*flag) = 0; 1719 return TRUE; 1720 default: 1721 return FALSE; 1722 } 1723} 1724 1725static inline void 1726memcpy32sw(void *dest, void *src, int len) 1727{ 1728 uint32_t *d = dest, *s = src; 1729 1730#if DEBUG 1731 if ((((long)dest & 3) + ((long)src & 3) + (len & 3)) != 0) { 1732 xf86Msg(X_ERROR, "unaligned %s\n", __func__); 1733 return; 1734 } 1735#endif 1736 while (len > 0) { 1737 *d = bswap32(*s); 1738 d++; 1739 s++; 1740 len -= 4; 1741 } 1742} 1743 1744/* adapted from miext/shadow/shpacked.c::shadowUpdatePacked() */ 1745void 1746WsfbShadowUpdateSwap32(ScreenPtr pScreen, shadowBufPtr pBuf) 1747{ 1748 RegionPtr damage = DamageRegion (pBuf->pDamage); 1749 PixmapPtr pShadow = pBuf->pPixmap; 1750 int nbox = RegionNumRects (damage); 1751 BoxPtr pbox = RegionRects (damage); 1752 FbBits *shaBase, *shaLine, *sha; 1753 FbStride shaStride; 1754 int scrBase, scrLine, scr; 1755 int shaBpp; 1756 int shaXoff, shaYoff; /* XXX assumed to be zero */ 1757 int x, y, w, h, width; 1758 int i; 1759 FbBits *winBase = NULL, *win; 1760 CARD32 winSize; 1761 1762 fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); 1763 while (nbox--) 1764 { 1765 x = pbox->x1 * shaBpp; 1766 y = pbox->y1; 1767 w = (pbox->x2 - pbox->x1) * shaBpp; 1768 h = pbox->y2 - pbox->y1; 1769 1770 scrLine = (x >> FB_SHIFT); 1771 shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); 1772 1773 x &= FB_MASK; 1774 w = (w + x + FB_MASK) >> FB_SHIFT; 1775 1776 while (h--) 1777 { 1778 winSize = 0; 1779 scrBase = 0; 1780 width = w; 1781 scr = scrLine; 1782 sha = shaLine; 1783 while (width) { 1784 /* how much remains in this window */ 1785 i = scrBase + winSize - scr; 1786 if (i <= 0 || scr < scrBase) 1787 { 1788 winBase = (FbBits *) (*pBuf->window) (pScreen, 1789 y, 1790 scr * sizeof (FbBits), 1791 SHADOW_WINDOW_WRITE, 1792 &winSize, 1793 pBuf->closure); 1794 if(!winBase) 1795 return; 1796 scrBase = scr; 1797 winSize /= sizeof (FbBits); 1798 i = winSize; 1799 } 1800 win = winBase + (scr - scrBase); 1801 if (i > width) 1802 i = width; 1803 width -= i; 1804 scr += i; 1805 memcpy32sw(win, sha, i * sizeof(FbBits)); 1806 sha += i; 1807 } 1808 shaLine += shaStride; 1809 y++; 1810 } 1811 pbox++; 1812 } 1813} 1814 1815void 1816WsfbShadowUpdateSplit(ScreenPtr pScreen, shadowBufPtr pBuf) 1817{ 1818 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1819 WsfbPtr fPtr = WSFBPTR(pScrn); 1820 RegionPtr damage = DamageRegion (pBuf->pDamage); 1821 PixmapPtr pShadow = pBuf->pPixmap; 1822 int nbox = RegionNumRects (damage); 1823 BoxPtr pbox = RegionRects (damage); 1824 FbBits *shaBase, *shaLine, *sha; 1825 FbStride shaStride; 1826 int scrBase, scrLine, scr; 1827 int shaBpp; 1828 int shaXoff, shaYoff; /* XXX assumed to be zero */ 1829 int x, y, w, h, width; 1830 int i; 1831 FbBits *winBase = NULL, *win, *win2; 1832 unsigned long split = fPtr->fbi.fbi_fbsize / 2; 1833 CARD32 winSize; 1834 1835 fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); 1836 while (nbox--) 1837 { 1838 x = pbox->x1 * shaBpp; 1839 y = pbox->y1; 1840 w = (pbox->x2 - pbox->x1) * shaBpp; 1841 h = pbox->y2 - pbox->y1; 1842 1843 scrLine = (x >> FB_SHIFT); 1844 shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); 1845 1846 x &= FB_MASK; 1847 w = (w + x + FB_MASK) >> FB_SHIFT; 1848 1849 while (h--) 1850 { 1851 winSize = 0; 1852 scrBase = 0; 1853 width = w; 1854 scr = scrLine; 1855 sha = shaLine; 1856 while (width) { 1857 /* how much remains in this window */ 1858 i = scrBase + winSize - scr; 1859 if (i <= 0 || scr < scrBase) 1860 { 1861 winBase = (FbBits *) (*pBuf->window) (pScreen, 1862 y, 1863 scr * sizeof (FbBits), 1864 SHADOW_WINDOW_WRITE, 1865 &winSize, 1866 pBuf->closure); 1867 if(!winBase) 1868 return; 1869 scrBase = scr; 1870 winSize /= sizeof (FbBits); 1871 i = winSize; 1872 } 1873 win = winBase + (scr - scrBase); 1874 win2 = (FbBits *)(split + (unsigned long)win); 1875 if (i > width) 1876 i = width; 1877 width -= i; 1878 scr += i; 1879 memcpy(win, sha, i * sizeof(FbBits)); 1880 memcpy(win2, sha, i * sizeof(FbBits)); 1881 sha += i; 1882 } 1883 shaLine += shaStride; 1884 y++; 1885 } 1886 pbox++; 1887 } 1888} 1889