1/* 2 * Copyright 2007 NVIDIA, Corporation 3 * Copyright 2008 Ben Skeggs 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24#include "nv_include.h" 25#include "nv_rop.h" 26 27#include "nv50_accel.h" 28 29#define NV50EXA_LOCALS(p) \ 30 ScrnInfoPtr pScrn = xf86ScreenToScrn((p)->drawable.pScreen); \ 31 NVPtr pNv = NVPTR(pScrn); \ 32 struct nouveau_pushbuf *push = pNv->pushbuf; (void)push; 33 34#define BF(f) NV50_BLEND_FACTOR_##f 35 36struct nv50_blend_op { 37 unsigned src_alpha; 38 unsigned dst_alpha; 39 unsigned src_blend; 40 unsigned dst_blend; 41}; 42 43static struct nv50_blend_op 44NV50EXABlendOp[] = { 45/* Clear */ { 0, 0, BF( ZERO), BF( ZERO) }, 46/* Src */ { 0, 0, BF( ONE), BF( ZERO) }, 47/* Dst */ { 0, 0, BF( ZERO), BF( ONE) }, 48/* Over */ { 1, 0, BF( ONE), BF(ONE_MINUS_SRC_ALPHA) }, 49/* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ONE) }, 50/* In */ { 0, 1, BF( DST_ALPHA), BF( ZERO) }, 51/* InReverse */ { 1, 0, BF( ZERO), BF( SRC_ALPHA) }, 52/* Out */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ZERO) }, 53/* OutReverse */ { 1, 0, BF( ZERO), BF(ONE_MINUS_SRC_ALPHA) }, 54/* Atop */ { 1, 1, BF( DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) }, 55/* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF( SRC_ALPHA) }, 56/* Xor */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) }, 57/* Add */ { 0, 0, BF( ONE), BF( ONE) }, 58}; 59 60static Bool 61NV50EXA2DSurfaceFormat(PixmapPtr ppix, uint32_t *fmt) 62{ 63 NV50EXA_LOCALS(ppix); 64 65 switch (ppix->drawable.bitsPerPixel) { 66 case 8 : *fmt = NV50_SURFACE_FORMAT_R8_UNORM; break; 67 case 15: *fmt = NV50_SURFACE_FORMAT_BGR5_X1_UNORM; break; 68 case 16: *fmt = NV50_SURFACE_FORMAT_B5G6R5_UNORM; break; 69 case 24: *fmt = NV50_SURFACE_FORMAT_BGRX8_UNORM; break; 70 case 30: *fmt = NV50_SURFACE_FORMAT_RGB10_A2_UNORM; break; 71 case 32: *fmt = NV50_SURFACE_FORMAT_BGRA8_UNORM; break; 72 default: 73 NOUVEAU_FALLBACK("Unknown surface format for bpp=%d\n", 74 ppix->drawable.bitsPerPixel); 75 return FALSE; 76 } 77 78 return TRUE; 79} 80 81static void NV50EXASetClip(PixmapPtr ppix, int x, int y, int w, int h) 82{ 83 NV50EXA_LOCALS(ppix); 84 85 BEGIN_NV04(push, NV50_2D(CLIP_X), 4); 86 PUSH_DATA (push, x); 87 PUSH_DATA (push, y); 88 PUSH_DATA (push, w); 89 PUSH_DATA (push, h); 90} 91 92static void 93NV50EXAAcquireSurface2D(PixmapPtr ppix, int is_src, uint32_t fmt) 94{ 95 NV50EXA_LOCALS(ppix); 96 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); 97 struct nouveau_pixmap *nvpix = nouveau_pixmap(ppix); 98 int mthd = is_src ? NV50_2D_SRC_FORMAT : NV50_2D_DST_FORMAT; 99 uint32_t bo_flags; 100 101 bo_flags = nvpix->shared ? NOUVEAU_BO_GART : NOUVEAU_BO_VRAM; 102 bo_flags |= is_src ? NOUVEAU_BO_RD : NOUVEAU_BO_WR; 103 104 if (!nv50_style_tiled_pixmap(ppix)) { 105 BEGIN_NV04(push, SUBC_2D(mthd), 2); 106 PUSH_DATA (push, fmt); 107 PUSH_DATA (push, 1); 108 BEGIN_NV04(push, SUBC_2D(mthd + 0x14), 1); 109 PUSH_DATA (push, (uint32_t)exaGetPixmapPitch(ppix)); 110 } else { 111 BEGIN_NV04(push, SUBC_2D(mthd), 5); 112 PUSH_DATA (push, fmt); 113 PUSH_DATA (push, 0); 114 PUSH_DATA (push, bo->config.nv50.tile_mode); 115 PUSH_DATA (push, 1); 116 PUSH_DATA (push, 0); 117 } 118 119 BEGIN_NV04(push, SUBC_2D(mthd + 0x18), 4); 120 PUSH_DATA (push, ppix->drawable.width); 121 PUSH_DATA (push, ppix->drawable.height); 122 PUSH_DATA (push, bo->offset >> 32); 123 PUSH_DATA (push, bo->offset); 124 125 if (is_src == 0) 126 NV50EXASetClip(ppix, 0, 0, ppix->drawable.width, ppix->drawable.height); 127 128 PUSH_REFN (push, bo, bo_flags); 129} 130 131static void 132NV50EXASetPattern(PixmapPtr pdpix, int col0, int col1, int pat0, int pat1) 133{ 134 NV50EXA_LOCALS(pdpix); 135 136 BEGIN_NV04(push, NV50_2D(PATTERN_COLOR(0)), 4); 137 PUSH_DATA (push, col0); 138 PUSH_DATA (push, col1); 139 PUSH_DATA (push, pat0); 140 PUSH_DATA (push, pat1); 141} 142 143static void 144NV50EXASetROP(PixmapPtr pdpix, int alu, Pixel planemask) 145{ 146 NV50EXA_LOCALS(pdpix); 147 int rop; 148 149 if (planemask != ~0) 150 rop = NVROP[alu].copy_planemask; 151 else 152 rop = NVROP[alu].copy; 153 154 BEGIN_NV04(push, NV50_2D(OPERATION), 1); 155 if (alu == GXcopy && EXA_PM_IS_SOLID(&pdpix->drawable, planemask)) { 156 PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY); 157 return; 158 } else { 159 PUSH_DATA (push, NV50_2D_OPERATION_ROP); 160 } 161 162 BEGIN_NV04(push, NV50_2D(PATTERN_COLOR_FORMAT), 2); 163 switch (pdpix->drawable.bitsPerPixel) { 164 case 8: PUSH_DATA (push, 3); break; 165 case 15: PUSH_DATA (push, 1); break; 166 case 16: PUSH_DATA (push, 0); break; 167 case 24: 168 case 32: 169 default: 170 PUSH_DATA (push, 2); 171 break; 172 } 173 PUSH_DATA (push, 1); 174 175 /* There are 16 alu's. 176 * 0-15: copy 177 * 16-31: copy_planemask 178 */ 179 180 if (!EXA_PM_IS_SOLID(&pdpix->drawable, planemask)) { 181 alu += 16; 182 NV50EXASetPattern(pdpix, 0, planemask, ~0, ~0); 183 } else { 184 if (pNv->currentRop > 15) 185 NV50EXASetPattern(pdpix, ~0, ~0, ~0, ~0); 186 } 187 188 if (pNv->currentRop != alu) { 189 BEGIN_NV04(push, NV50_2D(ROP), 1); 190 PUSH_DATA (push, rop); 191 pNv->currentRop = alu; 192 } 193} 194 195Bool 196NV50EXAPrepareSolid(PixmapPtr pdpix, int alu, Pixel planemask, Pixel fg) 197{ 198 NV50EXA_LOCALS(pdpix); 199 uint32_t fmt; 200 201 if (!NV50EXA2DSurfaceFormat(pdpix, &fmt)) 202 NOUVEAU_FALLBACK("rect format\n"); 203 204 if (!PUSH_SPACE(push, 64)) 205 NOUVEAU_FALLBACK("space\n"); 206 PUSH_RESET(push); 207 208 NV50EXAAcquireSurface2D(pdpix, 0, fmt); 209 NV50EXASetROP(pdpix, alu, planemask); 210 211 BEGIN_NV04(push, NV50_2D(DRAW_SHAPE), 3); 212 PUSH_DATA (push, NV50_2D_DRAW_SHAPE_RECTANGLES); 213 PUSH_DATA (push, fmt); 214 PUSH_DATA (push, fg); 215 216 nouveau_pushbuf_bufctx(push, pNv->bufctx); 217 if (nouveau_pushbuf_validate(push)) { 218 nouveau_pushbuf_bufctx(push, NULL); 219 NOUVEAU_FALLBACK("validate\n"); 220 } 221 222 return TRUE; 223} 224 225void 226NV50EXASolid(PixmapPtr pdpix, int x1, int y1, int x2, int y2) 227{ 228 NV50EXA_LOCALS(pdpix); 229 230 if (!PUSH_SPACE(push, 8)) 231 return; 232 233 BEGIN_NV04(push, NV50_2D(DRAW_POINT32_X(0)), 4); 234 PUSH_DATA (push, x1); 235 PUSH_DATA (push, y1); 236 PUSH_DATA (push, x2); 237 PUSH_DATA (push, y2); 238 239 if ((x2 - x1) * (y2 - y1) >= 512) 240 PUSH_KICK(push); 241} 242 243void 244NV50EXADoneSolid(PixmapPtr pdpix) 245{ 246 NV50EXA_LOCALS(pdpix); 247 nouveau_pushbuf_bufctx(push, NULL); 248} 249 250Bool 251NV50EXAPrepareCopy(PixmapPtr pspix, PixmapPtr pdpix, int dx, int dy, 252 int alu, Pixel planemask) 253{ 254 NV50EXA_LOCALS(pdpix); 255 uint32_t src, dst; 256 257 if (!NV50EXA2DSurfaceFormat(pspix, &src)) 258 NOUVEAU_FALLBACK("src format\n"); 259 if (!NV50EXA2DSurfaceFormat(pdpix, &dst)) 260 NOUVEAU_FALLBACK("dst format\n"); 261 262 if (!PUSH_SPACE(push, 64)) 263 NOUVEAU_FALLBACK("space\n"); 264 PUSH_RESET(push); 265 266 NV50EXAAcquireSurface2D(pspix, 1, src); 267 NV50EXAAcquireSurface2D(pdpix, 0, dst); 268 NV50EXASetROP(pdpix, alu, planemask); 269 270 nouveau_pushbuf_bufctx(push, pNv->bufctx); 271 if (nouveau_pushbuf_validate(push)) { 272 nouveau_pushbuf_bufctx(push, NULL); 273 NOUVEAU_FALLBACK("validate\n"); 274 } 275 276 return TRUE; 277} 278 279void 280NV50EXACopy(PixmapPtr pdpix, int srcX , int srcY, 281 int dstX , int dstY, 282 int width, int height) 283{ 284 NV50EXA_LOCALS(pdpix); 285 286 if (!PUSH_SPACE(push, 32)) 287 return; 288 289 BEGIN_NV04(push, SUBC_2D(NV50_GRAPH_SERIALIZE), 1); 290 PUSH_DATA (push, 0); 291 BEGIN_NV04(push, NV50_2D(BLIT_CONTROL), 1); 292 PUSH_DATA (push, 0); 293 BEGIN_NV04(push, NV50_2D(BLIT_DST_X), 12); 294 PUSH_DATA (push, dstX); 295 PUSH_DATA (push, dstY); 296 PUSH_DATA (push, width); 297 PUSH_DATA (push, height); 298 PUSH_DATA (push, 0); 299 PUSH_DATA (push, 1); 300 PUSH_DATA (push, 0); 301 PUSH_DATA (push, 1); 302 PUSH_DATA (push, 0); 303 PUSH_DATA (push, srcX); 304 PUSH_DATA (push, 0); 305 PUSH_DATA (push, srcY); 306 307 if (width * height >= 512) 308 PUSH_KICK(push); 309} 310 311void 312NV50EXADoneCopy(PixmapPtr pdpix) 313{ 314 NV50EXA_LOCALS(pdpix); 315 nouveau_pushbuf_bufctx(push, NULL); 316} 317 318Bool 319NV50EXAUploadSIFC(const char *src, int src_pitch, 320 PixmapPtr pdpix, int x, int y, int w, int h, int cpp) 321{ 322 NV50EXA_LOCALS(pdpix); 323 ScreenPtr pScreen = pdpix->drawable.pScreen; 324 int line_dwords = (w * cpp + 3) / 4; 325 uint32_t sifc_fmt; 326 Bool ret = FALSE; 327 328 if (!NV50EXA2DSurfaceFormat(pdpix, &sifc_fmt)) 329 NOUVEAU_FALLBACK("hostdata format\n"); 330 331 if (!PUSH_SPACE(push, 64)) 332 NOUVEAU_FALLBACK("space\n"); 333 PUSH_RESET(push); 334 335 NV50EXAAcquireSurface2D(pdpix, 0, sifc_fmt); 336 NV50EXASetClip(pdpix, x, y, w, h); 337 338 BEGIN_NV04(push, NV50_2D(OPERATION), 1); 339 PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY); 340 BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); 341 PUSH_DATA (push, 0); 342 PUSH_DATA (push, sifc_fmt); 343 BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); 344 PUSH_DATA (push, (line_dwords * 4) / cpp); 345 PUSH_DATA (push, h); 346 PUSH_DATA (push, 0); 347 PUSH_DATA (push, 1); 348 PUSH_DATA (push, 0); 349 PUSH_DATA (push, 1); 350 PUSH_DATA (push, 0); 351 PUSH_DATA (push, x); 352 PUSH_DATA (push, 0); 353 PUSH_DATA (push, y); 354 355 nouveau_pushbuf_bufctx(push, pNv->bufctx); 356 if (nouveau_pushbuf_validate(push)) 357 goto out; 358 359 while (h--) { 360 int count = line_dwords; 361 const char *p = src; 362 363 while(count) { 364 int size = count > 1792 ? 1792 : count; 365 366 if (!PUSH_SPACE(push, size + 1)) 367 goto out; 368 BEGIN_NI04(push, NV50_2D(SIFC_DATA), size); 369 PUSH_DATAp(push, p, size); 370 371 p += size * 4; 372 count -= size; 373 } 374 375 src += src_pitch; 376 } 377 378 ret = TRUE; 379out: 380 nouveau_pushbuf_bufctx(push, NULL); 381 if (pdpix == pScreen->GetScreenPixmap(pScreen)) 382 PUSH_KICK(push); 383 return ret; 384} 385 386static Bool 387NV50EXACheckRenderTarget(PicturePtr ppict) 388{ 389 if (ppict->pDrawable->width > 8192 || 390 ppict->pDrawable->height > 8192) 391 NOUVEAU_FALLBACK("render target dimensions exceeded %dx%d\n", 392 ppict->pDrawable->width, 393 ppict->pDrawable->height); 394 395 switch (ppict->format) { 396 case PICT_a8r8g8b8: 397 case PICT_x8r8g8b8: 398 case PICT_r5g6b5: 399 case PICT_a8: 400 case PICT_x1r5g5b5: 401 case PICT_a1r5g5b5: 402 case PICT_x8b8g8r8: 403 case PICT_a2b10g10r10: 404 case PICT_x2b10g10r10: 405 case PICT_a2r10g10b10: 406 case PICT_x2r10g10b10: 407 break; 408 default: 409 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict->format); 410 } 411 412 return TRUE; 413} 414 415static Bool 416NV50EXARenderTarget(PixmapPtr ppix, PicturePtr ppict) 417{ 418 NV50EXA_LOCALS(ppix); 419 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); 420 unsigned format; 421 422 /*XXX: Scanout buffer not tiled, someone needs to figure it out */ 423 if (!nv50_style_tiled_pixmap(ppix)) 424 NOUVEAU_FALLBACK("pixmap is scanout buffer\n"); 425 426 switch (ppict->format) { 427 case PICT_a8r8g8b8: format = NV50_SURFACE_FORMAT_BGRA8_UNORM; break; 428 case PICT_x8r8g8b8: format = NV50_SURFACE_FORMAT_BGRX8_UNORM; break; 429 case PICT_r5g6b5 : format = NV50_SURFACE_FORMAT_B5G6R5_UNORM; break; 430 case PICT_a8 : format = NV50_SURFACE_FORMAT_A8_UNORM; break; 431 case PICT_x1r5g5b5: 432 case PICT_a1r5g5b5: 433 format = NV50_SURFACE_FORMAT_BGR5_A1_UNORM; 434 break; 435 case PICT_x8b8g8r8: format = NV50_SURFACE_FORMAT_RGBX8_UNORM; break; 436 case PICT_a2b10g10r10: 437 case PICT_x2b10g10r10: 438 format = NV50_SURFACE_FORMAT_RGB10_A2_UNORM; 439 break; 440 case PICT_a2r10g10b10: 441 case PICT_x2r10g10b10: 442 format = NV50_SURFACE_FORMAT_BGR10_A2_UNORM; 443 break; 444 default: 445 NOUVEAU_FALLBACK("invalid picture format\n"); 446 } 447 448 PUSH_REFN (push, bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 449 BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5); 450 PUSH_DATA (push, bo->offset >> 32); 451 PUSH_DATA (push, bo->offset); 452 PUSH_DATA (push, format); 453 PUSH_DATA (push, bo->config.nv50.tile_mode); 454 PUSH_DATA (push, 0x00000000); 455 BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2); 456 PUSH_DATA (push, ppix->drawable.width); 457 PUSH_DATA (push, ppix->drawable.height); 458 BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1); 459 PUSH_DATA (push, 0x00000001); 460 461 return TRUE; 462} 463 464static Bool 465NV50EXACheckTexture(PicturePtr ppict, PicturePtr pdpict, int op) 466{ 467 if (ppict->pDrawable) { 468 if (ppict->pDrawable->width > 8192 || 469 ppict->pDrawable->height > 8192) 470 NOUVEAU_FALLBACK("texture too large\n"); 471 } else { 472 switch (ppict->pSourcePict->type) { 473 case SourcePictTypeSolidFill: 474 break; 475 default: 476 NOUVEAU_FALLBACK("pict %d\n", ppict->pSourcePict->type); 477 break; 478 } 479 } 480 481 switch (ppict->format) { 482 case PICT_a8r8g8b8: 483 case PICT_a8b8g8r8: 484 case PICT_x8r8g8b8: 485 case PICT_x8b8g8r8: 486 case PICT_r5g6b5: 487 case PICT_a8: 488 case PICT_x1r5g5b5: 489 case PICT_x1b5g5r5: 490 case PICT_a1r5g5b5: 491 case PICT_a1b5g5r5: 492 case PICT_b5g6r5: 493 case PICT_b8g8r8a8: 494 case PICT_b8g8r8x8: 495 case PICT_a2b10g10r10: 496 case PICT_x2b10g10r10: 497 case PICT_x2r10g10b10: 498 case PICT_a2r10g10b10: 499 case PICT_x4r4g4b4: 500 case PICT_x4b4g4r4: 501 case PICT_a4r4g4b4: 502 case PICT_a4b4g4r4: 503 break; 504 default: 505 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict->format); 506 } 507 508 switch (ppict->filter) { 509 case PictFilterNearest: 510 case PictFilterBilinear: 511 break; 512 default: 513 NOUVEAU_FALLBACK("picture filter %d\n", ppict->filter); 514 } 515 516 /* Opengl and Render disagree on what should be sampled outside an XRGB 517 * texture (with no repeating). Opengl has a hardcoded alpha value of 518 * 1.0, while render expects 0.0. We assume that clipping is done for 519 * untranformed sources. 520 */ 521 if (NV50EXABlendOp[op].src_alpha && !ppict->repeat && 522 ppict->transform && (PICT_FORMAT_A(ppict->format) == 0) 523 && (PICT_FORMAT_A(pdpict->format) != 0)) 524 NOUVEAU_FALLBACK("REPEAT_NONE unsupported for XRGB source\n"); 525 526 return TRUE; 527} 528 529#define _(X1,X2,X3,X4,FMT) (NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_TYPEG_UNORM | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_TYPEA_UNORM | \ 530 NV50TIC_0_0_MAP##X1 | NV50TIC_0_0_MAP##X2 | NV50TIC_0_0_MAP##X3 | NV50TIC_0_0_MAP##X4 | \ 531 NV50TIC_0_0_FMT_##FMT) 532 533static Bool 534NV50EXAPictSolid(NVPtr pNv, PicturePtr ppict, unsigned unit) 535{ 536 uint64_t offset = pNv->scratch->offset + SOLID(unit); 537 struct nouveau_pushbuf *push = pNv->pushbuf; 538 539 PUSH_DATAu(push, pNv->scratch, SOLID(unit), 1); 540 PUSH_DATA (push, ppict->pSourcePict->solidFill.color); 541 PUSH_DATAu(push, pNv->scratch, TIC_OFFSET + (unit * 32), 8); 542 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_C3, 8_8_8_8)); 543 PUSH_DATA (push, offset); 544 PUSH_DATA (push, (offset >> 32) | 0xd005d000); 545 PUSH_DATA (push, 0x00300000); 546 PUSH_DATA (push, 0x00000001); 547 PUSH_DATA (push, 0x00010001); 548 PUSH_DATA (push, 0x03000000); 549 PUSH_DATA (push, 0x00000000); 550 PUSH_DATAu(push, pNv->scratch, TSC_OFFSET + (unit * 32), 8); 551 PUSH_DATA (push, NV50TSC_1_0_WRAPS_REPEAT | 552 NV50TSC_1_0_WRAPT_REPEAT | 553 NV50TSC_1_0_WRAPR_REPEAT | 0x00024000); 554 PUSH_DATA (push, NV50TSC_1_1_MAGF_NEAREST | 555 NV50TSC_1_1_MINF_NEAREST | 556 NV50TSC_1_1_MIPF_NONE); 557 PUSH_DATA (push, 0x00000000); 558 PUSH_DATA (push, 0x00000000); 559 PUSH_DATA (push, 0x00000000); 560 PUSH_DATA (push, 0x00000000); 561 PUSH_DATA (push, 0x00000000); 562 PUSH_DATA (push, 0x00000000); 563 564 return TRUE; 565} 566 567static Bool 568NV50EXAPictGradient(NVPtr pNv, PicturePtr ppict, unsigned unit) 569{ 570 return FALSE; 571} 572 573static Bool 574NV50EXAPictTexture(NVPtr pNv, PixmapPtr ppix, PicturePtr ppict, unsigned unit) 575{ 576 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); 577 struct nouveau_pushbuf *push = pNv->pushbuf; 578 uint32_t format; 579 580 /*XXX: Scanout buffer not tiled, someone needs to figure it out */ 581 if (!nv50_style_tiled_pixmap(ppix)) 582 NOUVEAU_FALLBACK("pixmap is scanout buffer\n"); 583 584 switch (ppict->format) { 585 case PICT_a8r8g8b8: 586 format = _(B_C0, G_C1, R_C2, A_C3, 8_8_8_8); 587 break; 588 case PICT_a8b8g8r8: 589 format = _(R_C0, G_C1, B_C2, A_C3, 8_8_8_8); 590 break; 591 case PICT_x8r8g8b8: 592 format = _(B_C0, G_C1, R_C2, A_ONE, 8_8_8_8); 593 break; 594 case PICT_x8b8g8r8: 595 format = _(R_C0, G_C1, B_C2, A_ONE, 8_8_8_8); 596 break; 597 case PICT_r5g6b5: 598 format = _(B_C0, G_C1, R_C2, A_ONE, 5_6_5); 599 break; 600 case PICT_a8: 601 format = _(A_C0, B_ZERO, G_ZERO, R_ZERO, 8); 602 break; 603 case PICT_x1r5g5b5: 604 format = _(B_C0, G_C1, R_C2, A_ONE, 1_5_5_5); 605 break; 606 case PICT_x1b5g5r5: 607 format = _(R_C0, G_C1, B_C2, A_ONE, 1_5_5_5); 608 break; 609 case PICT_a1r5g5b5: 610 format = _(B_C0, G_C1, R_C2, A_C3, 1_5_5_5); 611 break; 612 case PICT_a1b5g5r5: 613 format = _(R_C0, G_C1, B_C2, A_C3, 1_5_5_5); 614 break; 615 case PICT_b5g6r5: 616 format = _(R_C0, G_C1, B_C2, A_ONE, 5_6_5); 617 break; 618 case PICT_b8g8r8x8: 619 format = _(A_ONE, R_C1, G_C2, B_C3, 8_8_8_8); 620 break; 621 case PICT_b8g8r8a8: 622 format = _(A_C0, R_C1, G_C2, B_C3, 8_8_8_8); 623 break; 624 case PICT_a2b10g10r10: 625 format = _(R_C0, G_C1, B_C2, A_C3, 2_10_10_10); 626 break; 627 case PICT_x2b10g10r10: 628 format = _(R_C0, G_C1, B_C2, A_ONE, 2_10_10_10); 629 break; 630 case PICT_x2r10g10b10: 631 format = _(B_C0, G_C1, R_C2, A_ONE, 2_10_10_10); 632 break; 633 case PICT_a2r10g10b10: 634 format = _(B_C0, G_C1, R_C2, A_C3, 2_10_10_10); 635 break; 636 case PICT_x4r4g4b4: 637 format = _(B_C0, G_C1, R_C2, A_ONE, 4_4_4_4); 638 break; 639 case PICT_x4b4g4r4: 640 format = _(R_C0, G_C1, B_C2, A_ONE, 4_4_4_4); 641 break; 642 case PICT_a4r4g4b4: 643 format = _(B_C0, G_C1, R_C2, A_C3, 4_4_4_4); 644 break; 645 case PICT_a4b4g4r4: 646 format = _(R_C0, G_C1, B_C2, A_C3, 4_4_4_4); 647 break; 648 default: 649 NOUVEAU_FALLBACK("invalid picture format, this SHOULD NOT HAPPEN. Expect trouble.\n"); 650 } 651#undef _ 652 653 PUSH_REFN (push, bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 654 PUSH_DATAu(push, pNv->scratch, TIC_OFFSET + (unit * 32), 8); 655 PUSH_DATA (push, format); 656 PUSH_DATA (push, bo->offset); 657 PUSH_DATA (push, (bo->offset >> 32) | 658 (bo->config.nv50.tile_mode << 18) | 659 0xd0005000); 660 PUSH_DATA (push, 0x00300000); 661 PUSH_DATA (push, ppix->drawable.width); 662 PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | ppix->drawable.height); 663 PUSH_DATA (push, 0x03000000); 664 PUSH_DATA (push, 0x00000000); 665 666 PUSH_DATAu(push, pNv->scratch, TSC_OFFSET + (unit * 32), 8); 667 if (ppict->repeat) { 668 switch (ppict->repeatType) { 669 case RepeatPad: 670 PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | 671 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | 672 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE | 0x00024000); 673 break; 674 case RepeatReflect: 675 PUSH_DATA (push, NV50TSC_1_0_WRAPS_MIRROR_REPEAT | 676 NV50TSC_1_0_WRAPT_MIRROR_REPEAT | 677 NV50TSC_1_0_WRAPR_MIRROR_REPEAT | 0x00024000); 678 break; 679 case RepeatNormal: 680 default: 681 PUSH_DATA (push, NV50TSC_1_0_WRAPS_REPEAT | 682 NV50TSC_1_0_WRAPT_REPEAT | 683 NV50TSC_1_0_WRAPR_REPEAT | 0x00024000); 684 break; 685 } 686 } else { 687 PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER | 688 NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER | 689 NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER | 0x00024000); 690 } 691 if (ppict->filter == PictFilterBilinear) { 692 PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR | 693 NV50TSC_1_1_MINF_LINEAR | 694 NV50TSC_1_1_MIPF_NONE); 695 } else { 696 PUSH_DATA (push, NV50TSC_1_1_MAGF_NEAREST | 697 NV50TSC_1_1_MINF_NEAREST | 698 NV50TSC_1_1_MIPF_NONE); 699 } 700 PUSH_DATA (push, 0x00000000); 701 PUSH_DATA (push, 0x00000000); 702 PUSH_DATA (push, 0x00000000); 703 PUSH_DATA (push, 0x00000000); 704 PUSH_DATA (push, 0x00000000); 705 PUSH_DATA (push, 0x00000000); 706 707 PUSH_DATAu(push, pNv->scratch, PVP_DATA + (unit * 11 * 4), 11); 708 if (ppict->transform) { 709 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][0])); 710 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][1])); 711 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][2])); 712 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][0])); 713 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][1])); 714 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][2])); 715 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][0])); 716 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][1])); 717 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][2])); 718 } else { 719 PUSH_DATAf(push, 1.0); 720 PUSH_DATAf(push, 0.0); 721 PUSH_DATAf(push, 0.0); 722 PUSH_DATAf(push, 0.0); 723 PUSH_DATAf(push, 1.0); 724 PUSH_DATAf(push, 0.0); 725 PUSH_DATAf(push, 0.0); 726 PUSH_DATAf(push, 0.0); 727 PUSH_DATAf(push, 1.0); 728 } 729 PUSH_DATAf(push, 1.0 / ppix->drawable.width); 730 PUSH_DATAf(push, 1.0 / ppix->drawable.height); 731 return TRUE; 732} 733 734static Bool 735NV50EXAPicture(NVPtr pNv, PixmapPtr ppix, PicturePtr ppict, int unit) 736{ 737 if (ppict->pDrawable) 738 return NV50EXAPictTexture(pNv, ppix, ppict, unit); 739 740 switch (ppict->pSourcePict->type) { 741 case SourcePictTypeSolidFill: 742 return NV50EXAPictSolid(pNv, ppict, unit); 743 case SourcePictTypeLinear: 744 return NV50EXAPictGradient(pNv, ppict, unit); 745 default: 746 break; 747 } 748 749 return FALSE; 750} 751 752static Bool 753NV50EXACheckBlend(int op) 754{ 755 if (op > PictOpAdd) 756 NOUVEAU_FALLBACK("unsupported blend op %d\n", op); 757 return TRUE; 758} 759 760static void 761NV50EXABlend(PixmapPtr ppix, PicturePtr ppict, int op, int component_alpha) 762{ 763 NV50EXA_LOCALS(ppix); 764 struct nv50_blend_op *b = &NV50EXABlendOp[op]; 765 unsigned sblend = b->src_blend; 766 unsigned dblend = b->dst_blend; 767 768 if (b->dst_alpha) { 769 if (!PICT_FORMAT_A(ppict->format)) { 770 if (sblend == BF(DST_ALPHA)) 771 sblend = BF(ONE); 772 else 773 if (sblend == BF(ONE_MINUS_DST_ALPHA)) 774 sblend = BF(ZERO); 775 } 776 } 777 778 if (b->src_alpha && component_alpha) { 779 if (dblend == BF(SRC_ALPHA)) 780 dblend = BF(SRC_COLOR); 781 else 782 if (dblend == BF(ONE_MINUS_SRC_ALPHA)) 783 dblend = BF(ONE_MINUS_SRC_COLOR); 784 } 785 786 if (sblend == BF(ONE) && dblend == BF(ZERO)) { 787 BEGIN_NV04(push, NV50_3D(BLEND_ENABLE(0)), 1); 788 PUSH_DATA (push, 0); 789 } else { 790 BEGIN_NV04(push, NV50_3D(BLEND_ENABLE(0)), 1); 791 PUSH_DATA (push, 1); 792 BEGIN_NV04(push, NV50_3D(BLEND_EQUATION_RGB), 5); 793 PUSH_DATA (push, NV50_3D_BLEND_EQUATION_RGB_FUNC_ADD); 794 PUSH_DATA (push, sblend); 795 PUSH_DATA (push, dblend); 796 PUSH_DATA (push, NV50_3D_BLEND_EQUATION_ALPHA_FUNC_ADD); 797 PUSH_DATA (push, sblend); 798 BEGIN_NV04(push, NV50_3D(BLEND_FUNC_DST_ALPHA), 1); 799 PUSH_DATA (push, dblend); 800 } 801} 802 803Bool 804NV50EXACheckComposite(int op, 805 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict) 806{ 807 if (!NV50EXACheckBlend(op)) 808 NOUVEAU_FALLBACK("blend not supported\n"); 809 810 if (!NV50EXACheckRenderTarget(pdpict)) 811 NOUVEAU_FALLBACK("render target invalid\n"); 812 813 if (!NV50EXACheckTexture(pspict, pdpict, op)) 814 NOUVEAU_FALLBACK("src picture invalid\n"); 815 816 if (pmpict) { 817 if (pmpict->componentAlpha && 818 PICT_FORMAT_RGB(pmpict->format) && 819 NV50EXABlendOp[op].src_alpha && 820 NV50EXABlendOp[op].src_blend != BF(ZERO)) 821 NOUVEAU_FALLBACK("component-alpha not supported\n"); 822 823 if (!NV50EXACheckTexture(pmpict, pdpict, op)) 824 NOUVEAU_FALLBACK("mask picture invalid\n"); 825 } 826 827 return TRUE; 828} 829 830Bool 831NV50EXAPrepareComposite(int op, 832 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict, 833 PixmapPtr pspix, PixmapPtr pmpix, PixmapPtr pdpix) 834{ 835 NV50EXA_LOCALS(pdpix); 836 837 if (!PUSH_SPACE(push, 256)) 838 NOUVEAU_FALLBACK("space\n"); 839 PUSH_RESET(push); 840 PUSH_REFN (push, pNv->scratch, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 841 842 BEGIN_NV04(push, SUBC_2D(NV50_GRAPH_SERIALIZE), 1); 843 PUSH_DATA (push, 0); 844 845 if (!NV50EXARenderTarget(pdpix, pdpict)) 846 NOUVEAU_FALLBACK("render target invalid\n"); 847 848 NV50EXABlend(pdpix, pdpict, op, pmpict && pmpict->componentAlpha && 849 PICT_FORMAT_RGB(pmpict->format)); 850 851 if (!NV50EXAPicture(pNv, pspix, pspict, 0)) 852 NOUVEAU_FALLBACK("src picture invalid\n"); 853 854 if (pmpict) { 855 if (!NV50EXAPicture(pNv, pmpix, pmpict, 1)) 856 NOUVEAU_FALLBACK("mask picture invalid\n"); 857 858 BEGIN_NV04(push, NV50_3D(FP_START_ID), 1); 859 if (pdpict->format == PICT_a8) { 860 PUSH_DATA (push, PFP_C_A8); 861 } else { 862 if (pmpict->componentAlpha && 863 PICT_FORMAT_RGB(pmpict->format)) { 864 if (NV50EXABlendOp[op].src_alpha) 865 PUSH_DATA (push, PFP_CCASA); 866 else 867 PUSH_DATA (push, PFP_CCA); 868 } else { 869 PUSH_DATA (push, PFP_C); 870 } 871 } 872 } else { 873 BEGIN_NV04(push, NV50_3D(FP_START_ID), 1); 874 if (pdpict->format == PICT_a8) 875 PUSH_DATA (push, PFP_S_A8); 876 else 877 PUSH_DATA (push, PFP_S); 878 } 879 880 BEGIN_NV04(push, NV50_3D(TIC_FLUSH), 1); 881 PUSH_DATA (push, 0); 882 883 BEGIN_NV04(push, NV50_3D(BIND_TIC(2)), 1); 884 PUSH_DATA (push, 1); 885 BEGIN_NV04(push, NV50_3D(BIND_TIC(2)), 1); 886 PUSH_DATA (push, 0x203); 887 888 nouveau_pushbuf_bufctx(push, pNv->bufctx); 889 if (nouveau_pushbuf_validate(push)) { 890 nouveau_pushbuf_bufctx(push, NULL); 891 NOUVEAU_FALLBACK("validate\n"); 892 } 893 894 return TRUE; 895} 896 897void 898NV50EXAComposite(PixmapPtr pdpix, int sx, int sy, int mx, int my, 899 int dx, int dy, int w, int h) 900{ 901 NV50EXA_LOCALS(pdpix); 902 903 if (!PUSH_SPACE(push, 64)) 904 return; 905 906 BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2); 907 PUSH_DATA (push, (dx + w) << 16 | dx); 908 PUSH_DATA (push, (dy + h) << 16 | dy); 909 BEGIN_NV04(push, NV50_3D(VERTEX_BEGIN_GL), 1); 910 PUSH_DATA (push, NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES); 911 PUSH_VTX2s(push, sx, sy + (h * 2), mx, my + (h * 2), dx, dy + (h * 2)); 912 PUSH_VTX2s(push, sx, sy, mx, my, dx, dy); 913 PUSH_VTX2s(push, sx + (w * 2), sy, mx + (w * 2), my, dx + (w * 2), dy); 914 BEGIN_NV04(push, NV50_3D(VERTEX_END_GL), 1); 915 PUSH_DATA (push, 0); 916} 917 918void 919NV50EXADoneComposite(PixmapPtr pdpix) 920{ 921 NV50EXA_LOCALS(pdpix); 922 nouveau_pushbuf_bufctx(push, NULL); 923} 924 925Bool 926NV50EXARectM2MF(NVPtr pNv, int w, int h, int cpp, 927 struct nouveau_bo *src, uint32_t src_off, int src_dom, 928 int src_pitch, int src_h, int src_x, int src_y, 929 struct nouveau_bo *dst, uint32_t dst_off, int dst_dom, 930 int dst_pitch, int dst_h, int dst_x, int dst_y) 931{ 932 struct nouveau_pushbuf *push = pNv->pushbuf; 933 struct nouveau_pushbuf_refn refs[] = { 934 { src, src_dom | NOUVEAU_BO_RD }, 935 { dst, dst_dom | NOUVEAU_BO_WR }, 936 }; 937 938 if (!PUSH_SPACE(push, 64)) 939 return FALSE; 940 941 if (src->config.nv50.memtype) { 942 BEGIN_NV04(push, NV50_M2MF(LINEAR_IN), 6); 943 PUSH_DATA (push, 0); 944 PUSH_DATA (push, src->config.nv50.tile_mode); 945 PUSH_DATA (push, src_pitch); 946 PUSH_DATA (push, src_h); 947 PUSH_DATA (push, 1); 948 PUSH_DATA (push, 0); 949 } else { 950 BEGIN_NV04(push, NV50_M2MF(LINEAR_IN), 1); 951 PUSH_DATA (push, 1); 952 BEGIN_NV04(push, NV03_M2MF(PITCH_IN), 1); 953 PUSH_DATA (push, src_pitch); 954 src_off += src_y * src_pitch + src_x * cpp; 955 } 956 957 if (dst->config.nv50.memtype) { 958 BEGIN_NV04(push, NV50_M2MF(LINEAR_OUT), 6); 959 PUSH_DATA (push, 0); 960 PUSH_DATA (push, dst->config.nv50.tile_mode); 961 PUSH_DATA (push, dst_pitch); 962 PUSH_DATA (push, dst_h); 963 PUSH_DATA (push, 1); 964 PUSH_DATA (push, 0); 965 } else { 966 BEGIN_NV04(push, NV50_M2MF(LINEAR_OUT), 1); 967 PUSH_DATA (push, 1); 968 BEGIN_NV04(push, NV03_M2MF(PITCH_OUT), 1); 969 PUSH_DATA (push, dst_pitch); 970 dst_off += dst_y * dst_pitch + dst_x * cpp; 971 } 972 973 while (h) { 974 int line_count = h; 975 if (line_count > 2047) 976 line_count = 2047; 977 978 if (nouveau_pushbuf_space(push, 32, 0, 0) || 979 nouveau_pushbuf_refn (push, refs, 2)) 980 return FALSE; 981 982 BEGIN_NV04(push, NV50_M2MF(OFFSET_IN_HIGH), 2); 983 PUSH_DATA (push, (src->offset + src_off) >> 32); 984 PUSH_DATA (push, (dst->offset + dst_off) >> 32); 985 BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 2); 986 PUSH_DATA (push, (src->offset + src_off)); 987 PUSH_DATA (push, (dst->offset + dst_off)); 988 989 if (src->config.nv50.memtype) { 990 BEGIN_NV04(push, NV50_M2MF(TILING_POSITION_IN), 1); 991 PUSH_DATA (push, (src_y << 16) | (src_x * cpp)); 992 } else { 993 src_off += line_count * src_pitch; 994 } 995 996 if (dst->config.nv50.memtype) { 997 BEGIN_NV04(push, NV50_M2MF(TILING_POSITION_OUT), 1); 998 PUSH_DATA (push, (dst_y << 16) | (dst_x * cpp)); 999 } else { 1000 dst_off += line_count * dst_pitch; 1001 } 1002 1003 BEGIN_NV04(push, NV03_M2MF(LINE_LENGTH_IN), 4); 1004 PUSH_DATA (push, w * cpp); 1005 PUSH_DATA (push, line_count); 1006 PUSH_DATA (push, 0x00000101); 1007 PUSH_DATA (push, 0x00000000); 1008 1009 src_y += line_count; 1010 dst_y += line_count; 1011 h -= line_count; 1012 } 1013 1014 return TRUE; 1015} 1016