wsfb_driver.c revision c2056409
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 * LUNA's color framebuffers support 4bpp or 8bpp 572 * but they have multiple 1bpp VRAM planes like ancient VGA. 573 */ 574#ifdef HAVE_SHADOW_AFB 575 if (bitsperpixel == 8) { 576 /* 577 * For 8bpp one, we can use the bitplane ops with 578 * shadow update proc as amiga. 579 */ 580 fPtr->planarAfb = TRUE; 581 } else 582#endif 583 { 584 /* 585 * For 4bpp one (or there is no planar support), 586 * just use only the first one plane 587 * as 1bpp monochrome server. 588 * 589 * Note OpenBSD/luna88k workarounds this by 590 * switching depth and palette settings by 591 * WSDISPLAYIO_SETGFXMODE ioctl. 592 */ 593 default_depth = 1; 594 bitsperpixel = 1; 595 } 596 } 597#endif 598#ifdef WSDISPLAY_TYPE_AMIGACC 599 if (wstype == WSDISPLAY_TYPE_AMIGACC) { 600 /* 601 * Video memory is organized in bitplanes. 602 * 8bpp or 1bpp supported in this driver. 603 * With 8bpp conversion to bitplane format 604 * is done in shadow update proc. 605 * With 1bpp no conversion needed. 606 */ 607#ifdef HAVE_SHADOW_AFB 608 if (bitsperpixel == 8) { 609 fPtr->planarAfb = TRUE; 610 } else 611#endif 612 { 613 default_depth = 1; 614 bitsperpixel = 1; 615 } 616 } 617#endif 618 619 if (!xf86SetDepthBpp(pScrn, default_depth, default_depth, 620 bitsperpixel, 621 bitsperpixel >= 24 ? Support24bppFb|Support32bppFb : 0)) 622 return FALSE; 623 624 /* Check consistency. */ 625 if (pScrn->bitsPerPixel != bitsperpixel) { 626 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 627 "specified depth (%d) or bpp (%d) doesn't match " 628 "framebuffer depth (%d)\n", pScrn->depth, 629 pScrn->bitsPerPixel, bitsperpixel); 630 return FALSE; 631 } 632 xf86PrintDepthBpp(pScrn); 633 634 /* Get the depth24 pixmap format. */ 635 if (pScrn->depth == 24 && pix24bpp == 0) 636 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 637 638 /* Handle options. */ 639 xf86CollectOptions(pScrn, NULL); 640 fPtr->Options = (OptionInfoRec *)malloc(sizeof(WsfbOptions)); 641 if (fPtr->Options == NULL) 642 return FALSE; 643 memcpy(fPtr->Options, WsfbOptions, sizeof(WsfbOptions)); 644 xf86ProcessOptions(pScrn->scrnIndex, fPtr->pEnt->device->options, 645 fPtr->Options); 646 647 /* Use shadow framebuffer by default, on depth >= 8 */ 648 xf86Msg(X_INFO, "fbi_flags: %x\n", fPtr->fbi.fbi_flags); 649 if ((pScrn->depth >= 8) && 650 ((fPtr->fbi.fbi_flags & WSFB_VRAM_IS_RAM) == 0)) { 651 fPtr->shadowFB = xf86ReturnOptValBool(fPtr->Options, 652 OPTION_SHADOW_FB, TRUE); 653 } else 654 if (xf86ReturnOptValBool(fPtr->Options, 655 OPTION_SHADOW_FB, FALSE)) { 656 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 657 "Shadow FB option ignored on depth < 8\n"); 658 } 659 if (fPtr->fbi.fbi_flags & WSFB_VRAM_IS_SPLIT) { 660 if (!fPtr->shadowFB) { 661 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 662 "Shadow FB forced on for split framebuffer\n"); 663 fPtr->shadowFB = TRUE; 664 } 665 } 666 /* Rotation */ 667 fPtr->rotate = WSFB_ROTATE_NONE; 668 if ((s = xf86GetOptValString(fPtr->Options, OPTION_ROTATE))) { 669 if (pScrn->depth >= 8) { 670 if (!xf86NameCmp(s, "CW")) { 671 fPtr->shadowFB = TRUE; 672 fPtr->rotate = WSFB_ROTATE_CW; 673 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 674 "Rotating screen clockwise\n"); 675 } else if (!xf86NameCmp(s, "CCW")) { 676 fPtr->shadowFB = TRUE; 677 fPtr->rotate = WSFB_ROTATE_CCW; 678 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 679 "Rotating screen counter clockwise\n"); 680 } else if (!xf86NameCmp(s, "UD")) { 681 fPtr->shadowFB = TRUE; 682 fPtr->rotate = WSFB_ROTATE_UD; 683 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 684 "Rotating screen upside down\n"); 685 } else { 686 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 687 "\"%s\" is not a valid value for Option " 688 "\"Rotate\"\n", s); 689 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 690 "Valid options are \"CW\", \"CCW\"," 691 " or \"UD\"\n"); 692 } 693 } else { 694 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 695 "Option \"Rotate\" ignored on depth < 8\n"); 696 } 697 } 698 699 700 fPtr->useSwap32 = FALSE; 701 /* Color weight */ 702 if (fPtr->fbi.fbi_pixeltype == WSFB_RGB) { 703 rgb zeros = { 0, 0, 0 }, masks; 704 705 if (fPtr->fbi.fbi_subtype.fbi_rgbmasks.red_size > 0) { 706 uint32_t msk; 707 708 /* 709 * see if we need to byte-swap pixels 710 * XXX this requires a shadow FB and is incompatible 711 * (for now ) with rotation 712 */ 713 if ((fPtr->fbi.fbi_bitsperpixel == 32) && 714 (fPtr->fbi.fbi_subtype.fbi_rgbmasks.blue_offset == 24) && 715 (fPtr->rotate == WSFB_ROTATE_NONE) && 716 (fPtr->shadowFB == TRUE)) { 717 /* 718 * looks like BGRA - set the swap flag and flip 719 * the offsets 720 */ 721 xf86Msg(X_INFO, "endian-flipped RGB framebuffer " 722 "detected, using WsfbShadowUpdateSwap32()\n"); 723 fPtr->fbi.fbi_subtype.fbi_rgbmasks.blue_offset = 0; 724 fPtr->fbi.fbi_subtype.fbi_rgbmasks.green_offset = 8; 725 fPtr->fbi.fbi_subtype.fbi_rgbmasks.red_offset = 16; 726 fPtr->fbi.fbi_subtype.fbi_rgbmasks.alpha_offset = 24; 727 fPtr->useSwap32 = TRUE; 728 } 729 730 msk = 0xffffffff; 731 msk = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.red_size; 732 msk = ~msk; 733 masks.red = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.red_offset; 734 735 msk = 0xffffffff; 736 msk = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.green_size; 737 msk = ~msk; 738 masks.green = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.green_offset; 739 740 msk = 0xffffffff; 741 msk = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.blue_size; 742 msk = ~msk; 743 masks.blue = msk << fPtr->fbi.fbi_subtype.fbi_rgbmasks.blue_offset; 744 xf86Msg(X_INFO, "masks generated: %08lx %08lx %08lx\n", 745 (unsigned long)masks.red, 746 (unsigned long)masks.green, 747 (unsigned long)masks.blue); 748 } else { 749 masks.red = 0; 750 masks.green = 0; 751 masks.blue = 0; 752 } 753 754 if (!xf86SetWeight(pScrn, zeros, masks)) 755 return FALSE; 756 } 757 758 /* Visual init */ 759 if (!xf86SetDefaultVisual(pScrn, -1)) 760 return FALSE; 761 762 /* We don't currently support DirectColor at > 8bpp . */ 763 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 764 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 765 " (%s) is not supported at depth %d\n", 766 xf86GetVisualName(pScrn->defaultVisual), 767 pScrn->depth); 768 return FALSE; 769 } 770 771 xf86SetGamma(pScrn,zeros); 772 773 pScrn->progClock = TRUE; 774 pScrn->rgbBits = (pScrn->depth >= 8) ? 8 : pScrn->depth; 775 pScrn->chipset = "wsfb"; 776 pScrn->videoRam = fPtr->fbi.fbi_fbsize; 777 778 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Vidmem: %dk\n", 779 pScrn->videoRam/1024); 780 781 /* Fake video mode struct. */ 782 mode = (DisplayModePtr)malloc(sizeof(DisplayModeRec)); 783 mode->prev = mode; 784 mode->next = mode; 785 mode->name = "wsfb current mode"; 786 mode->status = MODE_OK; 787 mode->type = M_T_BUILTIN; 788 mode->Clock = 0; 789 mode->HDisplay = fPtr->fbi.fbi_width; 790 mode->HSyncStart = 0; 791 mode->HSyncEnd = 0; 792 mode->HTotal = 0; 793 mode->HSkew = 0; 794 mode->VDisplay = fPtr->fbi.fbi_height; 795 mode->VSyncStart = 0; 796 mode->VSyncEnd = 0; 797 mode->VTotal = 0; 798 mode->VScan = 0; 799 mode->Flags = 0; 800 if (pScrn->modes != NULL) { 801 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 802 "Ignoring mode specification from screen section\n"); 803 } 804 pScrn->currentMode = pScrn->modes = mode; 805 pScrn->virtualX = fPtr->fbi.fbi_width; 806 pScrn->virtualY = fPtr->fbi.fbi_height; 807 pScrn->displayWidth = pScrn->virtualX; 808 809 /* Set the display resolution. */ 810 xf86SetDpi(pScrn, 0, 0); 811 812 from = X_DEFAULT; 813 fPtr->HWCursor = TRUE; 814 if (xf86GetOptValBool(fPtr->Options, OPTION_HW_CURSOR, &fPtr->HWCursor)) 815 from = X_CONFIG; 816 if (xf86ReturnOptValBool(fPtr->Options, OPTION_SW_CURSOR, FALSE)) { 817 from = X_CONFIG; 818 fPtr->HWCursor = FALSE; 819 } 820 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 821 fPtr->HWCursor ? "HW" : "SW"); 822 823 /* Load bpp-specific modules. */ 824 switch(pScrn->bitsPerPixel) { 825 case 1: 826 case 4: 827 default: 828 mod = "fb"; 829 break; 830 } 831 832 833 /* Load shadow if needed. */ 834 if (fPtr->shadowFB) { 835 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 836 "Using \"Shadow Framebuffer\"\n"); 837 if (xf86LoadSubModule(pScrn, "shadow") == NULL) { 838 WsfbFreeRec(pScrn); 839 return FALSE; 840 } 841 } 842 843 if (mod && xf86LoadSubModule(pScrn, mod) == NULL) { 844 WsfbFreeRec(pScrn); 845 return FALSE; 846 } 847 848 if (xf86LoadSubModule(pScrn, "ramdac") == NULL) { 849 WsfbFreeRec(pScrn); 850 return FALSE; 851 } 852 853 if (mod) { 854 if (reqSym) { 855 xf86LoaderReqSymbols(reqSym, NULL); 856 } else { 857 xf86LoaderReqSymLists(fbSymbols, NULL); 858 } 859 } 860 TRACE_EXIT("PreInit"); 861 return TRUE; 862} 863 864static Bool 865WsfbCreateScreenResources(ScreenPtr pScreen) 866{ 867 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 868 WsfbPtr fPtr = WSFBPTR(pScrn); 869 PixmapPtr pPixmap; 870 Bool ret; 871 void (*shadowproc)(ScreenPtr, shadowBufPtr); 872 ShadowWindowProc windowproc = WsfbWindowLinear; 873 874 pScreen->CreateScreenResources = fPtr->CreateScreenResources; 875 ret = pScreen->CreateScreenResources(pScreen); 876 pScreen->CreateScreenResources = WsfbCreateScreenResources; 877 878 if (!ret) 879 return FALSE; 880 881 pPixmap = pScreen->GetScreenPixmap(pScreen); 882 if (fPtr->fbi.fbi_flags & WSFB_VRAM_IS_SPLIT) { 883 shadowproc = WsfbShadowUpdateSplit; 884 } else if (fPtr->useSwap32) { 885 shadowproc = WsfbShadowUpdateSwap32; 886 } else if (fPtr->rotate) { 887 shadowproc = shadowUpdateRotatePacked; 888 } else 889#ifdef HAVE_SHADOW_AFB 890 if (fPtr->planarAfb) { 891 shadowproc = shadowUpdateAfb8; 892 windowproc = WsfbWindowAfb; 893 } else 894#endif 895 { 896 shadowproc = shadowUpdatePacked; 897 } 898 899 if (!shadowAdd(pScreen, pPixmap, shadowproc, 900 windowproc, fPtr->rotate, NULL)) { 901 return FALSE; 902 } 903 return TRUE; 904} 905 906 907static Bool 908WsfbShadowInit(ScreenPtr pScreen) 909{ 910 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 911 WsfbPtr fPtr = WSFBPTR(pScrn); 912 913 if (!shadowSetup(pScreen)) 914 return FALSE; 915 fPtr->CreateScreenResources = pScreen->CreateScreenResources; 916 pScreen->CreateScreenResources = WsfbCreateScreenResources; 917 918 return TRUE; 919} 920 921static Bool 922WsfbScreenInit(SCREEN_INIT_ARGS_DECL) 923{ 924 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 925 WsfbPtr fPtr = WSFBPTR(pScrn); 926 VisualPtr visual; 927 int ret, flags, ncolors; 928 int wsmode = WSDISPLAYIO_MODE_DUMBFB; 929 int wstype; 930 int width; 931 size_t len; 932 933 TRACE_ENTER("WsfbScreenInit"); 934#if DEBUG 935 ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n" 936 "\tmask: %x,%x,%x, offset: %u,%u,%u\n", 937 pScrn->bitsPerPixel, 938 pScrn->depth, 939 xf86GetVisualName(pScrn->defaultVisual), 940 pScrn->mask.red,pScrn->mask.green,pScrn->mask.blue, 941 pScrn->offset.red,pScrn->offset.green,pScrn->offset.blue); 942#endif 943 switch (fPtr->fbi.fbi_bitsperpixel) { 944 case 1: 945 case 4: 946 case 8: 947 len = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 948#ifdef HAVE_SHADOW_AFB 949 if (fPtr->planarAfb) { 950 /* 951 * stride is "bytes per line" for each plane so 952 * we need a number of planes to mmap in planar case. 953 */ 954 len *= fPtr->fbi.fbi_bitsperpixel; 955 } 956#endif 957 958 break; 959 case 15: 960 case 16: 961 if (fPtr->fbi.fbi_stride == fPtr->fbi.fbi_width) { 962 xf86Msg(X_ERROR, "Bogus stride == width in 16bit colour\n"); 963 len = fPtr->fbi.fbi_width * fPtr->fbi.fbi_height * sizeof(short); 964 } else { 965 len = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 966 } 967 break; 968 case 24: 969 if (fPtr->fbi.fbi_stride == fPtr->fbi.fbi_width) { 970 xf86Msg(X_ERROR, "Bogus stride == width in 24bit colour\n"); 971 len = fPtr->fbi.fbi_width * fPtr->fbi.fbi_height * 3; 972 } else { 973 len = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 974 } 975 break; 976 case 32: 977 if (fPtr->fbi.fbi_stride == fPtr->fbi.fbi_width) { 978 xf86Msg(X_ERROR, "Bogus stride == width in 32bit colour\n"); 979 len = fPtr->fbi.fbi_width * fPtr->fbi.fbi_height * sizeof(int); 980 } else { 981 len = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 982 } 983 break; 984 default: 985 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 986 "unsupported depth %d\n", fPtr->fbi.fbi_bitsperpixel); 987 return FALSE; 988 } 989 /* Switch to graphics mode - required before mmap. */ 990 if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) { 991 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 992 "ioctl WSDISPLAYIO_SMODE: %s\n", 993 strerror(errno)); 994 return FALSE; 995 } 996 /* Get wsdisplay type to handle quirks */ 997 if (ioctl(fPtr->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) { 998 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 999 "ioctl WSDISPLAY_GTYPE: %s\n", 1000 strerror(errno)); 1001 return FALSE; 1002 } 1003 len = max(len, fPtr->fbi.fbi_fbsize); 1004 fPtr->fbmem = wsfb_mmap(len + fPtr->fbi.fbi_fboffset, 0, fPtr->fd); 1005 1006 if (fPtr->fbmem == NULL) { 1007 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1008 "wsfb_mmap: %s\n", strerror(errno)); 1009 return FALSE; 1010 } 1011 fPtr->fbmem_len = len; 1012 1013 WsfbSave(pScrn); 1014 pScrn->vtSema = TRUE; 1015 1016 /* MI layer */ 1017 miClearVisualTypes(); 1018 if (pScrn->bitsPerPixel > 8) { 1019 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, 1020 pScrn->rgbBits, TrueColor)) 1021 return FALSE; 1022 } else { 1023 if (!miSetVisualTypes(pScrn->depth, 1024 miGetDefaultVisualMask(pScrn->depth), 1025 pScrn->rgbBits, pScrn->defaultVisual)) 1026 return FALSE; 1027 } 1028 if (!miSetPixmapDepths()) 1029 return FALSE; 1030 1031 if (fPtr->rotate == WSFB_ROTATE_CW 1032 || fPtr->rotate == WSFB_ROTATE_CCW) { 1033 int tmp = pScrn->virtualX; 1034 pScrn->virtualX = pScrn->displayWidth = pScrn->virtualY; 1035 pScrn->virtualY = tmp; 1036 } 1037 if (fPtr->rotate && !fPtr->PointerMoved) { 1038 fPtr->PointerMoved = pScrn->PointerMoved; 1039 pScrn->PointerMoved = WsfbPointerMoved; 1040 } 1041 1042 fPtr->fbstart = fPtr->fbmem + fPtr->fbi.fbi_fboffset; 1043 1044 if (fPtr->shadowFB) { 1045 if (fPtr->rotate) { 1046 /* 1047 * Note Rotate and Shadow FB options are valid 1048 * only on depth >= 8. 1049 */ 1050 len = pScrn->virtualX * pScrn->virtualY * 1051 (pScrn->bitsPerPixel >> 3); 1052 } else 1053#ifdef HAVE_SHADOW_AFB 1054 if (fPtr->planarAfb) { 1055 /* always 8bpp */ 1056 len = pScrn->virtualX * pScrn->virtualY; 1057 } else 1058#endif 1059 { 1060 len = fPtr->fbi.fbi_stride * pScrn->virtualY; 1061 } 1062 fPtr->shadow = calloc(1, len); 1063 1064 if (!fPtr->shadow) { 1065 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1066 "Failed to allocate shadow framebuffer\n"); 1067 return FALSE; 1068 } 1069 } 1070 1071 /* 1072 * fbScreenInit() seems to require "pixel width of frame buffer" 1073 * but it is actually "stride in pixel" of frame buffer, 1074 * per xorg/xserver/tree/fb/fbscreen.c. 1075 */ 1076 if (fPtr->rotate) { 1077 width = pScrn->displayWidth; 1078 } else 1079#ifdef HAVE_SHADOW_AFB 1080 if (fPtr->planarAfb) { 1081 width = pScrn->displayWidth; 1082 } else 1083#endif 1084 { 1085 if (pScrn->bitsPerPixel > 8) { 1086 width = 1087 fPtr->fbi.fbi_stride / (pScrn->bitsPerPixel >> 3); 1088 } else { 1089 width = 1090 fPtr->fbi.fbi_stride * (8 / pScrn->bitsPerPixel); 1091 } 1092 } 1093 switch (pScrn->bitsPerPixel) { 1094 case 1: 1095 ret = fbScreenInit(pScreen, 1096 fPtr->fbstart, 1097 pScrn->virtualX, pScrn->virtualY, 1098 pScrn->xDpi, pScrn->yDpi, 1099 width, pScrn->bitsPerPixel); 1100 break; 1101 case 4: 1102 case 8: 1103 case 16: 1104 case 24: 1105 case 32: 1106 ret = fbScreenInit(pScreen, 1107 fPtr->shadowFB ? fPtr->shadow : fPtr->fbstart, 1108 pScrn->virtualX, pScrn->virtualY, 1109 pScrn->xDpi, pScrn->yDpi, 1110 width, 1111 pScrn->bitsPerPixel); 1112 break; 1113 default: 1114 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1115 "Unsupported bpp: %d\n", pScrn->bitsPerPixel); 1116 return FALSE; 1117 } /* case */ 1118 1119 if (!ret) 1120 return FALSE; 1121 1122 if (pScrn->bitsPerPixel > 8) { 1123 /* Fixup RGB ordering. */ 1124 visual = pScreen->visuals + pScreen->numVisuals; 1125 while (--visual >= pScreen->visuals) { 1126 if ((visual->class | DynamicClass) == DirectColor) { 1127 visual->offsetRed = pScrn->offset.red; 1128 visual->offsetGreen = pScrn->offset.green; 1129 visual->offsetBlue = pScrn->offset.blue; 1130 visual->redMask = pScrn->mask.red; 1131 visual->greenMask = pScrn->mask.green; 1132 visual->blueMask = pScrn->mask.blue; 1133 } 1134 } 1135 } 1136 1137 if (pScrn->bitsPerPixel >= 8) { 1138 if (!fbPictureInit(pScreen, NULL, 0)) 1139 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1140 "RENDER extension initialisation failed.\n"); 1141 } 1142 if (fPtr->shadowFB && !WsfbShadowInit(pScreen)) { 1143 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1144 "shadow framebuffer initialization failed\n"); 1145 return FALSE; 1146 } 1147 1148#ifdef XFreeXDGA 1149 if (!fPtr->rotate) 1150 WsfbDGAInit(pScrn, pScreen); 1151 else 1152 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotated display, " 1153 "disabling DGA\n"); 1154#endif 1155 if (fPtr->rotate) { 1156 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Driver Rotation, " 1157 "disabling RandR\n"); 1158#if 0 1159 xf86DisableRandR(); 1160#endif 1161 if (pScrn->bitsPerPixel == 24) 1162 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1163 "Rotation might be broken in 24 bpp\n"); 1164 } 1165 1166 xf86SetBlackWhitePixels(pScreen); 1167 xf86SetBackingStore(pScreen); 1168 1169 /* Software cursor. */ 1170 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1171 1172 /* check for hardware cursor support */ 1173 if (fPtr->HWCursor) 1174 WsfbSetupCursor(pScreen); 1175 1176 /* 1177 * Colormap 1178 * 1179 * Note that, even on less than 8 bit depth frame buffers, we 1180 * expect the colormap to be programmable with 8 bit values. 1181 * As of now, this is indeed the case on all OpenBSD supported 1182 * graphics hardware. 1183 */ 1184 if (!miCreateDefColormap(pScreen)) 1185 return FALSE; 1186 flags = CMAP_RELOAD_ON_MODE_SWITCH; 1187 1188 ncolors = 0; 1189 if (fPtr->fbi.fbi_pixeltype == WSFB_CI) { 1190 ncolors = fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries; 1191 } 1192 1193 /* On StaticGray visuals, fake a 256 entries colormap. */ 1194 if (ncolors == 0) 1195 ncolors = 256; 1196 1197 if(!xf86HandleColormaps(pScreen, ncolors, 8, WsfbLoadPalette, 1198 NULL, flags)) 1199 return FALSE; 1200 1201#if defined(__NetBSD__) && defined(WSDISPLAY_TYPE_LUNA) 1202 if (wstype == WSDISPLAY_TYPE_LUNA) { 1203 ncolors = fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries; 1204 if (ncolors > 0 1205#ifdef HAVE_SHADOW_AFB 1206 && !fPtr->planarAfb 1207#endif 1208 ) { 1209 /* 1210 * Override palette to use 4bpp/8bpp framebuffers as 1211 * monochrome server by using only the first plane. 1212 * See also comment in WsfbPreInit(). 1213 */ 1214 struct wsdisplay_cmap cmap; 1215 uint8_t r[256], g[256], b[256]; 1216 int p; 1217 1218 for (p = 0; p < ncolors; p++) 1219 r[p] = g[p] = b[p] = (p & 1) ? 0xff : 0; 1220 cmap.index = 0; 1221 cmap.count = ncolors; 1222 cmap.red = r; 1223 cmap.green = g; 1224 cmap.blue = b; 1225 if (ioctl(fPtr->fd, WSDISPLAYIO_PUTCMAP, &cmap) == -1) { 1226 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1227 "ioctl WSDISPLAYIO_PUTCMAP: %s\n", 1228 strerror(errno)); 1229 } 1230 } 1231 } 1232#endif 1233 1234 pScreen->SaveScreen = WsfbSaveScreen; 1235 1236#ifdef XvExtension 1237 { 1238 XF86VideoAdaptorPtr *ptr; 1239 1240 int n = xf86XVListGenericAdaptors(pScrn,&ptr); 1241 if (n) { 1242 xf86XVScreenInit(pScreen,ptr,n); 1243 } 1244 } 1245#endif 1246 1247 /* Wrap the current CloseScreen function. */ 1248 fPtr->CloseScreen = pScreen->CloseScreen; 1249 pScreen->CloseScreen = WsfbCloseScreen; 1250 1251 TRACE_EXIT("WsfbScreenInit"); 1252 return TRUE; 1253} 1254 1255static Bool 1256WsfbCloseScreen(CLOSE_SCREEN_ARGS_DECL) 1257{ 1258 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1259 PixmapPtr pPixmap; 1260 WsfbPtr fPtr = WSFBPTR(pScrn); 1261 1262 1263 TRACE_ENTER("WsfbCloseScreen"); 1264 1265 pPixmap = pScreen->GetScreenPixmap(pScreen); 1266 if (fPtr->shadowFB) 1267 shadowRemove(pScreen, pPixmap); 1268 1269 if (pScrn->vtSema) { 1270 WsfbRestore(pScrn); 1271 if (munmap(fPtr->fbmem, fPtr->fbmem_len + fPtr->fbi.fbi_fboffset) == -1) { 1272 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1273 "munmap: %s\n", strerror(errno)); 1274 } 1275 1276 fPtr->fbmem = NULL; 1277 } 1278#ifdef XFreeXDGA 1279 if (fPtr->pDGAMode) { 1280 free(fPtr->pDGAMode); 1281 fPtr->pDGAMode = NULL; 1282 fPtr->nDGAMode = 0; 1283 } 1284#endif 1285 pScrn->vtSema = FALSE; 1286 1287 /* Unwrap CloseScreen. */ 1288 pScreen->CloseScreen = fPtr->CloseScreen; 1289 TRACE_EXIT("WsfbCloseScreen"); 1290 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1291} 1292 1293static void * 1294WsfbWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1295 CARD32 *size, void *closure) 1296{ 1297 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1298 WsfbPtr fPtr = WSFBPTR(pScrn); 1299 1300 /* 1301 * XXX 1302 * This should never happen. Is it really necessary? 1303 */ 1304 if (fPtr->fbi.fbi_stride) 1305 *size = fPtr->fbi.fbi_stride; 1306 else { 1307 if (ioctl(fPtr->fd, WSDISPLAYIO_LINEBYTES, size) == -1) 1308 return NULL; 1309 fPtr->fbi.fbi_stride = *size; 1310 } 1311 return ((CARD8 *)fPtr->fbstart + row * fPtr->fbi.fbi_stride + offset); 1312} 1313 1314#ifdef HAVE_SHADOW_AFB 1315/* 1316 * For use with shadowUpdateAfb8 1317 * 1318 * For video memory layout with non-interleaved bitplanes. 1319 */ 1320static void * 1321WsfbWindowAfb(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, 1322 CARD32 *size, void *closure) 1323{ 1324 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1325 WsfbPtr fPtr = WSFBPTR(pScrn); 1326 1327 /* size is offset from start of bitplane to next bitplane */ 1328 *size = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 1329 return ((CARD8 *)fPtr->fbstart + row * fPtr->fbi.fbi_stride + offset); 1330} 1331#endif 1332 1333static void 1334WsfbPointerMoved(SCRN_ARG_TYPE arg, int x, int y) 1335{ 1336 SCRN_INFO_PTR(arg); 1337 WsfbPtr fPtr = WSFBPTR(pScrn); 1338 int newX, newY; 1339 1340 switch (fPtr->rotate) 1341 { 1342 case WSFB_ROTATE_CW: 1343 /* 90 degrees CW rotation. */ 1344 newX = pScrn->pScreen->height - y - 1; 1345 newY = x; 1346 break; 1347 1348 case WSFB_ROTATE_CCW: 1349 /* 90 degrees CCW rotation. */ 1350 newX = y; 1351 newY = pScrn->pScreen->width - x - 1; 1352 break; 1353 1354 case WSFB_ROTATE_UD: 1355 /* 180 degrees UD rotation. */ 1356 newX = pScrn->pScreen->width - x - 1; 1357 newY = pScrn->pScreen->height - y - 1; 1358 break; 1359 1360 default: 1361 /* No rotation. */ 1362 newX = x; 1363 newY = y; 1364 break; 1365 } 1366 1367 /* Pass adjusted pointer coordinates to wrapped PointerMoved function. */ 1368 (*fPtr->PointerMoved)(arg, newX, newY); 1369} 1370 1371static Bool 1372WsfbEnterVT(VT_FUNC_ARGS_DECL) 1373{ 1374 SCRN_INFO_PTR(arg); 1375 WsfbPtr fPtr = WSFBPTR(pScrn); 1376 int mode; 1377 1378 TRACE_ENTER("EnterVT"); 1379 pScrn->vtSema = TRUE; 1380 1381 /* Restore the graphics mode. */ 1382 mode = WSDISPLAYIO_MODE_DUMBFB; 1383 if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) { 1384 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1385 "error setting graphics mode %s\n", strerror(errno)); 1386 } 1387 1388 TRACE_EXIT("EnterVT"); 1389 return TRUE; 1390} 1391 1392static void 1393WsfbLeaveVT(VT_FUNC_ARGS_DECL) 1394{ 1395 SCRN_INFO_PTR(arg); 1396 WsfbPtr fPtr = WSFBPTR(pScrn); 1397 int mode; 1398 1399 TRACE_ENTER("LeaveVT"); 1400 1401 /* 1402 * stuff to do: 1403 * - turn off hw cursor 1404 * - restore colour map if WSFB_CI 1405 * - ioctl(WSDISPLAYIO_MODE_EMUL) to notify the kernel driver that 1406 * we're backing off 1407 */ 1408 1409 if (fPtr->fbi.fbi_pixeltype == WSFB_CI && 1410 fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries > 0) { 1411 /* reset colormap for text mode */ 1412 if (ioctl(fPtr->fd, WSDISPLAYIO_PUTCMAP, 1413 &(fPtr->saved_cmap)) == -1) { 1414 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1415 "error restoring colormap %s\n", 1416 strerror(errno)); 1417 } 1418 } 1419 1420 /* Restore the text mode. */ 1421 mode = WSDISPLAYIO_MODE_EMUL; 1422 if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) { 1423 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1424 "error setting text mode %s\n", strerror(errno)); 1425 } 1426 1427 pScrn->vtSema = FALSE; 1428 TRACE_EXIT("LeaveVT"); 1429} 1430 1431static Bool 1432WsfbSwitchMode(SWITCH_MODE_ARGS_DECL) 1433{ 1434 TRACE_ENTER("SwitchMode"); 1435 /* Nothing else to do. */ 1436 return TRUE; 1437} 1438 1439static int 1440WsfbValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1441{ 1442 TRACE_ENTER("ValidMode"); 1443 return MODE_OK; 1444} 1445 1446static void 1447WsfbLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 1448 LOCO *colors, VisualPtr pVisual) 1449{ 1450 WsfbPtr fPtr = WSFBPTR(pScrn); 1451 struct wsdisplay_cmap cmap; 1452 unsigned char red[256],green[256],blue[256]; 1453 int i, indexMin=256, indexMax=0; 1454 1455 TRACE_ENTER("LoadPalette"); 1456 1457 /* nothing to do if there is no color palette support */ 1458 if (fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries == 0) 1459 return; 1460 1461 cmap.count = 1; 1462 cmap.red = red; 1463 cmap.green = green; 1464 cmap.blue = blue; 1465 1466 if (numColors == 1) { 1467 /* Optimisation */ 1468 cmap.index = indices[0]; 1469 red[0] = colors[indices[0]].red; 1470 green[0] = colors[indices[0]].green; 1471 blue[0] = colors[indices[0]].blue; 1472 if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1) 1473 ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno)); 1474 } else { 1475 /* 1476 * Change all colors in 2 ioctls 1477 * and limit the data to be transfered. 1478 */ 1479 for (i = 0; i < numColors; i++) { 1480 if (indices[i] < indexMin) 1481 indexMin = indices[i]; 1482 if (indices[i] > indexMax) 1483 indexMax = indices[i]; 1484 } 1485 cmap.index = indexMin; 1486 cmap.count = indexMax - indexMin + 1; 1487 cmap.red = &red[indexMin]; 1488 cmap.green = &green[indexMin]; 1489 cmap.blue = &blue[indexMin]; 1490 /* Get current map. */ 1491 if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, &cmap) == -1) 1492 ErrorF("ioctl FBIOGETCMAP: %s\n", strerror(errno)); 1493 /* Change the colors that require updating. */ 1494 for (i = 0; i < numColors; i++) { 1495 red[indices[i]] = colors[indices[i]].red; 1496 green[indices[i]] = colors[indices[i]].green; 1497 blue[indices[i]] = colors[indices[i]].blue; 1498 } 1499 /* Write the colormap back. */ 1500 if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1) 1501 ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno)); 1502 } 1503 TRACE_EXIT("LoadPalette"); 1504} 1505 1506static Bool 1507WsfbSaveScreen(ScreenPtr pScreen, int mode) 1508{ 1509 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1510 WsfbPtr fPtr = WSFBPTR(pScrn); 1511 int state; 1512 1513 TRACE_ENTER("SaveScreen"); 1514 1515 if (!pScrn->vtSema) 1516 return TRUE; 1517 1518 if (mode != SCREEN_SAVER_FORCER) { 1519 state = xf86IsUnblank(mode)?WSDISPLAYIO_VIDEO_ON: 1520 WSDISPLAYIO_VIDEO_OFF; 1521 ioctl(fPtr->fd, 1522 WSDISPLAYIO_SVIDEO, &state); 1523 } 1524 TRACE_EXIT("SaveScreen"); 1525 return TRUE; 1526} 1527 1528 1529static void 1530WsfbSave(ScrnInfoPtr pScrn) 1531{ 1532 WsfbPtr fPtr = WSFBPTR(pScrn); 1533 1534 TRACE_ENTER("WsfbSave"); 1535 1536 /* nothing to save if we don't run in colour-indexed mode */ 1537 if (fPtr->fbi.fbi_pixeltype != WSFB_CI) 1538 return; 1539 1540 /* nothing to do if no color palette support */ 1541 if (fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries == 0) 1542 return; 1543 1544 fPtr->saved_cmap.index = 0; 1545 fPtr->saved_cmap.count = fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries; 1546 if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, 1547 &(fPtr->saved_cmap)) == -1) { 1548 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1549 "error saving colormap %s\n", strerror(errno)); 1550 } 1551 TRACE_EXIT("WsfbSave"); 1552 1553} 1554 1555static void 1556WsfbRestore(ScrnInfoPtr pScrn) 1557{ 1558 WsfbPtr fPtr = WSFBPTR(pScrn); 1559 int mode; 1560 1561 TRACE_ENTER("WsfbRestore"); 1562 1563 if (fPtr->fbi.fbi_pixeltype == WSFB_CI && 1564 fPtr->fbi.fbi_subtype.fbi_cmapinfo.cmap_entries > 0) { 1565 /* reset colormap for text mode */ 1566 if (ioctl(fPtr->fd, WSDISPLAYIO_PUTCMAP, 1567 &(fPtr->saved_cmap)) == -1) { 1568 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1569 "error restoring colormap %s\n", 1570 strerror(errno)); 1571 } 1572 } 1573 1574 /* Clear the screen. */ 1575 memset(fPtr->fbstart, 0, fPtr->fbmem_len); 1576 1577 /* Restore the text mode. */ 1578 mode = WSDISPLAYIO_MODE_EMUL; 1579 if (ioctl(fPtr->fd, WSDISPLAYIO_SMODE, &mode) == -1) { 1580 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1581 "error setting text mode %s\n", strerror(errno)); 1582 } 1583 TRACE_EXIT("WsfbRestore"); 1584} 1585 1586#ifdef XFreeXDGA 1587/*********************************************************************** 1588 * DGA stuff 1589 ***********************************************************************/ 1590 1591static Bool 1592WsfbDGAOpenFramebuffer(ScrnInfoPtr pScrn, char **DeviceName, 1593 unsigned char **ApertureBase, int *ApertureSize, 1594 int *ApertureOffset, int *flags) 1595{ 1596 *DeviceName = NULL; /* No special device */ 1597 *ApertureBase = (unsigned char *)(pScrn->memPhysBase); 1598 *ApertureSize = pScrn->videoRam; 1599 *ApertureOffset = pScrn->fbOffset; 1600 *flags = 0; 1601 1602 return TRUE; 1603} 1604 1605static Bool 1606WsfbDGASetMode(ScrnInfoPtr pScrn, DGAModePtr pDGAMode) 1607{ 1608 DisplayModePtr pMode; 1609 int scrnIdx = pScrn->pScreen->myNum; 1610 int frameX0, frameY0; 1611 1612 if (pDGAMode) { 1613 pMode = pDGAMode->mode; 1614 frameX0 = frameY0 = 0; 1615 } else { 1616 if (!(pMode = pScrn->currentMode)) 1617 return TRUE; 1618 1619 frameX0 = pScrn->frameX0; 1620 frameY0 = pScrn->frameY0; 1621 } 1622 1623 if (!(*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode))) 1624 return FALSE; 1625 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, frameX0, frameY0)); 1626 1627 return TRUE; 1628} 1629 1630static void 1631WsfbDGASetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 1632{ 1633 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y)); 1634} 1635 1636static int 1637WsfbDGAGetViewport(ScrnInfoPtr pScrn) 1638{ 1639 return (0); 1640} 1641 1642static DGAFunctionRec WsfbDGAFunctions = 1643{ 1644 WsfbDGAOpenFramebuffer, 1645 NULL, /* CloseFramebuffer */ 1646 WsfbDGASetMode, 1647 WsfbDGASetViewport, 1648 WsfbDGAGetViewport, 1649 NULL, /* Sync */ 1650 NULL, /* FillRect */ 1651 NULL, /* BlitRect */ 1652 NULL, /* BlitTransRect */ 1653}; 1654 1655static void 1656WsfbDGAAddModes(ScrnInfoPtr pScrn) 1657{ 1658 WsfbPtr fPtr = WSFBPTR(pScrn); 1659 DisplayModePtr pMode = pScrn->modes; 1660 DGAModePtr pDGAMode; 1661 1662 do { 1663 pDGAMode = realloc(fPtr->pDGAMode, 1664 (fPtr->nDGAMode + 1) * sizeof(DGAModeRec)); 1665 if (!pDGAMode) 1666 break; 1667 1668 fPtr->pDGAMode = pDGAMode; 1669 pDGAMode += fPtr->nDGAMode; 1670 (void)memset(pDGAMode, 0, sizeof(DGAModeRec)); 1671 1672 ++fPtr->nDGAMode; 1673 pDGAMode->mode = pMode; 1674 pDGAMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 1675 pDGAMode->byteOrder = pScrn->imageByteOrder; 1676 pDGAMode->depth = pScrn->depth; 1677 pDGAMode->bitsPerPixel = pScrn->bitsPerPixel; 1678 pDGAMode->red_mask = pScrn->mask.red; 1679 pDGAMode->green_mask = pScrn->mask.green; 1680 pDGAMode->blue_mask = pScrn->mask.blue; 1681 pDGAMode->visualClass = pScrn->bitsPerPixel > 8 ? 1682 TrueColor : PseudoColor; 1683 pDGAMode->xViewportStep = 1; 1684 pDGAMode->yViewportStep = 1; 1685 pDGAMode->viewportWidth = pMode->HDisplay; 1686 pDGAMode->viewportHeight = pMode->VDisplay; 1687 1688 if (fPtr->fbi.fbi_stride) 1689 pDGAMode->bytesPerScanline = fPtr->fbi.fbi_stride; 1690 else { 1691 ioctl(fPtr->fd, WSDISPLAYIO_LINEBYTES, 1692 &fPtr->fbi.fbi_stride); 1693 pDGAMode->bytesPerScanline = fPtr->fbi.fbi_stride; 1694 } 1695 1696 pDGAMode->imageWidth = pMode->HDisplay; 1697 pDGAMode->imageHeight = pMode->VDisplay; 1698 pDGAMode->pixmapWidth = pDGAMode->imageWidth; 1699 pDGAMode->pixmapHeight = pDGAMode->imageHeight; 1700 pDGAMode->maxViewportX = pScrn->virtualX - 1701 pDGAMode->viewportWidth; 1702 pDGAMode->maxViewportY = pScrn->virtualY - 1703 pDGAMode->viewportHeight; 1704 1705 pDGAMode->address = fPtr->fbstart; 1706 1707 pMode = pMode->next; 1708 } while (pMode != pScrn->modes); 1709} 1710 1711static Bool 1712WsfbDGAInit(ScrnInfoPtr pScrn, ScreenPtr pScreen) 1713{ 1714 WsfbPtr fPtr = WSFBPTR(pScrn); 1715 1716 if (pScrn->depth < 8) 1717 return FALSE; 1718 1719 if (!fPtr->nDGAMode) 1720 WsfbDGAAddModes(pScrn); 1721 1722 return (DGAInit(pScreen, &WsfbDGAFunctions, 1723 fPtr->pDGAMode, fPtr->nDGAMode)); 1724} 1725#endif 1726 1727static Bool 1728WsfbDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, 1729 pointer ptr) 1730{ 1731 xorgHWFlags *flag; 1732 1733 switch (op) { 1734 case GET_REQUIRED_HW_INTERFACES: 1735 flag = (CARD32*)ptr; 1736 (*flag) = 0; 1737 return TRUE; 1738 default: 1739 return FALSE; 1740 } 1741} 1742 1743static inline void 1744memcpy32sw(void *dest, void *src, int len) 1745{ 1746 uint32_t *d = dest, *s = src; 1747 1748#if DEBUG 1749 if ((((long)dest & 3) + ((long)src & 3) + (len & 3)) != 0) { 1750 xf86Msg(X_ERROR, "unaligned %s\n", __func__); 1751 return; 1752 } 1753#endif 1754 while (len > 0) { 1755 *d = bswap32(*s); 1756 d++; 1757 s++; 1758 len -= 4; 1759 } 1760} 1761 1762/* adapted from miext/shadow/shpacked.c::shadowUpdatePacked() */ 1763void 1764WsfbShadowUpdateSwap32(ScreenPtr pScreen, shadowBufPtr pBuf) 1765{ 1766 RegionPtr damage = DamageRegion (pBuf->pDamage); 1767 PixmapPtr pShadow = pBuf->pPixmap; 1768 int nbox = RegionNumRects (damage); 1769 BoxPtr pbox = RegionRects (damage); 1770 FbBits *shaBase, *shaLine, *sha; 1771 FbStride shaStride; 1772 int scrBase, scrLine, scr; 1773 int shaBpp; 1774 int shaXoff, shaYoff; /* XXX assumed to be zero */ 1775 int x, y, w, h, width; 1776 int i; 1777 FbBits *winBase = NULL, *win; 1778 CARD32 winSize; 1779 1780 fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); 1781 while (nbox--) 1782 { 1783 x = pbox->x1 * shaBpp; 1784 y = pbox->y1; 1785 w = (pbox->x2 - pbox->x1) * shaBpp; 1786 h = pbox->y2 - pbox->y1; 1787 1788 scrLine = (x >> FB_SHIFT); 1789 shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); 1790 1791 x &= FB_MASK; 1792 w = (w + x + FB_MASK) >> FB_SHIFT; 1793 1794 while (h--) 1795 { 1796 winSize = 0; 1797 scrBase = 0; 1798 width = w; 1799 scr = scrLine; 1800 sha = shaLine; 1801 while (width) { 1802 /* how much remains in this window */ 1803 i = scrBase + winSize - scr; 1804 if (i <= 0 || scr < scrBase) 1805 { 1806 winBase = (FbBits *) (*pBuf->window) (pScreen, 1807 y, 1808 scr * sizeof (FbBits), 1809 SHADOW_WINDOW_WRITE, 1810 &winSize, 1811 pBuf->closure); 1812 if(!winBase) 1813 return; 1814 scrBase = scr; 1815 winSize /= sizeof (FbBits); 1816 i = winSize; 1817 } 1818 win = winBase + (scr - scrBase); 1819 if (i > width) 1820 i = width; 1821 width -= i; 1822 scr += i; 1823 memcpy32sw(win, sha, i * sizeof(FbBits)); 1824 sha += i; 1825 } 1826 shaLine += shaStride; 1827 y++; 1828 } 1829 pbox++; 1830 } 1831} 1832 1833void 1834WsfbShadowUpdateSplit(ScreenPtr pScreen, shadowBufPtr pBuf) 1835{ 1836 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1837 WsfbPtr fPtr = WSFBPTR(pScrn); 1838 RegionPtr damage = DamageRegion (pBuf->pDamage); 1839 PixmapPtr pShadow = pBuf->pPixmap; 1840 int nbox = RegionNumRects (damage); 1841 BoxPtr pbox = RegionRects (damage); 1842 FbBits *shaBase, *shaLine, *sha; 1843 FbStride shaStride; 1844 int scrBase, scrLine, scr; 1845 int shaBpp; 1846 int shaXoff, shaYoff; /* XXX assumed to be zero */ 1847 int x, y, w, h, width; 1848 int i; 1849 FbBits *winBase = NULL, *win, *win2; 1850 unsigned long split = fPtr->fbi.fbi_fbsize / 2; 1851 CARD32 winSize; 1852 1853 fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); 1854 while (nbox--) 1855 { 1856 x = pbox->x1 * shaBpp; 1857 y = pbox->y1; 1858 w = (pbox->x2 - pbox->x1) * shaBpp; 1859 h = pbox->y2 - pbox->y1; 1860 1861 scrLine = (x >> FB_SHIFT); 1862 shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); 1863 1864 x &= FB_MASK; 1865 w = (w + x + FB_MASK) >> FB_SHIFT; 1866 1867 while (h--) 1868 { 1869 winSize = 0; 1870 scrBase = 0; 1871 width = w; 1872 scr = scrLine; 1873 sha = shaLine; 1874 while (width) { 1875 /* how much remains in this window */ 1876 i = scrBase + winSize - scr; 1877 if (i <= 0 || scr < scrBase) 1878 { 1879 winBase = (FbBits *) (*pBuf->window) (pScreen, 1880 y, 1881 scr * sizeof (FbBits), 1882 SHADOW_WINDOW_WRITE, 1883 &winSize, 1884 pBuf->closure); 1885 if(!winBase) 1886 return; 1887 scrBase = scr; 1888 winSize /= sizeof (FbBits); 1889 i = winSize; 1890 } 1891 win = winBase + (scr - scrBase); 1892 win2 = (FbBits *)(split + (unsigned long)win); 1893 if (i > width) 1894 i = width; 1895 width -= i; 1896 scr += i; 1897 memcpy(win, sha, i * sizeof(FbBits)); 1898 memcpy(win2, sha, i * sizeof(FbBits)); 1899 sha += i; 1900 } 1901 shaLine += shaStride; 1902 y++; 1903 } 1904 pbox++; 1905 } 1906} 1907