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