Bool NV40EXACheckComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict) { nv_pict_surface_format_t *fmt; nv_pict_op_t *opr; opr = NV40_GetPictOpRec(op); if (!opr) NOUVEAU_FALLBACK("unsupported blend op 0x%x\n", op); fmt = NV40_GetPictSurfaceFormat(pdPict->format); if (!fmt) NOUVEAU_FALLBACK("dst picture format 0x%08x not supported\n", pdPict->format); if (!NV40EXACheckCompositeTexture(psPict, pdPict, op)) NOUVEAU_FALLBACK("src picture\n"); if (pmPict) { if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format) && opr->src_alpha && opr->src_card_op != SF(ZERO)) NOUVEAU_FALLBACK("mask CA + SA\n"); if (!NV40EXACheckCompositeTexture(pmPict, pdPict, op)) NOUVEAU_FALLBACK("mask picture\n"); } return TRUE; }
Bool NV40EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *curie = pNv->Nv3D; nv_pict_op_t *blend; int fpid = NV40EXA_FPID_PASS_COL0; NV40EXA_STATE; if (MARK_RING(chan, 128, 1 + 1 + 2*2)) return FALSE; blend = NV40_GetPictOpRec(op); NV40_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV40_SetupSurface(pScrn, pdPix, pdPict->format) || !NV40EXATexture(pScrn, psPix, psPict, 0)) { MARK_UNDO(chan); return FALSE; } NV40_LoadVtxProg(pScrn, &nv40_vp_exa_render); if (pmPict) { if (!NV40EXATexture(pScrn, pmPix, pmPict, 1)) { MARK_UNDO(chan); return FALSE; } if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fpid = NV40EXA_FPID_COMPOSITE_MASK_SA_CA; else fpid = NV40EXA_FPID_COMPOSITE_MASK_CA; } else { fpid = NV40EXA_FPID_COMPOSITE_MASK; } state->have_mask = TRUE; } else { fpid = NV40EXA_FPID_PASS_TEX0; state->have_mask = FALSE; } if (!NV40_LoadFragProg(pScrn, (pdPict->format == PICT_a8) ? nv40_fp_map_a8[fpid] : nv40_fp_map[fpid])) { MARK_UNDO(chan); return FALSE; } /* Appears to be some kind of cache flush, needed here at least * sometimes.. funky text rendering otherwise :) */ BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); OUT_RING (chan, 2); BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); OUT_RING (chan, 1); pNv->alu = op; pNv->pspict = psPict; pNv->pmpict = pmPict; pNv->pdpict = pdPict; pNv->pspix = psPix; pNv->pmpix = pmPix; pNv->pdpix = pdPix; chan->flush_notify = NV40EXAStateCompositeReemit; return TRUE; }
Bool NV40EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); nv_pict_op_t *blend = NV40_GetPictOpRec(op); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t fragprog; if (!PUSH_SPACE(push, 128)) NOUVEAU_FALLBACK("space\n"); PUSH_RESET(push); NV40_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV40_SetupSurface(pScrn, pdPix, pdPict->format) || !NV40EXAPicture(pNv, psPix, psPict, 0)) return FALSE; if (pmPict) { if (!NV40EXAPicture(pNv, pmPix, pmPict, 1)) return FALSE; if (pdPict->format == PICT_a8) { fragprog = PFP_C_A8; } else if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fragprog = PFP_CCASA; else fragprog = PFP_CCA; } else { fragprog = PFP_C; } } else { if (pdPict->format == PICT_a8) fragprog = PFP_S_A8; else fragprog = PFP_S; } BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch, fragprog, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, NV30_3D_FP_ACTIVE_PROGRAM_DMA0, NV30_3D_FP_ACTIVE_PROGRAM_DMA1); BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); PUSH_DATA (push, 0x02000000); /* Appears to be some kind of cache flush, needed here at least * sometimes.. funky text rendering otherwise :) */ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 2); BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 1); nouveau_pushbuf_bufctx(push, pNv->bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return FALSE; } return TRUE; }