/* * Copyright 2008 Ben Skeggs * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "nv_include.h" #include "nvc0_accel.h" #include "shader/xfrm2nvc0.vp" #include "shader/videonvc0.fp" #include "shader/exascnvc0.fp" #include "shader/exacmnvc0.fp" #include "shader/exacanvc0.fp" #include "shader/exasanvc0.fp" #include "shader/exas8nvc0.fp" #include "shader/exac8nvc0.fp" #include "shader/xfrm2nve0.vp" #include "shader/videonve0.fp" #include "shader/exascnve0.fp" #include "shader/exacmnve0.fp" #include "shader/exacanve0.fp" #include "shader/exasanve0.fp" #include "shader/exas8nve0.fp" #include "shader/exac8nve0.fp" #include "shader/xfrm2nvf0.vp" #include "shader/videonvf0.fp" #include "shader/exascnvf0.fp" #include "shader/exacmnvf0.fp" #include "shader/exacanvf0.fp" #include "shader/exasanvf0.fp" #include "shader/exas8nvf0.fp" #include "shader/exac8nvf0.fp" #include "shader/xfrm2nv110.vp" #include "shader/videonv110.fp" #include "shader/exascnv110.fp" #include "shader/exacmnv110.fp" #include "shader/exacanv110.fp" #include "shader/exasanv110.fp" #include "shader/exas8nv110.fp" #include "shader/exac8nv110.fp" #define NVC0PushProgram(pNv,addr,code) do { \ const unsigned size = sizeof(code) / sizeof(code[0]); \ PUSH_DATAu((pNv)->pushbuf, (pNv)->scratch, (addr), size); \ PUSH_DATAp((pNv)->pushbuf, (code), size); \ } while(0) void NVC0SyncToVBlank(PixmapPtr ppix, BoxPtr box) { ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; int head; xf86CrtcPtr crtc; if (!pNv->NvSW || !nouveau_exa_pixmap_is_onscreen(ppix)) return; crtc = nouveau_pick_best_crtc(pScrn, FALSE, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); if (!crtc) return; if (!PUSH_SPACE(push, 32)) return; head = drmmode_head(crtc); BEGIN_NVC0(push, NV01_SUBC(NVSW, OBJECT), 1); PUSH_DATA (push, pNv->NvSW->handle); BEGIN_NVC0(push, NV84_SUBC(NVSW, SEMAPHORE_ADDRESS_HIGH), 4); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET) >> 32); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET)); PUSH_DATA (push, 0x22222222); PUSH_DATA (push, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); BEGIN_NVC0(push, SUBC_NVSW(0x0400), 4); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET) >> 32); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET)); PUSH_DATA (push, 0x11111111); PUSH_DATA (push, head); BEGIN_NVC0(push, NV84_SUBC(NVSW, SEMAPHORE_ADDRESS_HIGH), 4); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET) >> 32); PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET)); PUSH_DATA (push, 0x11111111); PUSH_DATA (push, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL); } Bool NVAccelInitM2MF_NVC0(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; int ret; ret = nouveau_object_new(pNv->channel, 0x00009039, 0x9039, NULL, 0, &pNv->NvMemFormat); if (ret) return FALSE; BEGIN_NVC0(push, NV01_SUBC(M2MF, OBJECT), 1); PUSH_DATA (push, pNv->NvMemFormat->handle); BEGIN_NVC0(push, NVC0_M2MF(QUERY_ADDRESS_HIGH), 3); PUSH_DATA (push, (pNv->scratch->offset + NTFY_OFFSET) >> 32); PUSH_DATA (push, (pNv->scratch->offset + NTFY_OFFSET)); PUSH_DATA (push, 0); return TRUE; } Bool NVAccelInitP2MF_NVE0(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t class = (pNv->dev->chipset < 0xf0) ? 0xa040 : 0xa140; int ret; ret = nouveau_object_new(pNv->channel, class, class, NULL, 0, &pNv->NvMemFormat); if (ret) return FALSE; BEGIN_NVC0(push, NV01_SUBC(P2MF, OBJECT), 1); PUSH_DATA (push, pNv->NvMemFormat->handle); return TRUE; } Bool NVAccelInitCOPY_NVE0(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t class; int ret; if (pNv->dev->chipset < 0x110) class = 0xa0b5; else if (pNv->dev->chipset < 0x130) class = 0xb0b5; else class = 0xc0b5; ret = nouveau_object_new(pNv->channel, class, class, NULL, 0, &pNv->NvCOPY); if (ret) return FALSE; BEGIN_NVC0(push, NV01_SUBC(COPY, OBJECT), 1); PUSH_DATA (push, pNv->NvCOPY->handle); return TRUE; } Bool NVAccelInit2D_NVC0(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; int ret; ret = nouveau_object_new(pNv->channel, 0x0000902d, 0x902d, NULL, 0, &pNv->Nv2D); if (ret) return FALSE; if (!PUSH_SPACE(push, 64)) return FALSE; BEGIN_NVC0(push, NV01_SUBC(2D, OBJECT), 1); PUSH_DATA (push, pNv->Nv2D->handle); BEGIN_NVC0(push, NV50_2D(CLIP_ENABLE), 1); PUSH_DATA (push, 1); BEGIN_NVC0(push, NV50_2D(COLOR_KEY_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, NV50_2D(UNK0884), 1); PUSH_DATA (push, 0x3f); BEGIN_NVC0(push, NV50_2D(UNK0888), 1); PUSH_DATA (push, 1); BEGIN_NVC0(push, NV50_2D(ROP), 1); PUSH_DATA (push, 0x55); BEGIN_NVC0(push, NV50_2D(OPERATION), 1); PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY); BEGIN_NVC0(push, NV50_2D(BLIT_DU_DX_FRACT), 4); PUSH_DATA (push, 0); PUSH_DATA (push, 1); PUSH_DATA (push, 0); PUSH_DATA (push, 1); BEGIN_NVC0(push, NV50_2D(DRAW_SHAPE), 2); PUSH_DATA (push, 4); PUSH_DATA (push, NV50_SURFACE_FORMAT_B5G6R5_UNORM); BEGIN_NVC0(push, NV50_2D(PATTERN_COLOR_FORMAT), 2); PUSH_DATA (push, 2); PUSH_DATA (push, 1); pNv->currentRop = 0xfffffffa; return TRUE; } Bool NVAccelInit3D_NVC0(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = pNv->scratch; uint32_t class, handle; int ret; if (pNv->Architecture < NV_KEPLER) { class = 0x9097; handle = 0x001f906e; } else if (pNv->dev->chipset == 0xea) { class = 0xa297; handle = 0x0000906e; } else if (pNv->dev->chipset < 0xf0) { class = 0xa097; handle = 0x0000906e; } else if (pNv->dev->chipset < 0x110) { class = 0xa197; handle = 0x0000906e; } else if (pNv->dev->chipset < 0x120) { class = 0xb097; handle = 0x0000906e; } else if (pNv->dev->chipset < 0x130) { class = 0xb197; handle = 0x0000906e; } else if (pNv->dev->chipset == 0x130) { class = 0xc097; handle = 0x0000906e; } else if (pNv->dev->chipset < 0x140) { class = 0xc197; handle = 0x0000906e; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No 3D acceleration support for NV%X\n", pNv->dev->chipset); return FALSE; } ret = nouveau_object_new(pNv->channel, class, class, NULL, 0, &pNv->Nv3D); if (ret) return FALSE; ret = nouveau_object_new(pNv->channel, handle, 0x906e, NULL, 0, &pNv->NvSW); if (ret) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DRM doesn't support sync-to-vblank\n"); } if (nouveau_pushbuf_space(push, 512, 0, 0) || nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) { pNv->scratch, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR }, 1)) return FALSE; BEGIN_NVC0(push, NV01_SUBC(3D, OBJECT), 1); PUSH_DATA (push, pNv->Nv3D->handle); BEGIN_NVC0(push, NVC0_3D(COND_MODE), 1); PUSH_DATA (push, NVC0_3D_COND_MODE_ALWAYS); BEGIN_NVC0(push, SUBC_3D(NVC0_GRAPH_NOTIFY_ADDRESS_HIGH), 3); PUSH_DATA (push, (pNv->scratch->offset + NTFY_OFFSET) >> 32); PUSH_DATA (push, (pNv->scratch->offset + NTFY_OFFSET)); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_3D(CSAA_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_3D(RT_SEPARATE_FRAG_DATA), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(0)), 2); PUSH_DATA (push, (8192 << 16) | 0); PUSH_DATA (push, (8192 << 16) | 0); BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); PUSH_DATA (push, (8192 << 16) | 0); PUSH_DATA (push, (8192 << 16) | 0); BEGIN_NVC0(push, NVC0_3D(SCISSOR_ENABLE(0)), 1); PUSH_DATA (push, 1); BEGIN_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_3D(VIEW_VOLUME_CLIP_CTRL), 1); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_3D(TIC_ADDRESS_HIGH), 3); PUSH_DATA (push, (bo->offset + TIC_OFFSET) >> 32); PUSH_DATA (push, (bo->offset + TIC_OFFSET)); PUSH_DATA (push, 15); BEGIN_NVC0(push, NVC0_3D(TSC_ADDRESS_HIGH), 3); PUSH_DATA (push, (bo->offset + TSC_OFFSET) >> 32); PUSH_DATA (push, (bo->offset + TSC_OFFSET)); PUSH_DATA (push, 0); BEGIN_NVC0(push, NVC0_3D(LINKED_TSC), 1); PUSH_DATA (push, 1); if (pNv->Architecture < NV_KEPLER) { BEGIN_NVC0(push, NVC0_3D(TEX_LIMITS(4)), 1); PUSH_DATA (push, 0x54); BEGIN_NIC0(push, NVC0_3D(BIND_TIC(4)), 2); PUSH_DATA (push, (0 << 9) | (0 << 1) | NVC0_3D_BIND_TIC_ACTIVE); PUSH_DATA (push, (1 << 9) | (1 << 1) | NVC0_3D_BIND_TIC_ACTIVE); } else { BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 6); PUSH_DATA (push, 256); PUSH_DATA (push, (bo->offset + TB_OFFSET) >> 32); PUSH_DATA (push, (bo->offset + TB_OFFSET)); PUSH_DATA (push, 0); PUSH_DATA (push, 0x00000000); PUSH_DATA (push, 0x00000001); BEGIN_NVC0(push, NVC0_3D(CB_BIND(4)), 1); PUSH_DATA (push, 0x11); BEGIN_NVC0(push, NVE4_3D(TEX_CB_INDEX), 1); PUSH_DATA (push, 1); } if (pNv->Architecture < NV_MAXWELL) { BEGIN_NVC0(push, NVC0_3D(VERTEX_QUARANTINE_ADDRESS_HIGH), 3); PUSH_DATA (push, (bo->offset + MISC_OFFSET) >> 32); PUSH_DATA (push, (bo->offset + MISC_OFFSET)); PUSH_DATA (push, 1); } else { /* Use new TIC format. Not strictly necessary for GM20x+ */ IMMED_NVC0(push, SUBC_3D(0x0f10), 1); if (pNv->dev->chipset >= 0x120) { /* Use center sample locations. */ BEGIN_NVC0(push, SUBC_3D(0x11e0), 4); PUSH_DATA (push, 0x88888888); PUSH_DATA (push, 0x88888888); PUSH_DATA (push, 0x88888888); PUSH_DATA (push, 0x88888888); } } BEGIN_NVC0(push, NVC0_3D(CODE_ADDRESS_HIGH), 2); PUSH_DATA (push, (bo->offset + CODE_OFFSET) >> 32); PUSH_DATA (push, (bo->offset + CODE_OFFSET)); if (pNv->Architecture < NV_KEPLER) { NVC0PushProgram(pNv, PVP_PASS, NVC0VP_Transform2); NVC0PushProgram(pNv, PFP_S, NVC0FP_Source); NVC0PushProgram(pNv, PFP_C, NVC0FP_Composite); NVC0PushProgram(pNv, PFP_CCA, NVC0FP_CAComposite); NVC0PushProgram(pNv, PFP_CCASA, NVC0FP_CACompositeSrcAlpha); NVC0PushProgram(pNv, PFP_S_A8, NVC0FP_Source_A8); NVC0PushProgram(pNv, PFP_C_A8, NVC0FP_Composite_A8); NVC0PushProgram(pNv, PFP_NV12, NVC0FP_NV12); BEGIN_NVC0(push, NVC0_3D(MEM_BARRIER), 1); PUSH_DATA (push, 0x1111); } else if (pNv->dev->chipset < 0xf0 && pNv->dev->chipset != 0xea) { NVC0PushProgram(pNv, PVP_PASS, NVE0VP_Transform2); NVC0PushProgram(pNv, PFP_S, NVE0FP_Source); NVC0PushProgram(pNv, PFP_C, NVE0FP_Composite); NVC0PushProgram(pNv, PFP_CCA, NVE0FP_CAComposite); NVC0PushProgram(pNv, PFP_CCASA, NVE0FP_CACompositeSrcAlpha); NVC0PushProgram(pNv, PFP_S_A8, NVE0FP_Source_A8); NVC0PushProgram(pNv, PFP_C_A8, NVE0FP_Composite_A8); NVC0PushProgram(pNv, PFP_NV12, NVE0FP_NV12); } else if (pNv->dev->chipset < 0x110) { NVC0PushProgram(pNv, PVP_PASS, NVF0VP_Transform2); NVC0PushProgram(pNv, PFP_S, NVF0FP_Source); NVC0PushProgram(pNv, PFP_C, NVF0FP_Composite); NVC0PushProgram(pNv, PFP_CCA, NVF0FP_CAComposite); NVC0PushProgram(pNv, PFP_CCASA, NVF0FP_CACompositeSrcAlpha); NVC0PushProgram(pNv, PFP_S_A8, NVF0FP_Source_A8); NVC0PushProgram(pNv, PFP_C_A8, NVF0FP_Composite_A8); NVC0PushProgram(pNv, PFP_NV12, NVF0FP_NV12); } else { NVC0PushProgram(pNv, PVP_PASS, NV110VP_Transform2); NVC0PushProgram(pNv, PFP_S, NV110FP_Source); NVC0PushProgram(pNv, PFP_C, NV110FP_Composite); NVC0PushProgram(pNv, PFP_CCA, NV110FP_CAComposite); NVC0PushProgram(pNv, PFP_CCASA, NV110FP_CACompositeSrcAlpha); NVC0PushProgram(pNv, PFP_S_A8, NV110FP_Source_A8); NVC0PushProgram(pNv, PFP_C_A8, NV110FP_Composite_A8); NVC0PushProgram(pNv, PFP_NV12, NV110FP_NV12); } BEGIN_NVC0(push, NVC0_3D(SP_SELECT(1)), 4); PUSH_DATA (push, NVC0_3D_SP_SELECT_PROGRAM_VP_B | NVC0_3D_SP_SELECT_ENABLE); PUSH_DATA (push, PVP_PASS); PUSH_DATA (push, 0x00000000); PUSH_DATA (push, 8); BEGIN_NVC0(push, NVC0_3D(VERT_COLOR_CLAMP_EN), 1); PUSH_DATA (push, 1); BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); PUSH_DATA (push, 256); PUSH_DATA (push, (bo->offset + PVP_DATA) >> 32); PUSH_DATA (push, (bo->offset + PVP_DATA)); BEGIN_NVC0(push, NVC0_3D(CB_BIND(0)), 1); PUSH_DATA (push, 0x01); BEGIN_NVC0(push, NVC0_3D(SP_SELECT(5)), 4); PUSH_DATA (push, NVC0_3D_SP_SELECT_PROGRAM_FP | NVC0_3D_SP_SELECT_ENABLE); PUSH_DATA (push, PFP_S); PUSH_DATA (push, 0x00000000); PUSH_DATA (push, 8); BEGIN_NVC0(push, NVC0_3D(FRAG_COLOR_CLAMP_EN), 1); PUSH_DATA (push, 0x11111111); BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); PUSH_DATA (push, 256); PUSH_DATA (push, (bo->offset + PFP_DATA) >> 32); PUSH_DATA (push, (bo->offset + PFP_DATA)); BEGIN_NVC0(push, NVC0_3D(CB_BIND(4)), 1); PUSH_DATA (push, 0x01); return TRUE; }