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, NV50_2D(BLIT_CONTROL), 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 struct nouveau_pushbuf *push = pNv->pushbuf; 536 537 PUSH_DATAu(push, pNv->scratch, SOLID(unit), 1); 538 PUSH_DATA (push, ppict->pSourcePict->solidFill.color); 539 PUSH_DATAu(push, pNv->scratch, TIC_OFFSET + (unit * 32), 8); 540 PUSH_TIC (push, pNv->scratch, SOLID(unit), 1, 1, 4, 541 _(B_C0, G_C1, R_C2, A_C3, 8_8_8_8)); 542 PUSH_DATAu(push, pNv->scratch, TSC_OFFSET + (unit * 32), 8); 543 PUSH_DATA (push, NV50TSC_1_0_WRAPS_REPEAT | 544 NV50TSC_1_0_WRAPT_REPEAT | 545 NV50TSC_1_0_WRAPR_REPEAT | 0x00024000); 546 PUSH_DATA (push, NV50TSC_1_1_MAGF_NEAREST | 547 NV50TSC_1_1_MINF_NEAREST | 548 NV50TSC_1_1_MIPF_NONE); 549 PUSH_DATA (push, 0x00000000); 550 PUSH_DATA (push, 0x00000000); 551 PUSH_DATA (push, 0x00000000); 552 PUSH_DATA (push, 0x00000000); 553 PUSH_DATA (push, 0x00000000); 554 PUSH_DATA (push, 0x00000000); 555 556 return TRUE; 557} 558 559static Bool 560NVC0EXAPictGradient(NVPtr pNv, PicturePtr ppict, unsigned unit) 561{ 562 return FALSE; 563} 564 565static Bool 566NVC0EXAPictTexture(NVPtr pNv, PixmapPtr ppix, PicturePtr ppict, unsigned unit) 567{ 568 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); 569 struct nouveau_pushbuf *push = pNv->pushbuf; 570 uint32_t format; 571 572 /*XXX: Scanout buffer not tiled, someone needs to figure it out */ 573 if (!nv50_style_tiled_pixmap(ppix)) 574 NOUVEAU_FALLBACK("pixmap is scanout buffer\n"); 575 576 switch (ppict->format) { 577 case PICT_a8r8g8b8: 578 format = _(B_C0, G_C1, R_C2, A_C3, 8_8_8_8); 579 break; 580 case PICT_a8b8g8r8: 581 format = _(R_C0, G_C1, B_C2, A_C3, 8_8_8_8); 582 break; 583 case PICT_x8r8g8b8: 584 format = _(B_C0, G_C1, R_C2, A_ONE, 8_8_8_8); 585 break; 586 case PICT_x8b8g8r8: 587 format = _(R_C0, G_C1, B_C2, A_ONE, 8_8_8_8); 588 break; 589 case PICT_r5g6b5: 590 format = _(B_C0, G_C1, R_C2, A_ONE, 5_6_5); 591 break; 592 case PICT_a8: 593 format = _(A_C0, B_ZERO, G_ZERO, R_ZERO, 8); 594 break; 595 case PICT_x1r5g5b5: 596 format = _(B_C0, G_C1, R_C2, A_ONE, 1_5_5_5); 597 break; 598 case PICT_x1b5g5r5: 599 format = _(R_C0, G_C1, B_C2, A_ONE, 1_5_5_5); 600 break; 601 case PICT_a1r5g5b5: 602 format = _(B_C0, G_C1, R_C2, A_C3, 1_5_5_5); 603 break; 604 case PICT_a1b5g5r5: 605 format = _(R_C0, G_C1, B_C2, A_C3, 1_5_5_5); 606 break; 607 case PICT_b5g6r5: 608 format = _(R_C0, G_C1, B_C2, A_ONE, 5_6_5); 609 break; 610 case PICT_b8g8r8x8: 611 format = _(A_ONE, R_C1, G_C2, B_C3, 8_8_8_8); 612 break; 613 case PICT_b8g8r8a8: 614 format = _(A_C0, R_C1, G_C2, B_C3, 8_8_8_8); 615 break; 616 case PICT_a2b10g10r10: 617 format = _(R_C0, G_C1, B_C2, A_C3, 2_10_10_10); 618 break; 619 case PICT_x2b10g10r10: 620 format = _(R_C0, G_C1, B_C2, A_ONE, 2_10_10_10); 621 break; 622 case PICT_x2r10g10b10: 623 format = _(B_C0, G_C1, R_C2, A_ONE, 2_10_10_10); 624 break; 625 case PICT_a2r10g10b10: 626 format = _(B_C0, G_C1, R_C2, A_C3, 2_10_10_10); 627 break; 628 case PICT_x4r4g4b4: 629 format = _(B_C0, G_C1, R_C2, A_ONE, 4_4_4_4); 630 break; 631 case PICT_x4b4g4r4: 632 format = _(R_C0, G_C1, B_C2, A_ONE, 4_4_4_4); 633 break; 634 case PICT_a4r4g4b4: 635 format = _(B_C0, G_C1, R_C2, A_C3, 4_4_4_4); 636 break; 637 case PICT_a4b4g4r4: 638 format = _(R_C0, G_C1, B_C2, A_C3, 4_4_4_4); 639 break; 640 default: 641 NOUVEAU_FALLBACK("invalid picture format, this SHOULD NOT HAPPEN. Expect trouble.\n"); 642 } 643#undef _ 644 645 PUSH_REFN (push, bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 646 PUSH_DATAu(push, pNv->scratch, TIC_OFFSET + (unit * 32), 8); 647 PUSH_TIC (push, bo, 0, ppix->drawable.width, ppix->drawable.height, 0, 648 format); 649 650 PUSH_DATAu(push, pNv->scratch, TSC_OFFSET + (unit * 32), 8); 651 if (ppict->repeat) { 652 switch (ppict->repeatType) { 653 case RepeatPad: 654 PUSH_DATA (push, 0x00024000 | 655 NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | 656 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | 657 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE); 658 break; 659 case RepeatReflect: 660 PUSH_DATA (push, 0x00024000 | 661 NV50TSC_1_0_WRAPS_MIRROR_REPEAT | 662 NV50TSC_1_0_WRAPT_MIRROR_REPEAT | 663 NV50TSC_1_0_WRAPR_MIRROR_REPEAT); 664 break; 665 case RepeatNormal: 666 default: 667 PUSH_DATA (push, 0x00024000 | 668 NV50TSC_1_0_WRAPS_REPEAT | 669 NV50TSC_1_0_WRAPT_REPEAT | 670 NV50TSC_1_0_WRAPR_REPEAT); 671 break; 672 } 673 } else { 674 PUSH_DATA (push, 0x00024000 | 675 NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER | 676 NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER | 677 NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER); 678 } 679 if (ppict->filter == PictFilterBilinear) { 680 PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR | 681 NV50TSC_1_1_MINF_LINEAR | 682 NV50TSC_1_1_MIPF_NONE); 683 } else { 684 PUSH_DATA (push, NV50TSC_1_1_MAGF_NEAREST | 685 NV50TSC_1_1_MINF_NEAREST | 686 NV50TSC_1_1_MIPF_NONE); 687 } 688 PUSH_DATA (push, 0x00000000); 689 PUSH_DATA (push, 0x00000000); 690 PUSH_DATA (push, 0x00000000); 691 PUSH_DATA (push, 0x00000000); 692 PUSH_DATA (push, 0x00000000); 693 PUSH_DATA (push, 0x00000000); 694 695 PUSH_DATAu(push, pNv->scratch, PVP_DATA + (unit * 11 * 4), 11); 696 if (ppict->transform) { 697 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][0])); 698 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][1])); 699 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[0][2])); 700 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][0])); 701 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][1])); 702 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[1][2])); 703 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][0])); 704 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][1])); 705 PUSH_DATAf(push, xFixedToFloat(ppict->transform->matrix[2][2])); 706 } else { 707 PUSH_DATAf(push, 1.0); 708 PUSH_DATAf(push, 0.0); 709 PUSH_DATAf(push, 0.0); 710 PUSH_DATAf(push, 0.0); 711 PUSH_DATAf(push, 1.0); 712 PUSH_DATAf(push, 0.0); 713 PUSH_DATAf(push, 0.0); 714 PUSH_DATAf(push, 0.0); 715 PUSH_DATAf(push, 1.0); 716 } 717 PUSH_DATAf(push, 1.0 / ppix->drawable.width); 718 PUSH_DATAf(push, 1.0 / ppix->drawable.height); 719 return TRUE; 720} 721 722static Bool 723NVC0EXAPicture(NVPtr pNv, PixmapPtr ppix, PicturePtr ppict, int unit) 724{ 725 if (ppict->pDrawable) 726 return NVC0EXAPictTexture(pNv, ppix, ppict, unit); 727 728 switch (ppict->pSourcePict->type) { 729 case SourcePictTypeSolidFill: 730 return NVC0EXAPictSolid(pNv, ppict, unit); 731 case SourcePictTypeLinear: 732 return NVC0EXAPictGradient(pNv, ppict, unit); 733 default: 734 break; 735 } 736 737 return FALSE; 738} 739static Bool 740NVC0EXACheckBlend(int op) 741{ 742 if (op > PictOpAdd) 743 NOUVEAU_FALLBACK("unsupported blend op %d\n", op); 744 return TRUE; 745} 746 747static void 748NVC0EXABlend(PixmapPtr ppix, PicturePtr ppict, int op, int component_alpha) 749{ 750 NVC0EXA_LOCALS(ppix); 751 struct nvc0_blend_op *b = &NVC0EXABlendOp[op]; 752 unsigned sblend = b->src_blend; 753 unsigned dblend = b->dst_blend; 754 755 if (b->dst_alpha) { 756 if (!PICT_FORMAT_A(ppict->format)) { 757 if (sblend == BF(DST_ALPHA)) 758 sblend = BF(ONE); 759 else 760 if (sblend == BF(ONE_MINUS_DST_ALPHA)) 761 sblend = BF(ZERO); 762 } 763 } 764 765 if (b->src_alpha && component_alpha) { 766 if (dblend == BF(SRC_ALPHA)) 767 dblend = BF(SRC_COLOR); 768 else 769 if (dblend == BF(ONE_MINUS_SRC_ALPHA)) 770 dblend = BF(ONE_MINUS_SRC_COLOR); 771 } 772 773 if (sblend == BF(ONE) && dblend == BF(ZERO)) { 774 BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1); 775 PUSH_DATA (push, 0); 776 } else { 777 BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1); 778 PUSH_DATA (push, 1); 779 BEGIN_NVC0(push, NVC0_3D(BLEND_EQUATION_RGB), 5); 780 PUSH_DATA (push, NVC0_3D_BLEND_EQUATION_RGB_FUNC_ADD); 781 PUSH_DATA (push, sblend); 782 PUSH_DATA (push, dblend); 783 PUSH_DATA (push, NVC0_3D_BLEND_EQUATION_ALPHA_FUNC_ADD); 784 PUSH_DATA (push, sblend); 785 BEGIN_NVC0(push, NVC0_3D(BLEND_FUNC_DST_ALPHA), 1); 786 PUSH_DATA (push, dblend); 787 } 788} 789 790Bool 791NVC0EXACheckComposite(int op, 792 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict) 793{ 794 if (!NVC0EXACheckBlend(op)) 795 NOUVEAU_FALLBACK("blend not supported\n"); 796 797 if (!NVC0EXACheckRenderTarget(pdpict)) 798 NOUVEAU_FALLBACK("render target invalid\n"); 799 800 if (!NVC0EXACheckTexture(pspict, pdpict, op)) 801 NOUVEAU_FALLBACK("src picture invalid\n"); 802 803 if (pmpict) { 804 if (pmpict->componentAlpha && 805 PICT_FORMAT_RGB(pmpict->format) && 806 NVC0EXABlendOp[op].src_alpha && 807 NVC0EXABlendOp[op].src_blend != BF(ZERO)) 808 NOUVEAU_FALLBACK("component-alpha not supported\n"); 809 810 if (!NVC0EXACheckTexture(pmpict, pdpict, op)) 811 NOUVEAU_FALLBACK("mask picture invalid\n"); 812 } 813 814 return TRUE; 815} 816 817Bool 818NVC0EXAPrepareComposite(int op, 819 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict, 820 PixmapPtr pspix, PixmapPtr pmpix, PixmapPtr pdpix) 821{ 822 struct nouveau_bo *dst = nouveau_pixmap_bo(pdpix); 823 NVC0EXA_LOCALS(pdpix); 824 825 if (!PUSH_SPACE(push, 256)) 826 NOUVEAU_FALLBACK("space\n"); 827 828 BEGIN_NVC0(push, SUBC_2D(NV50_GRAPH_SERIALIZE), 1); 829 PUSH_DATA (push, 0); 830 831 if (!NVC0EXARenderTarget(pdpix, pdpict)) 832 NOUVEAU_FALLBACK("render target invalid\n"); 833 834 NVC0EXABlend(pdpix, pdpict, op, pmpict && pmpict->componentAlpha && 835 PICT_FORMAT_RGB(pmpict->format)); 836 837 if (!NVC0EXAPicture(pNv, pspix, pspict, 0)) 838 NOUVEAU_FALLBACK("src picture invalid\n"); 839 840 if (pmpict) { 841 if (!NVC0EXAPicture(pNv, pmpix, pmpict, 1)) 842 NOUVEAU_FALLBACK("mask picture invalid\n"); 843 844 BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1); 845 if (pdpict->format == PICT_a8) { 846 PUSH_DATA (push, PFP_C_A8); 847 } else { 848 if (pmpict->componentAlpha && 849 PICT_FORMAT_RGB(pmpict->format)) { 850 if (NVC0EXABlendOp[op].src_alpha) 851 PUSH_DATA (push, PFP_CCASA); 852 else 853 PUSH_DATA (push, PFP_CCA); 854 } else { 855 PUSH_DATA (push, PFP_C); 856 } 857 } 858 } else { 859 BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1); 860 if (pdpict->format == PICT_a8) 861 PUSH_DATA (push, PFP_S_A8); 862 else 863 PUSH_DATA (push, PFP_S); 864 } 865 866 BEGIN_NVC0(push, NVC0_3D(TSC_FLUSH), 1); 867 PUSH_DATA (push, 0); 868 BEGIN_NVC0(push, NVC0_3D(TIC_FLUSH), 1); 869 PUSH_DATA (push, 0); 870 BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1); 871 PUSH_DATA (push, 0); 872 873 PUSH_RESET(push); 874 PUSH_REFN (push, pNv->scratch, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 875 if (pspict->pDrawable) 876 PUSH_REFN (push, nouveau_pixmap_bo(pspix), 877 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 878 PUSH_REFN (push, dst, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 879 if (pmpict && pmpict->pDrawable) 880 PUSH_REFN (push, nouveau_pixmap_bo(pmpix), 881 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 882 883 nouveau_pushbuf_bufctx(push, pNv->bufctx); 884 if (nouveau_pushbuf_validate(push)) { 885 nouveau_pushbuf_bufctx(push, NULL); 886 NOUVEAU_FALLBACK("validate\n"); 887 } 888 889 return TRUE; 890} 891 892void 893NVC0EXAComposite(PixmapPtr pdpix, 894 int sx, int sy, int mx, int my, 895 int dx, int dy, int w, int h) 896{ 897 NVC0EXA_LOCALS(pdpix); 898 899 if (!PUSH_SPACE(push, 64)) 900 return; 901 902 if (pNv->dev->chipset >= 0x110) { 903 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 904 PUSH_DATA (push, 256); 905 PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA) >> 32); 906 PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA)); 907 BEGIN_1IC0(push, NVC0_3D(CB_POS), 24 + 1); 908 PUSH_DATA (push, 0x80); 909 910 PUSH_DATAf(push, dx); 911 PUSH_DATAf(push, dy + (h * 2)); 912 PUSH_DATAf(push, 0); 913 PUSH_DATAf(push, 1); 914 PUSH_DATAf(push, sx); 915 PUSH_DATAf(push, sy + (h * 2)); 916 PUSH_DATAf(push, mx); 917 PUSH_DATAf(push, my + (h * 2)); 918 919 PUSH_DATAf(push, dx); 920 PUSH_DATAf(push, dy); 921 PUSH_DATAf(push, 0); 922 PUSH_DATAf(push, 1); 923 PUSH_DATAf(push, sx); 924 PUSH_DATAf(push, sy); 925 PUSH_DATAf(push, mx); 926 PUSH_DATAf(push, my); 927 928 PUSH_DATAf(push, dx + (w * 2)); 929 PUSH_DATAf(push, dy); 930 PUSH_DATAf(push, 0); 931 PUSH_DATAf(push, 1); 932 PUSH_DATAf(push, sx + (w * 2)); 933 PUSH_DATAf(push, sy); 934 PUSH_DATAf(push, mx + (w * 2)); 935 PUSH_DATAf(push, my); 936 } 937 938 BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2); 939 PUSH_DATA (push, ((dx + w) << 16) | dx); 940 PUSH_DATA (push, ((dy + h) << 16) | dy); 941 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 942 PUSH_DATA (push, NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES); 943 if (pNv->dev->chipset < 0x110) { 944 PUSH_VTX2s(push, sx, sy + (h * 2), mx, my + (h * 2), dx, dy + (h * 2)); 945 PUSH_VTX2s(push, sx, sy, mx, my, dx, dy); 946 PUSH_VTX2s(push, sx + (w * 2), sy, mx + (w * 2), my, dx + (w * 2), dy); 947 } else { 948 BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2); 949 PUSH_DATA (push, 0); 950 PUSH_DATA (push, 3); 951 } 952 BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 1); 953 PUSH_DATA (push, 0); 954} 955 956void 957NVC0EXADoneComposite(PixmapPtr pdpix) 958{ 959 NVC0EXA_LOCALS(pdpix); 960 nouveau_pushbuf_bufctx(push, NULL); 961} 962 963Bool 964NVC0EXARectM2MF(NVPtr pNv, int w, int h, int cpp, 965 struct nouveau_bo *src, uint32_t src_off, int src_dom, 966 int src_pitch, int src_h, int src_x, int src_y, 967 struct nouveau_bo *dst, uint32_t dst_off, int dst_dom, 968 int dst_pitch, int dst_h, int dst_x, int dst_y) 969{ 970 struct nouveau_pushbuf_refn refs[] = { 971 { src, src_dom | NOUVEAU_BO_RD }, 972 { dst, dst_dom | NOUVEAU_BO_WR }, 973 }; 974 struct nouveau_pushbuf *push = pNv->pushbuf; 975 unsigned exec = 0; 976 977 if (!PUSH_SPACE(push, 64)) 978 return FALSE; 979 980 if (src->config.nvc0.memtype) { 981 BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_IN), 5); 982 PUSH_DATA (push, src->config.nvc0.tile_mode); 983 PUSH_DATA (push, src_pitch); 984 PUSH_DATA (push, src_h); 985 PUSH_DATA (push, 1); 986 PUSH_DATA (push, 0); 987 } else { 988 BEGIN_NVC0(push, NVC0_M2MF(PITCH_IN), 1); 989 PUSH_DATA (push, src_pitch); 990 991 src_off += src_y * src_pitch + src_x * cpp; 992 exec |= NVC0_M2MF_EXEC_LINEAR_IN; 993 } 994 995 if (dst->config.nvc0.memtype) { 996 BEGIN_NVC0(push, NVC0_M2MF(TILING_MODE_OUT), 5); 997 PUSH_DATA (push, dst->config.nvc0.tile_mode); 998 PUSH_DATA (push, dst_pitch); 999 PUSH_DATA (push, dst_h); 1000 PUSH_DATA (push, 1); 1001 PUSH_DATA (push, 0); 1002 } else { 1003 BEGIN_NVC0(push, NVC0_M2MF(PITCH_OUT), 1); 1004 PUSH_DATA (push, dst_pitch); 1005 1006 dst_off += dst_y * dst_pitch + dst_x * cpp; 1007 exec |= NVC0_M2MF_EXEC_LINEAR_OUT; 1008 } 1009 1010 while (h) { 1011 int line_count = h; 1012 if (line_count > 2047) 1013 line_count = 2047; 1014 1015 if (nouveau_pushbuf_space(push, 32, 0, 0) || 1016 nouveau_pushbuf_refn (push, refs, 2)) 1017 return FALSE; 1018 1019 BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2); 1020 PUSH_DATA (push, (dst->offset + dst_off) >> 32); 1021 PUSH_DATA (push, (dst->offset + dst_off)); 1022 BEGIN_NVC0(push, NVC0_M2MF(OFFSET_IN_HIGH), 2); 1023 PUSH_DATA (push, (src->offset + src_off) >> 32); 1024 PUSH_DATA (push, (src->offset + src_off)); 1025 1026 if (src->config.nvc0.memtype) { 1027 BEGIN_NVC0(push, NVC0_M2MF(TILING_POSITION_IN_X), 2); 1028 PUSH_DATA (push, src_x * cpp); 1029 PUSH_DATA (push, src_y); 1030 } else { 1031 src_off += line_count * src_pitch; 1032 } 1033 1034 if (dst->config.nvc0.memtype) { 1035 BEGIN_NVC0(push, NVC0_M2MF(TILING_POSITION_OUT_X), 2); 1036 PUSH_DATA (push, dst_x * cpp); 1037 PUSH_DATA (push, dst_y); 1038 } else { 1039 dst_off += line_count * dst_pitch; 1040 } 1041 1042 BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2); 1043 PUSH_DATA (push, w * cpp); 1044 PUSH_DATA (push, line_count); 1045 BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1); 1046 PUSH_DATA (push, NVC0_M2MF_EXEC_QUERY_SHORT | exec); 1047 1048 src_y += line_count; 1049 dst_y += line_count; 1050 h -= line_count; 1051 } 1052 1053 return TRUE; 1054} 1055 1056Bool 1057NVE0EXARectCopy(NVPtr pNv, int w, int h, int cpp, 1058 struct nouveau_bo *src, uint32_t src_off, int src_dom, 1059 int src_pitch, int src_h, int src_x, int src_y, 1060 struct nouveau_bo *dst, uint32_t dst_off, int dst_dom, 1061 int dst_pitch, int dst_h, int dst_x, int dst_y) 1062{ 1063 return nouveau_copya0b5_rect(pNv->pushbuf, pNv->NvCOPY, w, h, cpp, 1064 src, src_off, src_dom, src_pitch, 1065 src_h, src_x, src_y, dst, dst_off, 1066 dst_dom, dst_pitch, dst_h, dst_x, dst_y); 1067} 1068