nvc0_exa.c revision fda9279d
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#include "nvc0_accel.h" 27#include "nouveau_copy.h" 28 29#define NOUVEAU_BO(a, b, c) (NOUVEAU_BO_##a | NOUVEAU_BO_##b | NOUVEAU_BO_##c) 30 31#define NVC0EXA_LOCALS(p) \ 32 ScrnInfoPtr pScrn = xf86ScreenToScrn((p)->drawable.pScreen); \ 33 NVPtr pNv = NVPTR(pScrn); \ 34 struct nouveau_pushbuf *push = pNv->pushbuf; (void)push; 35 36#define BF(f) NV50_BLEND_FACTOR_##f 37 38struct nvc0_blend_op { 39 unsigned src_alpha; 40 unsigned dst_alpha; 41 unsigned src_blend; 42 unsigned dst_blend; 43}; 44 45static struct nvc0_blend_op 46NVC0EXABlendOp[] = { 47/* Clear */ { 0, 0, BF( ZERO), BF( ZERO) }, 48/* Src */ { 0, 0, BF( ONE), BF( ZERO) }, 49/* Dst */ { 0, 0, BF( ZERO), BF( ONE) }, 50/* Over */ { 1, 0, BF( ONE), BF(ONE_MINUS_SRC_ALPHA) }, 51/* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ONE) }, 52/* In */ { 0, 1, BF( DST_ALPHA), BF( ZERO) }, 53/* InReverse */ { 1, 0, BF( ZERO), BF( SRC_ALPHA) }, 54/* Out */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ZERO) }, 55/* OutReverse */ { 1, 0, BF( ZERO), BF(ONE_MINUS_SRC_ALPHA) }, 56/* Atop */ { 1, 1, BF( DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) }, 57/* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF( SRC_ALPHA) }, 58/* Xor */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) }, 59/* Add */ { 0, 0, BF( ONE), BF( ONE) }, 60}; 61 62static Bool 63NVC0EXA2DSurfaceFormat(PixmapPtr ppix, uint32_t *fmt) 64{ 65 NVC0EXA_LOCALS(ppix); 66 67 switch (ppix->drawable.bitsPerPixel) { 68 case 8 : *fmt = NV50_SURFACE_FORMAT_R8_UNORM; break; 69 case 15: *fmt = NV50_SURFACE_FORMAT_BGR5_X1_UNORM; break; 70 case 16: *fmt = NV50_SURFACE_FORMAT_B5G6R5_UNORM; break; 71 case 24: *fmt = NV50_SURFACE_FORMAT_BGRX8_UNORM; break; 72 case 30: *fmt = NV50_SURFACE_FORMAT_RGB10_A2_UNORM; break; 73 case 32: *fmt = NV50_SURFACE_FORMAT_BGRA8_UNORM; break; 74 default: 75 NOUVEAU_FALLBACK("Unknown surface format for bpp=%d\n", 76 ppix->drawable.bitsPerPixel); 77 return FALSE; 78 } 79 80 return TRUE; 81} 82 83static void NVC0EXASetClip(PixmapPtr ppix, int x, int y, int w, int h) 84{ 85 NVC0EXA_LOCALS(ppix); 86 87 BEGIN_NVC0(push, NV50_2D(CLIP_X), 4); 88 PUSH_DATA (push, x); 89 PUSH_DATA (push, y); 90 PUSH_DATA (push, w); 91 PUSH_DATA (push, h); 92} 93 94static void 95NVC0EXAAcquireSurface2D(PixmapPtr ppix, int is_src, uint32_t fmt) 96{ 97 NVC0EXA_LOCALS(ppix); 98 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); 99 struct nouveau_pixmap *nvpix = nouveau_pixmap(ppix); 100 int mthd = is_src ? NV50_2D_SRC_FORMAT : NV50_2D_DST_FORMAT; 101 uint32_t bo_flags; 102 103 bo_flags = nvpix->shared ? NOUVEAU_BO_GART : NOUVEAU_BO_VRAM; 104 bo_flags |= is_src ? NOUVEAU_BO_RD : NOUVEAU_BO_WR; 105 106 if (!nv50_style_tiled_pixmap(ppix)) { 107 BEGIN_NVC0(push, SUBC_2D(mthd), 2); 108 PUSH_DATA (push, fmt); 109 PUSH_DATA (push, 1); 110 BEGIN_NVC0(push, SUBC_2D(mthd + 0x14), 1); 111 PUSH_DATA (push, (uint32_t)exaGetPixmapPitch(ppix)); 112 } else { 113 BEGIN_NVC0(push, SUBC_2D(mthd), 5); 114 PUSH_DATA (push, fmt); 115 PUSH_DATA (push, 0); 116 PUSH_DATA (push, bo->config.nvc0.tile_mode); 117 PUSH_DATA (push, 1); 118 PUSH_DATA (push, 0); 119 } 120 121 BEGIN_NVC0(push, SUBC_2D(mthd + 0x18), 4); 122 PUSH_DATA (push, ppix->drawable.width); 123 PUSH_DATA (push, ppix->drawable.height); 124 PUSH_DATA (push, bo->offset >> 32); 125 PUSH_DATA (push, bo->offset); 126 127 if (is_src == 0) 128 NVC0EXASetClip(ppix, 0, 0, ppix->drawable.width, ppix->drawable.height); 129 130 PUSH_REFN (push, bo, bo_flags); 131} 132 133static void 134NVC0EXASetPattern(PixmapPtr pdpix, int col0, int col1, int pat0, int pat1) 135{ 136 NVC0EXA_LOCALS(pdpix); 137 138 BEGIN_NVC0(push, NV50_2D(PATTERN_COLOR(0)), 4); 139 PUSH_DATA (push, col0); 140 PUSH_DATA (push, col1); 141 PUSH_DATA (push, pat0); 142 PUSH_DATA (push, pat1); 143} 144 145static void 146NVC0EXASetROP(PixmapPtr pdpix, int alu, Pixel planemask) 147{ 148 NVC0EXA_LOCALS(pdpix); 149 int rop; 150 151 if (planemask != ~0) 152 rop = NVROP[alu].copy_planemask; 153 else 154 rop = NVROP[alu].copy; 155 156 BEGIN_NVC0(push, NV50_2D(OPERATION), 1); 157 if (alu == GXcopy && EXA_PM_IS_SOLID(&pdpix->drawable, planemask)) { 158 PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY); 159 return; 160 } else { 161 PUSH_DATA (push, NV50_2D_OPERATION_ROP); 162 } 163 164 BEGIN_NVC0(push, NV50_2D(PATTERN_COLOR_FORMAT), 2); 165 switch (pdpix->drawable.bitsPerPixel) { 166 case 8: PUSH_DATA (push, 3); break; 167 case 15: PUSH_DATA (push, 1); break; 168 case 16: PUSH_DATA (push, 0); break; 169 case 24: 170 case 32: 171 default: 172 PUSH_DATA (push, 2); 173 break; 174 } 175 PUSH_DATA (push, 1); 176 177 /* There are 16 ALUs. 178 * 0-15: copy 179 * 16-31: copy_planemask 180 */ 181 182 if (!EXA_PM_IS_SOLID(&pdpix->drawable, planemask)) { 183 alu += 16; 184 NVC0EXASetPattern(pdpix, 0, planemask, ~0, ~0); 185 } else { 186 if (pNv->currentRop > 15) 187 NVC0EXASetPattern(pdpix, ~0, ~0, ~0, ~0); 188 } 189 190 if (pNv->currentRop != alu) { 191 BEGIN_NVC0(push, NV50_2D(ROP), 1); 192 PUSH_DATA (push, rop); 193 pNv->currentRop = alu; 194 } 195} 196 197Bool 198NVC0EXAPrepareSolid(PixmapPtr pdpix, int alu, Pixel planemask, Pixel fg) 199{ 200 NVC0EXA_LOCALS(pdpix); 201 uint32_t fmt; 202 203 if (!NVC0EXA2DSurfaceFormat(pdpix, &fmt)) 204 NOUVEAU_FALLBACK("rect format\n"); 205 206 if (!PUSH_SPACE(push, 64)) 207 NOUVEAU_FALLBACK("space\n"); 208 PUSH_RESET(push); 209 210 NVC0EXAAcquireSurface2D(pdpix, 0, fmt); 211 NVC0EXASetROP(pdpix, alu, planemask); 212 213 BEGIN_NVC0(push, NV50_2D(DRAW_SHAPE), 3); 214 PUSH_DATA (push, NV50_2D_DRAW_SHAPE_RECTANGLES); 215 PUSH_DATA (push, fmt); 216 PUSH_DATA (push, fg); 217 218 nouveau_pushbuf_bufctx(push, pNv->bufctx); 219 if (nouveau_pushbuf_validate(push)) { 220 nouveau_pushbuf_bufctx(push, NULL); 221 NOUVEAU_FALLBACK("validate\n"); 222 } 223 224 return TRUE; 225} 226 227void 228NVC0EXASolid(PixmapPtr pdpix, int x1, int y1, int x2, int y2) 229{ 230 NVC0EXA_LOCALS(pdpix); 231 232 if (!PUSH_SPACE(push, 8)) 233 return; 234 235 BEGIN_NVC0(push, NV50_2D(DRAW_POINT32_X(0)), 4); 236 PUSH_DATA (push, x1); 237 PUSH_DATA (push, y1); 238 PUSH_DATA (push, x2); 239 PUSH_DATA (push, y2); 240 241 if ((x2 - x1) * (y2 - y1) >= 512) 242 PUSH_KICK(push); 243} 244 245void 246NVC0EXADoneSolid(PixmapPtr pdpix) 247{ 248 NVC0EXA_LOCALS(pdpix); 249 nouveau_pushbuf_bufctx(push, NULL); 250} 251 252Bool 253NVC0EXAPrepareCopy(PixmapPtr pspix, PixmapPtr pdpix, int dx, int dy, 254 int alu, Pixel planemask) 255{ 256 NVC0EXA_LOCALS(pdpix); 257 uint32_t src, dst; 258 259 if (!NVC0EXA2DSurfaceFormat(pspix, &src)) 260 NOUVEAU_FALLBACK("src format\n"); 261 if (!NVC0EXA2DSurfaceFormat(pdpix, &dst)) 262 NOUVEAU_FALLBACK("dst format\n"); 263 264 if (!PUSH_SPACE(push, 64)) 265 NOUVEAU_FALLBACK("space\n"); 266 PUSH_RESET(push); 267 268 NVC0EXAAcquireSurface2D(pspix, 1, src); 269 NVC0EXAAcquireSurface2D(pdpix, 0, dst); 270 NVC0EXASetROP(pdpix, alu, planemask); 271 272 nouveau_pushbuf_bufctx(push, pNv->bufctx); 273 if (nouveau_pushbuf_validate(push)) { 274 nouveau_pushbuf_bufctx(push, NULL); 275 NOUVEAU_FALLBACK("validate\n"); 276 } 277 278 return TRUE; 279} 280 281void 282NVC0EXACopy(PixmapPtr pdpix, int srcX , int srcY, 283 int dstX , int dstY, 284 int width, int height) 285{ 286 NVC0EXA_LOCALS(pdpix); 287 288 if (!PUSH_SPACE(push, 32)) 289 return; 290 291 BEGIN_NVC0(push, SUBC_2D(NV50_GRAPH_SERIALIZE), 1); 292 PUSH_DATA (push, 0); 293 BEGIN_NVC0(push, SUBC_2D(0x088c), 1); 294 PUSH_DATA (push, 0); 295 BEGIN_NVC0(push, NV50_2D(BLIT_DST_X), 12); 296 PUSH_DATA (push, dstX); 297 PUSH_DATA (push, dstY); 298 PUSH_DATA (push, width); 299 PUSH_DATA (push, height); 300 PUSH_DATA (push, 0); /* DU,V_DX,Y_FRACT,INT */ 301 PUSH_DATA (push, 1); 302 PUSH_DATA (push, 0); 303 PUSH_DATA (push, 1); 304 PUSH_DATA (push, 0); /* BLIT_SRC_X,Y_FRACT,INT */ 305 PUSH_DATA (push, srcX); 306 PUSH_DATA (push, 0); 307 PUSH_DATA (push, srcY); 308 309 if (width * height >= 512) 310 PUSH_KICK(push); 311} 312 313void 314NVC0EXADoneCopy(PixmapPtr pdpix) 315{ 316 NVC0EXA_LOCALS(pdpix); 317 nouveau_pushbuf_bufctx(push, NULL); 318} 319 320Bool 321NVC0EXAUploadSIFC(const char *src, int src_pitch, 322 PixmapPtr pdpix, int x, int y, int w, int h, int cpp) 323{ 324 NVC0EXA_LOCALS(pdpix); 325 ScreenPtr pScreen = pdpix->drawable.pScreen; 326 int line_dwords = (w * cpp + 3) / 4; 327 uint32_t sifc_fmt; 328 Bool ret = FALSE; 329 330 if (!NVC0EXA2DSurfaceFormat(pdpix, &sifc_fmt)) 331 NOUVEAU_FALLBACK("hostdata format\n"); 332 333 if (!PUSH_SPACE(push, 64)) 334 NOUVEAU_FALLBACK("pushbuf\n"); 335 PUSH_RESET(push); 336 337 NVC0EXAAcquireSurface2D(pdpix, 0, sifc_fmt); 338 NVC0EXASetClip(pdpix, x, y, w, h); 339 340 BEGIN_NVC0(push, NV50_2D(OPERATION), 1); 341 PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY); 342 BEGIN_NVC0(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); 343 PUSH_DATA (push, 0); 344 PUSH_DATA (push, sifc_fmt); 345 BEGIN_NVC0(push, NV50_2D(SIFC_WIDTH), 10); 346 PUSH_DATA (push, (line_dwords * 4) / cpp); 347 PUSH_DATA (push, h); 348 PUSH_DATA (push, 0); /* SIFC_DX,Y_DU,V_FRACT,INT */ 349 PUSH_DATA (push, 1); 350 PUSH_DATA (push, 0); 351 PUSH_DATA (push, 1); 352 PUSH_DATA (push, 0); /* SIFC_DST_X,Y_FRACT,INT */ 353 PUSH_DATA (push, x); 354 PUSH_DATA (push, 0); 355 PUSH_DATA (push, y); 356 357 nouveau_pushbuf_bufctx(push, pNv->bufctx); 358 if (nouveau_pushbuf_validate(push)) 359 goto out; 360 361 while (h--) { 362 const char *ptr = src; 363 int count = line_dwords; 364 365 while (count) { 366 int size = count > 1792 ? 1792 : count; 367 368 if (!PUSH_SPACE(push, size + 1)) 369 goto out; 370 BEGIN_NIC0(push, NV50_2D(SIFC_DATA), size); 371 PUSH_DATAp(push, ptr, size); 372 373 ptr += size * 4; 374 count -= size; 375 } 376 377 src += src_pitch; 378 } 379 380 ret = TRUE; 381out: 382 nouveau_pushbuf_bufctx(push, NULL); 383 if (pdpix == pScreen->GetScreenPixmap(pScreen)) 384 PUSH_KICK(push); 385 return ret; 386} 387 388static Bool 389NVC0EXACheckRenderTarget(PicturePtr ppict) 390{ 391 if (ppict->pDrawable->width > 8192 || 392 ppict->pDrawable->height > 8192) 393 NOUVEAU_FALLBACK("render target dimensions exceeded %dx%d\n", 394 ppict->pDrawable->width, 395 ppict->pDrawable->height); 396 397 switch (ppict->format) { 398 case PICT_a8r8g8b8: 399 case PICT_x8r8g8b8: 400 case PICT_r5g6b5: 401 case PICT_a8: 402 case PICT_x1r5g5b5: 403 case PICT_a1r5g5b5: 404 case PICT_x8b8g8r8: 405 case PICT_a2b10g10r10: 406 case PICT_x2b10g10r10: 407 case PICT_a2r10g10b10: 408 case PICT_x2r10g10b10: 409 break; 410 default: 411 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict->format); 412 } 413 414 return TRUE; 415} 416 417static Bool 418NVC0EXARenderTarget(PixmapPtr ppix, PicturePtr ppict) 419{ 420 NVC0EXA_LOCALS(ppix); 421 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); 422 unsigned format; 423 424 /*XXX: Scanout buffer not tiled, someone needs to figure it out */ 425 if (!nv50_style_tiled_pixmap(ppix)) 426 NOUVEAU_FALLBACK("pixmap is scanout buffer\n"); 427 428 switch (ppict->format) { 429 case PICT_a8r8g8b8: format = NV50_SURFACE_FORMAT_BGRA8_UNORM; break; 430 case PICT_x8r8g8b8: format = NV50_SURFACE_FORMAT_BGRX8_UNORM; break; 431 case PICT_r5g6b5 : format = NV50_SURFACE_FORMAT_B5G6R5_UNORM; break; 432 case PICT_a8 : format = NV50_SURFACE_FORMAT_A8_UNORM; break; 433 case PICT_x1r5g5b5: format = NV50_SURFACE_FORMAT_BGR5_X1_UNORM; break; 434 case PICT_a1r5g5b5: format = NV50_SURFACE_FORMAT_BGR5_A1_UNORM; 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 BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 8); 449 PUSH_DATA (push, bo->offset >> 32); 450 PUSH_DATA (push, bo->offset); 451 PUSH_DATA (push, ppix->drawable.width); 452 PUSH_DATA (push, ppix->drawable.height); 453 PUSH_DATA (push, format); 454 PUSH_DATA (push, bo->config.nvc0.tile_mode); 455 PUSH_DATA (push, 0x00000001); 456 PUSH_DATA (push, 0x00000000); 457 return TRUE; 458} 459 460static Bool 461NVC0EXACheckTexture(PicturePtr ppict, PicturePtr pdpict, int op) 462{ 463 if (ppict->pDrawable) { 464 if (ppict->pDrawable->width > 8192 || 465 ppict->pDrawable->height > 8192) 466 NOUVEAU_FALLBACK("texture too large\n"); 467 } else { 468 switch (ppict->pSourcePict->type) { 469 case SourcePictTypeSolidFill: 470 break; 471 default: 472 NOUVEAU_FALLBACK("pict %d\n", ppict->pSourcePict->type); 473 break; 474 } 475 } 476 477 switch (ppict->format) { 478 case PICT_a8r8g8b8: 479 case PICT_a8b8g8r8: 480 case PICT_x8r8g8b8: 481 case PICT_x8b8g8r8: 482 case PICT_r5g6b5: 483 case PICT_a8: 484 case PICT_x1r5g5b5: 485 case PICT_x1b5g5r5: 486 case PICT_a1r5g5b5: 487 case PICT_a1b5g5r5: 488 case PICT_b5g6r5: 489 case PICT_b8g8r8a8: 490 case PICT_b8g8r8x8: 491 case PICT_a2b10g10r10: 492 case PICT_x2b10g10r10: 493 case PICT_x2r10g10b10: 494 case PICT_a2r10g10b10: 495 case PICT_x4r4g4b4: 496 case PICT_x4b4g4r4: 497 case PICT_a4r4g4b4: 498 case PICT_a4b4g4r4: 499 break; 500 default: 501 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict->format); 502 } 503 504 switch (ppict->filter) { 505 case PictFilterNearest: 506 case PictFilterBilinear: 507 break; 508 default: 509 NOUVEAU_FALLBACK("picture filter %d\n", ppict->filter); 510 } 511 512 /* OpenGL and Render disagree on what should be sampled outside an XRGB 513 * texture (with no repeating). Opengl has a hardcoded alpha value of 514 * 1.0, while render expects 0.0. We assume that clipping is done for 515 * untranformed sources. 516 */ 517 if (NVC0EXABlendOp[op].src_alpha && !ppict->repeat && 518 ppict->transform && (PICT_FORMAT_A(ppict->format) == 0) 519 && (PICT_FORMAT_A(pdpict->format) != 0)) 520 NOUVEAU_FALLBACK("REPEAT_NONE unsupported for XRGB source\n"); 521 522 return TRUE; 523} 524 525#define _(X1, X2, X3, X4, FMT) \ 526 (NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_TYPEG_UNORM | \ 527 NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_TYPEA_UNORM | \ 528 NV50TIC_0_0_MAP##X1 | NV50TIC_0_0_MAP##X2 | \ 529 NV50TIC_0_0_MAP##X3 | NV50TIC_0_0_MAP##X4 | \ 530 NV50TIC_0_0_FMT_##FMT) 531 532static Bool 533NVC0EXAPictSolid(NVPtr pNv, PicturePtr ppict, unsigned unit) 534{ 535 uint64_t offset = pNv->scratch->offset + SOLID(unit); 536 struct nouveau_pushbuf *push = pNv->pushbuf; 537 538 PUSH_DATAu(push, pNv->scratch, SOLID(unit), 1); 539 PUSH_DATA (push, ppict->pSourcePict->solidFill.color); 540 PUSH_DATAu(push, pNv->scratch, TIC_OFFSET + (unit * 32), 8); 541 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_C3, 8_8_8_8)); 542 PUSH_DATA (push, offset); 543 PUSH_DATA (push, (offset >> 32) | 0xd005d000); 544 PUSH_DATA (push, 0x00300000); 545 PUSH_DATA (push, 0x00000001); 546 PUSH_DATA (push, 0x00010001); 547 PUSH_DATA (push, 0x03000000); 548 PUSH_DATA (push, 0x00000000); 549 PUSH_DATAu(push, pNv->scratch, TSC_OFFSET + (unit * 32), 8); 550 PUSH_DATA (push, NV50TSC_1_0_WRAPS_REPEAT | 551 NV50TSC_1_0_WRAPT_REPEAT | 552 NV50TSC_1_0_WRAPR_REPEAT | 0x00024000); 553 PUSH_DATA (push, NV50TSC_1_1_MAGF_NEAREST | 554 NV50TSC_1_1_MINF_NEAREST | 555 NV50TSC_1_1_MIPF_NONE); 556 PUSH_DATA (push, 0x00000000); 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 563 return TRUE; 564} 565 566static Bool 567NVC0EXAPictGradient(NVPtr pNv, PicturePtr ppict, unsigned unit) 568{ 569 return FALSE; 570} 571 572static Bool 573NVC0EXAPictTexture(NVPtr pNv, PixmapPtr ppix, PicturePtr ppict, unsigned unit) 574{ 575 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); 576 struct nouveau_pushbuf *push = pNv->pushbuf; 577 578 /*XXX: Scanout buffer not tiled, someone needs to figure it out */ 579 if (!nv50_style_tiled_pixmap(ppix)) 580 NOUVEAU_FALLBACK("pixmap is scanout buffer\n"); 581 582 PUSH_REFN (push, bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 583 PUSH_DATAu(push, pNv->scratch, TIC_OFFSET + (unit * 32), 8); 584 switch (ppict->format) { 585 case PICT_a8r8g8b8: 586 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_C3, 8_8_8_8)); 587 break; 588 case PICT_a8b8g8r8: 589 PUSH_DATA (push, _(R_C0, G_C1, B_C2, A_C3, 8_8_8_8)); 590 break; 591 case PICT_x8r8g8b8: 592 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_ONE, 8_8_8_8)); 593 break; 594 case PICT_x8b8g8r8: 595 PUSH_DATA (push, _(R_C0, G_C1, B_C2, A_ONE, 8_8_8_8)); 596 break; 597 case PICT_r5g6b5: 598 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_ONE, 5_6_5)); 599 break; 600 case PICT_a8: 601 PUSH_DATA (push, _(A_C0, B_ZERO, G_ZERO, R_ZERO, 8)); 602 break; 603 case PICT_x1r5g5b5: 604 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_ONE, 1_5_5_5)); 605 break; 606 case PICT_x1b5g5r5: 607 PUSH_DATA (push, _(R_C0, G_C1, B_C2, A_ONE, 1_5_5_5)); 608 break; 609 case PICT_a1r5g5b5: 610 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_C3, 1_5_5_5)); 611 break; 612 case PICT_a1b5g5r5: 613 PUSH_DATA (push, _(R_C0, G_C1, B_C2, A_C3, 1_5_5_5)); 614 break; 615 case PICT_b5g6r5: 616 PUSH_DATA (push, _(R_C0, G_C1, B_C2, A_ONE, 5_6_5)); 617 break; 618 case PICT_b8g8r8x8: 619 PUSH_DATA (push, _(A_ONE, R_C1, G_C2, B_C3, 8_8_8_8)); 620 break; 621 case PICT_b8g8r8a8: 622 PUSH_DATA (push, _(A_C0, R_C1, G_C2, B_C3, 8_8_8_8)); 623 break; 624 case PICT_a2b10g10r10: 625 PUSH_DATA (push, _(R_C0, G_C1, B_C2, A_C3, 2_10_10_10)); 626 break; 627 case PICT_x2b10g10r10: 628 PUSH_DATA (push, _(R_C0, G_C1, B_C2, A_ONE, 2_10_10_10)); 629 break; 630 case PICT_x2r10g10b10: 631 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_ONE, 2_10_10_10)); 632 break; 633 case PICT_a2r10g10b10: 634 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_C3, 2_10_10_10)); 635 break; 636 case PICT_x4r4g4b4: 637 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_ONE, 4_4_4_4)); 638 break; 639 case PICT_x4b4g4r4: 640 PUSH_DATA (push, _(R_C0, G_C1, B_C2, A_ONE, 4_4_4_4)); 641 break; 642 case PICT_a4r4g4b4: 643 PUSH_DATA (push, _(B_C0, G_C1, R_C2, A_C3, 4_4_4_4)); 644 break; 645 case PICT_a4b4g4r4: 646 PUSH_DATA (push, _(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_DATA (push, bo->offset); 654 PUSH_DATA (push, (bo->offset >> 32) | 655 (bo->config.nvc0.tile_mode << 18) | 656 0xd0005000); 657 PUSH_DATA (push, 0x00300000); 658 PUSH_DATA (push, (1 << 31) | ppix->drawable.width); 659 PUSH_DATA (push, (1 << 16) | ppix->drawable.height); 660 PUSH_DATA (push, 0x03000000); 661 PUSH_DATA (push, 0x00000000); 662 663 PUSH_DATAu(push, pNv->scratch, TSC_OFFSET + (unit * 32), 8); 664 if (ppict->repeat) { 665 switch (ppict->repeatType) { 666 case RepeatPad: 667 PUSH_DATA (push, 0x00024000 | 668 NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | 669 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | 670 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE); 671 break; 672 case RepeatReflect: 673 PUSH_DATA (push, 0x00024000 | 674 NV50TSC_1_0_WRAPS_MIRROR_REPEAT | 675 NV50TSC_1_0_WRAPT_MIRROR_REPEAT | 676 NV50TSC_1_0_WRAPR_MIRROR_REPEAT); 677 break; 678 case RepeatNormal: 679 default: 680 PUSH_DATA (push, 0x00024000 | 681 NV50TSC_1_0_WRAPS_REPEAT | 682 NV50TSC_1_0_WRAPT_REPEAT | 683 NV50TSC_1_0_WRAPR_REPEAT); 684 break; 685 } 686 } else { 687 PUSH_DATA (push, 0x00024000 | 688 NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER | 689 NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER | 690 NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER); 691 } 692 if (ppict->filter == PictFilterBilinear) { 693 PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR | 694 NV50TSC_1_1_MINF_LINEAR | 695 NV50TSC_1_1_MIPF_NONE); 696 } else { 697 PUSH_DATA (push, NV50TSC_1_1_MAGF_NEAREST | 698 NV50TSC_1_1_MINF_NEAREST | 699 NV50TSC_1_1_MIPF_NONE); 700 } 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 PUSH_DATA (push, 0x00000000); 707 708 PUSH_DATAu(push, pNv->scratch, PVP_DATA + (unit * 11 * 4), 11); 709 if (ppict->transform) { 710 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][0])); 711 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][1])); 712 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][2])); 713 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][0])); 714 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][1])); 715 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][2])); 716 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][0])); 717 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][1])); 718 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][2])); 719 } else { 720 PUSH_DATAf(push, 1.0); 721 PUSH_DATAf(push, 0.0); 722 PUSH_DATAf(push, 0.0); 723 PUSH_DATAf(push, 0.0); 724 PUSH_DATAf(push, 1.0); 725 PUSH_DATAf(push, 0.0); 726 PUSH_DATAf(push, 0.0); 727 PUSH_DATAf(push, 0.0); 728 PUSH_DATAf(push, 1.0); 729 } 730 PUSH_DATAf(push, 1.0 / ppix->drawable.width); 731 PUSH_DATAf(push, 1.0 / ppix->drawable.height); 732 return TRUE; 733} 734 735static Bool 736NVC0EXAPicture(NVPtr pNv, PixmapPtr ppix, PicturePtr ppict, int unit) 737{ 738 if (ppict->pDrawable) 739 return NVC0EXAPictTexture(pNv, ppix, ppict, unit); 740 741 switch (ppict->pSourcePict->type) { 742 case SourcePictTypeSolidFill: 743 return NVC0EXAPictSolid(pNv, ppict, unit); 744 case SourcePictTypeLinear: 745 return NVC0EXAPictGradient(pNv, ppict, unit); 746 default: 747 break; 748 } 749 750 return FALSE; 751} 752static Bool 753NVC0EXACheckBlend(int op) 754{ 755 if (op > PictOpAdd) 756 NOUVEAU_FALLBACK("unsupported blend op %d\n", op); 757 return TRUE; 758} 759 760static void 761NVC0EXABlend(PixmapPtr ppix, PicturePtr ppict, int op, int component_alpha) 762{ 763 NVC0EXA_LOCALS(ppix); 764 struct nvc0_blend_op *b = &NVC0EXABlendOp[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_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1); 788 PUSH_DATA (push, 0); 789 } else { 790 BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1); 791 PUSH_DATA (push, 1); 792 BEGIN_NVC0(push, NVC0_3D(BLEND_EQUATION_RGB), 5); 793 PUSH_DATA (push, NVC0_3D_BLEND_EQUATION_RGB_FUNC_ADD); 794 PUSH_DATA (push, sblend); 795 PUSH_DATA (push, dblend); 796 PUSH_DATA (push, NVC0_3D_BLEND_EQUATION_ALPHA_FUNC_ADD); 797 PUSH_DATA (push, sblend); 798 BEGIN_NVC0(push, NVC0_3D(BLEND_FUNC_DST_ALPHA), 1); 799 PUSH_DATA (push, dblend); 800 } 801} 802 803Bool 804NVC0EXACheckComposite(int op, 805 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict) 806{ 807 if (!NVC0EXACheckBlend(op)) 808 NOUVEAU_FALLBACK("blend not supported\n"); 809 810 if (!NVC0EXACheckRenderTarget(pdpict)) 811 NOUVEAU_FALLBACK("render target invalid\n"); 812 813 if (!NVC0EXACheckTexture(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 NVC0EXABlendOp[op].src_alpha && 820 NVC0EXABlendOp[op].src_blend != BF(ZERO)) 821 NOUVEAU_FALLBACK("component-alpha not supported\n"); 822 823 if (!NVC0EXACheckTexture(pmpict, pdpict, op)) 824 NOUVEAU_FALLBACK("mask picture invalid\n"); 825 } 826 827 return TRUE; 828} 829 830Bool 831NVC0EXAPrepareComposite(int op, 832 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict, 833 PixmapPtr pspix, PixmapPtr pmpix, PixmapPtr pdpix) 834{ 835 struct nouveau_bo *dst = nouveau_pixmap_bo(pdpix); 836 NVC0EXA_LOCALS(pdpix); 837 838 if (!PUSH_SPACE(push, 256)) 839 NOUVEAU_FALLBACK("space\n"); 840 841 BEGIN_NVC0(push, SUBC_2D(NV50_GRAPH_SERIALIZE), 1); 842 PUSH_DATA (push, 0); 843 844 if (!NVC0EXARenderTarget(pdpix, pdpict)) 845 NOUVEAU_FALLBACK("render target invalid\n"); 846 847 NVC0EXABlend(pdpix, pdpict, op, pmpict && pmpict->componentAlpha && 848 PICT_FORMAT_RGB(pmpict->format)); 849 850 if (!NVC0EXAPicture(pNv, pspix, pspict, 0)) 851 NOUVEAU_FALLBACK("src picture invalid\n"); 852 853 if (pmpict) { 854 if (!NVC0EXAPicture(pNv, pmpix, pmpict, 1)) 855 NOUVEAU_FALLBACK("mask picture invalid\n"); 856 857 BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1); 858 if (pdpict->format == PICT_a8) { 859 PUSH_DATA (push, PFP_C_A8); 860 } else { 861 if (pmpict->componentAlpha && 862 PICT_FORMAT_RGB(pmpict->format)) { 863 if (NVC0EXABlendOp[op].src_alpha) 864 PUSH_DATA (push, PFP_CCASA); 865 else 866 PUSH_DATA (push, PFP_CCA); 867 } else { 868 PUSH_DATA (push, PFP_C); 869 } 870 } 871 } else { 872 BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1); 873 if (pdpict->format == PICT_a8) 874 PUSH_DATA (push, PFP_S_A8); 875 else 876 PUSH_DATA (push, PFP_S); 877 } 878 879 BEGIN_NVC0(push, NVC0_3D(TSC_FLUSH), 1); 880 PUSH_DATA (push, 0); 881 BEGIN_NVC0(push, NVC0_3D(TIC_FLUSH), 1); 882 PUSH_DATA (push, 0); 883 BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1); 884 PUSH_DATA (push, 0); 885 886 PUSH_RESET(push); 887 PUSH_REFN (push, pNv->scratch, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 888 if (pspict->pDrawable) 889 PUSH_REFN (push, nouveau_pixmap_bo(pspix), 890 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 891 PUSH_REFN (push, dst, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 892 if (pmpict && pmpict->pDrawable) 893 PUSH_REFN (push, nouveau_pixmap_bo(pmpix), 894 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 895 896 nouveau_pushbuf_bufctx(push, pNv->bufctx); 897 if (nouveau_pushbuf_validate(push)) { 898 nouveau_pushbuf_bufctx(push, NULL); 899 NOUVEAU_FALLBACK("validate\n"); 900 } 901 902 return TRUE; 903} 904 905void 906NVC0EXAComposite(PixmapPtr pdpix, 907 int sx, int sy, int mx, int my, 908 int dx, int dy, int w, int h) 909{ 910 NVC0EXA_LOCALS(pdpix); 911 912 if (!PUSH_SPACE(push, 64)) 913 return; 914 915 BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2); 916 PUSH_DATA (push, ((dx + w) << 16) | dx); 917 PUSH_DATA (push, ((dy + h) << 16) | dy); 918 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 919 PUSH_DATA (push, NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES); 920 PUSH_VTX2s(push, sx, sy + (h * 2), mx, my + (h * 2), dx, dy + (h * 2)); 921 PUSH_VTX2s(push, sx, sy, mx, my, dx, dy); 922 PUSH_VTX2s(push, sx + (w * 2), sy, mx + (w * 2), my, dx + (w * 2), dy); 923 BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 1); 924 PUSH_DATA (push, 0); 925} 926 927void 928NVC0EXADoneComposite(PixmapPtr pdpix) 929{ 930 NVC0EXA_LOCALS(pdpix); 931 nouveau_pushbuf_bufctx(push, NULL); 932} 933 934Bool 935NVC0EXARectM2MF(NVPtr pNv, int w, int h, int cpp, 936 struct nouveau_bo *src, uint32_t src_off, int src_dom, 937 int src_pitch, int src_h, int src_x, int src_y, 938 struct nouveau_bo *dst, uint32_t dst_off, int dst_dom, 939 int dst_pitch, int dst_h, int dst_x, int dst_y) 940{ 941 struct nouveau_pushbuf_refn refs[] = { 942 { src, src_dom | NOUVEAU_BO_RD }, 943 { dst, dst_dom | NOUVEAU_BO_WR }, 944 }; 945 struct nouveau_pushbuf *push = pNv->pushbuf; 946 unsigned exec = 0; 947 948 if (!PUSH_SPACE(push, 64)) 949 return FALSE; 950 951 if (src->config.nvc0.memtype) { 952 BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_IN), 5); 953 PUSH_DATA (push, src->config.nvc0.tile_mode); 954 PUSH_DATA (push, src_pitch); 955 PUSH_DATA (push, src_h); 956 PUSH_DATA (push, 1); 957 PUSH_DATA (push, 0); 958 } else { 959 BEGIN_NVC0(push, NVC0_M2MF(PITCH_IN), 1); 960 PUSH_DATA (push, src_pitch); 961 962 src_off += src_y * src_pitch + src_x * cpp; 963 exec |= NVC0_M2MF_EXEC_LINEAR_IN; 964 } 965 966 if (dst->config.nvc0.memtype) { 967 BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_OUT), 5); 968 PUSH_DATA (push, dst->config.nvc0.tile_mode); 969 PUSH_DATA (push, dst_pitch); 970 PUSH_DATA (push, dst_h); 971 PUSH_DATA (push, 1); 972 PUSH_DATA (push, 0); 973 } else { 974 BEGIN_NVC0(push, NVC0_M2MF(PITCH_OUT), 1); 975 PUSH_DATA (push, dst_pitch); 976 977 dst_off += dst_y * dst_pitch + dst_x * cpp; 978 exec |= NVC0_M2MF_EXEC_LINEAR_OUT; 979 } 980 981 while (h) { 982 int line_count = h; 983 if (line_count > 2047) 984 line_count = 2047; 985 986 if (nouveau_pushbuf_space(push, 32, 0, 0) || 987 nouveau_pushbuf_refn (push, refs, 2)) 988 return FALSE; 989 990 BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2); 991 PUSH_DATA (push, (dst->offset + dst_off) >> 32); 992 PUSH_DATA (push, (dst->offset + dst_off)); 993 BEGIN_NVC0(push, NVC0_M2MF(OFFSET_IN_HIGH), 2); 994 PUSH_DATA (push, (src->offset + src_off) >> 32); 995 PUSH_DATA (push, (src->offset + src_off)); 996 997 if (src->config.nvc0.memtype) { 998 BEGIN_NVC0(push, NVC0_M2MF(TILING_POSITION_IN_X), 2); 999 PUSH_DATA (push, src_x * cpp); 1000 PUSH_DATA (push, src_y); 1001 } else { 1002 src_off += line_count * src_pitch; 1003 } 1004 1005 if (dst->config.nvc0.memtype) { 1006 BEGIN_NVC0(push, NVC0_M2MF(TILING_POSITION_OUT_X), 2); 1007 PUSH_DATA (push, dst_x * cpp); 1008 PUSH_DATA (push, dst_y); 1009 } else { 1010 dst_off += line_count * dst_pitch; 1011 } 1012 1013 BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2); 1014 PUSH_DATA (push, w * cpp); 1015 PUSH_DATA (push, line_count); 1016 BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1); 1017 PUSH_DATA (push, NVC0_M2MF_EXEC_QUERY_SHORT | exec); 1018 1019 src_y += line_count; 1020 dst_y += line_count; 1021 h -= line_count; 1022 } 1023 1024 return TRUE; 1025} 1026 1027Bool 1028NVE0EXARectCopy(NVPtr pNv, int w, int h, int cpp, 1029 struct nouveau_bo *src, uint32_t src_off, int src_dom, 1030 int src_pitch, int src_h, int src_x, int src_y, 1031 struct nouveau_bo *dst, uint32_t dst_off, int dst_dom, 1032 int dst_pitch, int dst_h, int dst_x, int dst_y) 1033{ 1034 return nouveau_copya0b5_rect(pNv->pushbuf, pNv->NvCOPY, w, h, cpp, 1035 src, src_off, src_dom, src_pitch, 1036 src_h, src_x, src_y, dst, dst_off, 1037 dst_dom, dst_pitch, dst_h, dst_x, dst_y); 1038} 1039