1/* $NetBSD: ffb_exa.c,v 1.5 2016/09/27 19:12:53 joerg Exp $ */ 2/* 3 * Copyright (c) 2015 Michael Lorenz 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * - Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * - Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 */ 31 32#include <sys/types.h> 33 34#ifdef HAVE_CONFIG_H 35#include "config.h" 36#endif 37 38#include "ffb_fifo.h" 39#include "ffb_rcache.h" 40#include "ffb.h" 41#include "ffb_regs.h" 42 43/* all driver need this */ 44#include "xf86.h" 45#include "xf86_OSproc.h" 46#include "compiler.h" 47#include "exa.h" 48 49extern void VISmoveImageRL(unsigned char *, unsigned char *, long, long, long, long); 50extern void VISmoveImageLR(unsigned char *, unsigned char *, long, long, long, long); 51 52/*#define FFB_DEBUG*/ 53 54#ifdef FFB_DEBUG 55#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__); 56#define DPRINTF xf86Msg 57#else 58#define ENTER 59#define DPRINTF while (0) xf86Msg 60#endif 61 62#define arraysize(ary) (sizeof(ary) / sizeof(ary[0])) 63 64int src_formats[] = {PICT_a8r8g8b8, PICT_x8r8g8b8, 65 PICT_a8b8g8r8, PICT_x8b8g8r8, PICT_a8}; 66int tex_formats[] = {PICT_a8r8g8b8, PICT_a8b8g8r8, PICT_a8}; 67 68static void 69FFBWaitMarker(ScreenPtr pScreen, int Marker) 70{ 71 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 72 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 73 ffb_fbcPtr ffb = pFfb->regs; 74 75 FFBWait(pFfb, ffb); 76} 77 78static Bool 79FFBPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, 80 int xdir, int ydir, int alu, Pixel planemask) 81{ 82 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 83 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 84 ffb_fbcPtr ffb = pFfb->regs; 85 86 ENTER; 87 pFfb->srcpitch = exaGetPixmapPitch(pSrcPixmap); 88 pFfb->srcoff = exaGetPixmapOffset(pSrcPixmap); 89 pFfb->xdir = xdir; 90 pFfb->ydir = ydir; 91 pFfb->rop = alu; 92 pFfb->planemask = planemask; 93 return TRUE; 94} 95 96static void 97FFBCopy(PixmapPtr pDstPixmap, 98 int srcX, int srcY, int dstX, int dstY, int w, int h) 99{ 100 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 101 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 102 ffb_fbcPtr ffb = pFfb->regs; 103 unsigned char *src, *dst, *sfb32; 104 int psz_shift = 2; 105 int sdkind; 106 107 ENTER; 108 if ((srcX == dstX) && (srcY != dstY) && (pFfb->rop == GXcopy)) { 109 /* we can use the vscroll command */ 110 FFB_ATTR_VSCROLL_XAA(pFfb, pFfb->planemask); 111 FFBFifo(pFfb, 7); 112 ffb->drawop = FFB_DRAWOP_VSCROLL; 113 FFB_WRITE64(&ffb->by, srcY, srcX); 114 FFB_WRITE64_2(&ffb->dy, dstY, dstX); 115 FFB_WRITE64_3(&ffb->bh, h, w); 116 exaMarkSync(pDstPixmap->drawable.pScreen); 117 return; 118 } 119 FFB_ATTR_SFB_VAR_XAA(pFfb, pFfb->planemask, pFfb->rop); 120 if (pFfb->use_blkread_prefetch) { 121 FFBFifo(pFfb, 1); 122 if (pFfb->xdir < 0) 123 ffb->mer = FFB_MER_EDRA; 124 else 125 ffb->mer = FFB_MER_EIRA; 126 } 127 FFBWait(pFfb, ffb); 128 sfb32 = (unsigned char *) pFfb->sfb32; 129 src = sfb32 + (srcY * (2048 << psz_shift)) + (srcX << psz_shift); 130 dst = sfb32 + (dstY * (2048 << psz_shift)) + (dstX << psz_shift); 131 sdkind = (2048 << psz_shift); 132 133 if (pFfb->ydir < 0) { 134 src += ((h - 1) * (2048 << psz_shift)); 135 dst += ((h - 1) * (2048 << psz_shift)); 136 sdkind = -sdkind; 137 } 138 w <<= psz_shift; 139 if (pFfb->xdir < 0) 140 VISmoveImageRL(src, dst, w, h, sdkind, sdkind); 141 else 142 VISmoveImageLR(src, dst, w, h, sdkind, sdkind); 143 if (pFfb->use_blkread_prefetch) { 144 FFBFifo(pFfb, 1); 145 ffb->mer = FFB_MER_DRA; 146 } 147} 148 149static void 150FFBDoneCopy(PixmapPtr pDstPixmap) 151{ 152} 153 154static Bool 155FFBPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) 156{ 157 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 158 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 159 ffb_fbcPtr ffb = pFfb->regs; 160 unsigned int ppc, ppc_mask, fbc; 161 162 ENTER; 163 FFBWait(pFfb, ffb); 164 pFfb->planemask = planemask; 165 pFfb->rop = alu; 166 167 fbc = pFfb->fbc; 168 if (pFfb->ffb_res == ffb_res_high) 169 fbc |= FFB_FBC_WB_B; 170 ppc = FFB_PPC_ABE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID; 171 ppc_mask = FFB_PPC_ABE_MASK | FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK; 172 173 FFB_ATTR_RAW(pFfb, ppc, ppc_mask, planemask, 174 (FFB_ROP_EDIT_BIT | alu) | (FFB_ROP_NEW << 8), 175 FFB_DRAWOP_RECTANGLE, fg, fbc, pFfb->wid); 176 177 return TRUE; 178} 179 180static void 181FFBSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 182{ 183 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 184 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 185 ffb_fbcPtr ffb = pFfb->regs; 186 187 ENTER; 188 FFBFifo(pFfb, 4); 189 FFB_WRITE64(&ffb->by, y1, x1); 190 FFB_WRITE64_2(&ffb->bh, y2 - y1, x2 - x1); 191 exaMarkSync(pPixmap->drawable.pScreen); 192} 193 194static Bool 195FFBUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 196 char *src, int src_pitch) 197{ 198 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 199 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 200 unsigned char *dst, *sfb32; 201 int psz_shift = 2; 202 ffb_fbcPtr ffb = pFfb->regs; 203 204 ENTER; 205 FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy); 206 FFBWait(pFfb, ffb); 207 208 sfb32 = (unsigned char *) pFfb->sfb32; 209 dst = sfb32 + (y * (2048 << psz_shift)) + (x << psz_shift); 210 VISmoveImageLR(src, dst, w << psz_shift, h, 211 src_pitch, (2048 << psz_shift)); 212 return TRUE; 213} 214 215static Bool 216FFBDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 217 char *dst, int dst_pitch) 218{ 219 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 220 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 221 unsigned char *src, *sfb32; 222 int psz_shift = 2; 223 ffb_fbcPtr ffb = pFfb->regs; 224 225 ENTER; 226 FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy); 227 if (pFfb->use_blkread_prefetch) { 228 FFBFifo(pFfb, 1); 229 ffb->mer = FFB_MER_EIRA; 230 } 231 FFBWait(pFfb, ffb); 232 233 sfb32 = (unsigned char *) pFfb->sfb32; 234 src = sfb32 + (y * (2048 << psz_shift)) + (x << psz_shift); 235 VISmoveImageLR(src, dst, w << psz_shift, h, 236 (2048 << psz_shift), dst_pitch); 237 if (pFfb->use_blkread_prefetch) { 238 FFBFifo(pFfb, 1); 239 ffb->mer = FFB_MER_DRA; 240 } 241 return TRUE; 242} 243 244static Bool 245FFBCheckComposite(int op, PicturePtr pSrcPicture, 246 PicturePtr pMaskPicture, 247 PicturePtr pDstPicture) 248{ 249 int i, ok = FALSE; 250 251 ENTER; 252 253 i = 0; 254 while ((i < arraysize(src_formats)) && (!ok)) { 255 ok = (pSrcPicture->format == src_formats[i]); 256 i++; 257 } 258 259 if (!ok) { 260 xf86Msg(X_ERROR, "%s: unsupported src format %x\n", 261 __func__, pSrcPicture->format); 262 return FALSE; 263 } 264 265 DPRINTF(X_ERROR, "src is %x, %d: %d %d\n", pSrcPicture->format, op, 266 pSrcPicture->pDrawable->width, pSrcPicture->pDrawable->height); 267 268 if (pMaskPicture != NULL) { 269 DPRINTF(X_ERROR, "mask is %x %d %d\n", pMaskPicture->format, 270 pMaskPicture->pDrawable->width, 271 pMaskPicture->pDrawable->height); 272 } 273 return TRUE; 274} 275 276static Bool 277FFBPrepareComposite(int op, PicturePtr pSrcPicture, 278 PicturePtr pMaskPicture, 279 PicturePtr pDstPicture, 280 PixmapPtr pSrc, 281 PixmapPtr pMask, 282 PixmapPtr pDst) 283{ 284 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 285 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 286 287 ENTER; 288 289 pFfb->no_source_pixmap = FALSE; 290 pFfb->source_is_solid = FALSE; 291 292 if (pSrcPicture->format == PICT_a1) { 293 xf86Msg(X_ERROR, "src mono, dst %x, op %d\n", 294 pDstPicture->format, op); 295 if (pMaskPicture != NULL) { 296 xf86Msg(X_ERROR, "msk %x\n", pMaskPicture->format); 297 } 298 } 299 if (pSrcPicture->pSourcePict != NULL) { 300 if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) { 301 pFfb->fillcolour = 302 pSrcPicture->pSourcePict->solidFill.color; 303 DPRINTF(X_ERROR, "%s: solid src %08"PRIx32"\n", 304 __func__, (uint32_t)pFfb->fillcolour); 305 pFfb->no_source_pixmap = TRUE; 306 pFfb->source_is_solid = TRUE; 307 } 308 } 309 if ((pMaskPicture != NULL) && (pMaskPicture->pSourcePict != NULL)) { 310 if (pMaskPicture->pSourcePict->type == 311 SourcePictTypeSolidFill) { 312 pFfb->fillcolour = 313 pMaskPicture->pSourcePict->solidFill.color; 314 xf86Msg(X_ERROR, "%s: solid mask %08"PRIx32"\n", 315 __func__, (uint32_t)pFfb->fillcolour); 316 } 317 } 318 if (pMaskPicture != NULL) { 319 pFfb->mskoff = exaGetPixmapOffset(pMask); 320 pFfb->mskpitch = exaGetPixmapPitch(pMask); 321 pFfb->mskformat = pMaskPicture->format; 322 } else { 323 pFfb->mskoff = 0; 324 pFfb->mskpitch = 0; 325 pFfb->mskformat = 0; 326 } 327 if (pSrc != NULL) { 328 pFfb->source_is_solid = 329 ((pSrc->drawable.width == 1) && (pSrc->drawable.height == 1)); 330 pFfb->srcoff = exaGetPixmapOffset(pSrc); 331 pFfb->srcpitch = exaGetPixmapPitch(pSrc); 332 if (pFfb->source_is_solid) { 333 pFfb->fillcolour = *(uint32_t *)(pFfb->fb + pFfb->srcoff); 334 } 335 } 336 pFfb->srcformat = pSrcPicture->format; 337 pFfb->dstformat = pDstPicture->format; 338 339 if (pFfb->source_is_solid) { 340 uint32_t temp; 341 342 /* swap solid source as needed */ 343 switch (pFfb->srcformat) { 344 case PICT_a8r8g8b8: 345 case PICT_x8r8g8b8: 346 temp = (pFfb->fillcolour & 0x000000ff) << 16; 347 temp |= (pFfb->fillcolour & 0x00ff0000) >> 16; 348 temp |= (pFfb->fillcolour & 0xff00ff00); 349 pFfb->fillcolour = temp; 350 break; 351 } 352 } 353 pFfb->op = op; 354 return TRUE; 355} 356 357static void 358FFBComposite(PixmapPtr pDst, int srcX, int srcY, 359 int maskX, int maskY, 360 int dstX, int dstY, 361 int width, int height) 362{ 363 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 364 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 365 exaMarkSync(pDst->drawable.pScreen); 366} 367 368static Bool 369FFBPrepareAccess(PixmapPtr pPix, int index) 370{ 371 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; 372 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 373 ffb_fbcPtr ffb = pFfb->regs; 374 375 ENTER; 376 FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy); 377 FFBWait(pFfb, ffb); 378 379 return TRUE; 380} 381 382static void 383FFBFinishAccess(PixmapPtr pPix, int index) 384{ 385} 386 387Bool 388FFBInitEXA(ScreenPtr pScreen) 389{ 390 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 391 FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 392 ffb_fbcPtr ffb = pFfb->regs; 393 ExaDriverPtr pExa; 394 395 pFfb->fbc = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A | 396 FFB_FBC_WE_FORCEON | 397 FFB_FBC_SB_BOTH | 398 FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | 399 FFB_FBC_RGBE_MASK | 400 FFB_FBC_XE_ON); 401 pFfb->wid = FFBWidAlloc(pFfb, TrueColor, 0, TRUE); 402 if (pFfb->wid == (unsigned int) -1) 403 return FALSE; 404 405 pFfb->ppc_cache = (FFB_PPC_FW_DISABLE | 406 FFB_PPC_VCE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | 407 FFB_PPC_XS_WID | FFB_PPC_YS_CONST | FFB_PPC_ZS_CONST | 408 FFB_PPC_DCE_DISABLE | FFB_PPC_ABE_DISABLE | FFB_PPC_TBE_OPAQUE); 409 pFfb->wid_cache = pFfb->wid; 410 pFfb->pmask_cache = ~0; 411 pFfb->rop_cache = (FFB_ROP_NEW | (FFB_ROP_NEW << 8)); 412 pFfb->drawop_cache = FFB_DRAWOP_RECTANGLE; 413 pFfb->fg_cache = pFfb->bg_cache = 0; 414 pFfb->fontw_cache = 32; 415 pFfb->fontinc_cache = (1 << 16) | 0; 416 pFfb->fbc_cache = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A | 417 FFB_FBC_WE_FORCEON | 418 FFB_FBC_SB_BOTH | 419 FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | 420 FFB_FBC_RGBE_OFF | 421 FFB_FBC_XE_ON); 422 423 /* We will now clear the screen: we'll draw a rectangle covering all the 424 * viewscreen, using a 'blackness' ROP. 425 */ 426 FFBFifo(pFfb, 22); 427 ffb->fbc = pFfb->fbc_cache; 428 ffb->ppc = pFfb->ppc_cache; 429 ffb->wid = pFfb->wid_cache; 430 ffb->xpmask = 0xff; 431 ffb->pmask = pFfb->pmask_cache; 432 ffb->rop = pFfb->rop_cache; 433 ffb->drawop = pFfb->drawop_cache; 434 ffb->fg = pFfb->fg_cache; 435 ffb->bg = pFfb->bg_cache; 436 ffb->fontw = pFfb->fontw_cache; 437 ffb->fontinc = pFfb->fontinc_cache; 438 ffb->xclip = FFB_XCLIP_TEST_ALWAYS; 439 ffb->cmp = 0x80808080; 440 ffb->matchab = 0x80808080; 441 ffb->magnab = 0x80808080; 442 ffb->blendc = (FFB_BLENDC_FORCE_ONE | 443 FFB_BLENDC_DF_ONE_M_A | 444 FFB_BLENDC_SF_A); 445 ffb->blendc1 = 0; 446 ffb->blendc2 = 0; 447 FFB_WRITE64(&ffb->by, 0, 0); 448 FFB_WRITE64_2(&ffb->bh, pFfb->psdp->height, pFfb->psdp->width); 449 FFBWait(pFfb, ffb); 450 451 FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy); 452 FFBWait(pFfb, ffb); 453 454 FFB_HardwareSetup(pFfb); 455 pExa = exaDriverAlloc(); 456 if (!pExa) 457 return FALSE; 458 459 pFfb->pExa = pExa; 460 461 pExa->exa_major = EXA_VERSION_MAJOR; 462 pExa->exa_minor = EXA_VERSION_MINOR; 463 464 465 pExa->memoryBase = (char *)pFfb->sfb32; 466 /* 467 * we don't have usable off-screen memory but EXA craps out if we don't 468 * pretend that we do, so register a ridiculously small amount and 469 * cross fingers 470 */ 471 pExa->memorySize = 8192 * pFfb->psdp->height + 4; 472 pExa->offScreenBase = pExa->memorySize - 4; 473 474 /* we want to use 64bit aligned accesses */ 475 pExa->pixmapOffsetAlign = 8; 476 pExa->pixmapPitchAlign = 8; 477 478 pExa->flags = EXA_OFFSCREEN_PIXMAPS | 479 /*EXA_SUPPORTS_OFFSCREEN_OVERLAPS |*/ 480 EXA_MIXED_PIXMAPS; 481 482 pExa->maxX = 2048; 483 pExa->maxY = 2048; 484 485 pExa->WaitMarker = FFBWaitMarker; 486 487 pExa->PrepareSolid = FFBPrepareSolid; 488 pExa->Solid = FFBSolid; 489 pExa->DoneSolid = FFBDoneCopy; 490 491 pExa->PrepareCopy = FFBPrepareCopy; 492 pExa->Copy = FFBCopy; 493 pExa->DoneCopy = FFBDoneCopy; 494 495 pExa->UploadToScreen = FFBUploadToScreen; 496 pExa->DownloadFromScreen = FFBDownloadFromScreen; 497 498 pExa->PrepareAccess = FFBPrepareAccess; 499 pExa->FinishAccess = FFBFinishAccess; 500 501if(0) { 502 pExa->CheckComposite = FFBCheckComposite; 503 pExa->PrepareComposite = FFBPrepareComposite; 504 pExa->Composite = FFBComposite; 505 pExa->DoneComposite = FFBDoneCopy; 506} 507 return exaDriverInit(pScreen, pExa); 508} 509