From 7af7d95eb8826fa3fb9914a8c6ad4b6f4867095e Mon Sep 17 00:00:00 2001 From: Henry Zhao Date: Mon, 23 Apr 2007 01:38:09 +0200 Subject: Import from nv : Need to inject a mode corresponding panel width/height for validation --- src/nv_driver.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/nv_driver.c b/src/nv_driver.c index 24564e8..acd8f42 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -33,6 +33,8 @@ #include "xf86drm.h" +extern DisplayModePtr xf86ModesAdd(DisplayModePtr Modes, DisplayModePtr Additions); + /*const OptionInfoRec * RivaAvailableOptions(int chipid, int busid); Bool RivaGetScrnInfoRec(PciChipsets *chips, int chip);*/ @@ -1036,6 +1038,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) int i, max_width, max_height; ClockRangePtr clockRanges; const char *s; + int config_mon_rates; if (flags & PROBE_DETECT) { EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]); @@ -1497,7 +1500,13 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) xf86FreeInt10(pNv->pInt); return FALSE; } - + + if ((pScrn->monitor->nHsync == 0) && + (pScrn->monitor->nVrefresh == 0)) + config_mon_rates = FALSE; + else + config_mon_rates = TRUE; + NVCommonSetup(pScrn); pScrn->videoRam = pNv->RamAmountKBytes; @@ -1555,6 +1564,36 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) max_height = 4096; } + /* If DFP, add a modeline corresponding to its panel size */ + if (pNv->FlatPanel && !pNv->Television && pNv->fpWidth && pNv->fpHeight) { + DisplayModePtr Mode; + + Mode = xnfcalloc(1, sizeof(DisplayModeRec)); + Mode = xf86CVTMode(pNv->fpWidth, pNv->fpHeight, 60.00, TRUE, FALSE); + Mode->type = M_T_DRIVER; + pScrn->monitor->Modes = xf86ModesAdd(pScrn->monitor->Modes, Mode); + + if (!config_mon_rates) { + if (!Mode->HSync) + Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal); + if (!Mode->VRefresh) + Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / + ((float) (Mode->HTotal * Mode->VTotal)); + + if (Mode->HSync < pScrn->monitor->hsync[0].lo) + pScrn->monitor->hsync[0].lo = Mode->HSync; + if (Mode->HSync > pScrn->monitor->hsync[0].hi) + pScrn->monitor->hsync[0].hi = Mode->HSync; + if (Mode->VRefresh < pScrn->monitor->vrefresh[0].lo) + pScrn->monitor->vrefresh[0].lo = Mode->VRefresh; + if (Mode->VRefresh > pScrn->monitor->vrefresh[0].hi) + pScrn->monitor->vrefresh[0].hi = Mode->VRefresh; + + pScrn->monitor->nHsync = 1; + pScrn->monitor->nVrefresh = 1; + } + } + /* * xf86ValidateModes will check that the mode HTotal and VTotal values * don't exceed the chipset's limit if pScrn->maxHValue and -- cgit v1.2.1 From d59fbb4725602c409beee4ab96dca1eab5d73b2a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 11 Jun 2007 20:36:28 +1000 Subject: don't nuke user-specified CFLAGS --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ab50e7f..412f37f 100644 --- a/configure.ac +++ b/configure.ac @@ -76,7 +76,7 @@ sdkdir=$(pkg-config --variable=sdkdir xorg-server) AC_HEADER_STDC # Use -Wall all the time -CFLAGS=-Wall +CFLAGS="$CFLAGS -Wall" AC_SUBST([CFLAGS]) AC_SUBST([XORG_CFLAGS]) -- cgit v1.2.1 From d41cf4febd555cca1c65df7aa981be64a6ae4219 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 24 Jun 2007 16:46:40 +1000 Subject: Pass pScrn instead of pNv in a few places --- src/nv_accel_common.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index 76697a6..0004bc2 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -1,8 +1,9 @@ #include "nv_include.h" static Bool -NVAccelInitNullObject(NVPtr pNv) +NVAccelInitNullObject(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; if (!have_object) { @@ -16,8 +17,9 @@ NVAccelInitNullObject(NVPtr pNv) } static Bool -NVAccelInitDmaFB(NVPtr pNv) +NVAccelInitDmaFB(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; if (!have_object) { @@ -49,8 +51,9 @@ NVAccelGetPixmapOffset(NVPtr pNv, PixmapPtr pPix) } static Bool -NVAccelInitDmaAGP(NVPtr pNv) +NVAccelInitDmaAGP(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; if (!pNv->AGPSize) @@ -72,8 +75,9 @@ NVAccelInitDmaAGP(NVPtr pNv) } static Bool -NVAccelInitDmaNotifier0(NVPtr pNv) +NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; if (!have_object) { @@ -88,8 +92,9 @@ NVAccelInitDmaNotifier0(NVPtr pNv) /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */ static Bool -NVAccelInitContextSurfaces(NVPtr pNv) +NVAccelInitContextSurfaces(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; uint32_t class; @@ -174,8 +179,9 @@ NVAccelSetCtxSurf2D(NVPtr pNv, PixmapPtr psPix, PixmapPtr pdPix, int format) /* FLAGS_ROP_AND|FLAGS_MONO, 0, 0, 0 */ static Bool -NVAccelInitImagePattern(NVPtr pNv) +NVAccelInitImagePattern(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; uint32_t class; @@ -206,8 +212,9 @@ NVAccelInitImagePattern(NVPtr pNv) /* FLAGS_ROP_AND, 0, 0, 0 */ static Bool -NVAccelInitRasterOp(NVPtr pNv) +NVAccelInitRasterOp(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; uint32_t class; @@ -228,8 +235,9 @@ NVAccelInitRasterOp(NVPtr pNv) /* FLAGS_ROP_AND | FLAGS_MONO, 0, 0, 0 */ static Bool -NVAccelInitRectangle(NVPtr pNv) +NVAccelInitRectangle(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; uint32_t class; @@ -262,8 +270,9 @@ NVAccelInitRectangle(NVPtr pNv) /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */ static Bool -NVAccelInitImageBlit(NVPtr pNv) +NVAccelInitImageBlit(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; uint32_t class; @@ -294,8 +303,9 @@ NVAccelInitImageBlit(NVPtr pNv) /* FLAGS_SRCCOPY, DmaFB, DmaFB, 0 */ static Bool -NVAccelInitScaledImage(NVPtr pNv) +NVAccelInitScaledImage(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; uint32_t class; @@ -347,8 +357,9 @@ NVAccelInitScaledImage(NVPtr pNv) /* FLAGS_NONE, 0, 0, 0 */ static Bool -NVAccelInitClipRectangle(NVPtr pNv) +NVAccelInitClipRectangle(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; int class = NV01_CONTEXT_CLIP_RECTANGLE; @@ -367,8 +378,9 @@ NVAccelInitClipRectangle(NVPtr pNv) /* FLAGS_ROP_AND | FLAGS_CLIP_ENABLE, 0, 0, 0 */ static Bool -NVAccelInitSolidLine(NVPtr pNv) +NVAccelInitSolidLine(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; int class = NV04_SOLID_LINE; @@ -393,8 +405,9 @@ NVAccelInitSolidLine(NVPtr pNv) /* FLAGS_NONE, NvDmaFB, NvDmaAGP, NvDmaNotifier0 */ static Bool -NVAccelInitMemFormat(NVPtr pNv) +NVAccelInitMemFormat(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); static int have_object = FALSE; uint32_t class; @@ -420,7 +433,7 @@ NVAccelInitMemFormat(NVPtr pNv) } #define INIT_CONTEXT_OBJECT(name) do { \ - ret = NVAccelInit##name(pNv); \ + ret = NVAccelInit##name(pScrn); \ if (!ret) { \ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \ "Failed to initialise context object: "#name \ -- cgit v1.2.1 From 45dccb99a541a0e1e7be7b4e5aab12c3d8d9f30d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 24 Jun 2007 16:47:36 +1000 Subject: Hide the allocator's use of physical addresses --- src/nv_accel_common.c | 4 ++-- src/nv_dma.c | 12 +++--------- src/nv_dri.c | 2 +- src/nv_driver.c | 2 +- src/nv_exa.c | 4 ++-- src/nv_hw.c | 2 +- src/nv_mem.c | 5 +++++ src/nv_video.c | 1 - src/nv_xaa.c | 8 ++------ 9 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index 0004bc2..b1ba672 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -40,11 +40,11 @@ NVAccelGetPixmapOffset(NVPtr pNv, PixmapPtr pPix) CARD32 offset; if (pPix->drawable.type == DRAWABLE_WINDOW) { - offset = pNv->FB->offset - pNv->VRAMPhysical; + offset = pNv->FB->offset; } else { offset = (uint32_t)((unsigned long)pPix->devPrivate.ptr - (unsigned long)pNv->FB->map); - offset += pNv->FB->offset - pNv->VRAMPhysical; + offset += pNv->FB->offset; } return offset; diff --git a/src/nv_dma.c b/src/nv_dma.c index a612c9b..cc5bdd6 100644 --- a/src/nv_dma.c +++ b/src/nv_dma.c @@ -170,8 +170,8 @@ void NVResetGraphics(ScrnInfoPtr pScrn) NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 4); NVDmaNext (pNv, surfaceFormat); NVDmaNext (pNv, pitch | (pitch << 16)); - NVDmaNext (pNv, (CARD32)(pNv->FB->offset - pNv->VRAMPhysical)); - NVDmaNext (pNv, (CARD32)(pNv->FB->offset - pNv->VRAMPhysical)); + NVDmaNext (pNv, (uint32_t)pNv->FB->offset); + NVDmaNext (pNv, (uint32_t)pNv->FB->offset); NVDmaStart(pNv, NvSubImagePattern, PATTERN_FORMAT, 1); NVDmaNext (pNv, patternFormat); @@ -214,20 +214,14 @@ Bool NVDmaCreateDMAObject(NVPtr pNv, uint32_t handle, int class, Bool NVDmaCreateDMAObjectFromMem(NVPtr pNv, uint32_t handle, int class, NVAllocRec *mem, int access) { - uint32_t offset = mem->offset; int target; target = mem->type & (NOUVEAU_MEM_FB | NOUVEAU_MEM_AGP); if (!target) return FALSE; - if (target & NOUVEAU_MEM_FB) - offset -= pNv->VRAMPhysical; - else if (target & NOUVEAU_MEM_AGP) - offset -= pNv->AGPPhysical; - return NVDmaCreateDMAObject(pNv, handle, class, target, - offset, mem->size, access); + mem->offset, mem->size, access); } /* diff --git a/src/nv_dri.c b/src/nv_dri.c index 7edb865..b6c38b0 100644 --- a/src/nv_dri.c +++ b/src/nv_dri.c @@ -377,7 +377,7 @@ Bool NVDRIFinishScreenInit(ScrnInfoPtr pScrn) pNOUVEAUDRI->depth = pScrn->depth; pNOUVEAUDRI->bpp = pScrn->bitsPerPixel; - pNOUVEAUDRI->front_offset = pNv->FB->offset - pNv->VRAMPhysical; + pNOUVEAUDRI->front_offset = pNv->FB->offset; pNOUVEAUDRI->front_pitch = pScrn->virtualX; /* back/depth buffers will likely be allocated on a per-drawable * basis, but these may be useful if we want to support shared back diff --git a/src/nv_driver.c b/src/nv_driver.c index acd8f42..61c89e3 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -832,7 +832,7 @@ NVAdjustFrame(int scrnIndex, int x, int y, int flags) NVFBLayout *pLayout = &pNv->CurrentLayout; startAddr = (((y*pLayout->displayWidth)+x)*(pLayout->bitsPerPixel/8)); - startAddr += (pNv->FB->offset - pNv->VRAMPhysical); + startAddr += pNv->FB->offset; NVSetStartAddress(pNv, startAddr); } diff --git a/src/nv_exa.c b/src/nv_exa.c index ed6901b..ae5a14a 100644 --- a/src/nv_exa.c +++ b/src/nv_exa.c @@ -291,7 +291,7 @@ static Bool NVDownloadFromScreen(PixmapPtr pSrc, NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_OFFSET_IN, 8); NVDmaNext (pNv, offset_in); - NVDmaNext (pNv, (uint32_t)(pNv->AGPScratch->offset - pNv->AGPPhysical)); + NVDmaNext (pNv, (uint32_t)pNv->AGPScratch->offset); NVDmaNext (pNv, pitch_in); NVDmaNext (pNv, dst_pitch); NVDmaNext (pNv, line_length); @@ -353,7 +353,7 @@ static Bool NVUploadToScreen(PixmapPtr pDst, NVDmaNext (pNv, 0); NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_OFFSET_IN, 8); - NVDmaNext (pNv, (uint32_t)(pNv->AGPScratch->offset - pNv->AGPPhysical)); + NVDmaNext (pNv, (uint32_t)pNv->AGPScratch->offset); NVDmaNext (pNv, offset_out); NVDmaNext (pNv, src_pitch); NVDmaNext (pNv, pitch_out); diff --git a/src/nv_hw.c b/src/nv_hw.c index 6cddf60..0dc78a1 100644 --- a/src/nv_hw.c +++ b/src/nv_hw.c @@ -940,7 +940,7 @@ void NVCalcStateExt ( &(state->arbitration0), &(state->arbitration1)); } - CursorStart = pNv->Cursor->offset - pNv->VRAMPhysical; + CursorStart = pNv->Cursor->offset; state->cursor0 = 0x80 | (CursorStart >> 17); state->cursor1 = (CursorStart >> 11) << 2; state->cursor2 = CursorStart >> 24; diff --git a/src/nv_mem.c b/src/nv_mem.c index 32dc25f..0ecd71a 100644 --- a/src/nv_mem.c +++ b/src/nv_mem.c @@ -32,6 +32,11 @@ NVAllocRec *NVAllocateMemory(NVPtr pNv, int type, int size) return NULL; } + if (mem->type & NOUVEAU_MEM_FB) + mem->offset -= pNv->VRAMPhysical; + else if (mem->type & NOUVEAU_MEM_AGP) + mem->offset -= pNv->AGPPhysical; + return mem; } diff --git a/src/nv_video.c b/src/nv_video.c index cf4f88d..3865142 100644 --- a/src/nv_video.c +++ b/src/nv_video.c @@ -917,7 +917,6 @@ NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y, dst_start = pPriv->video_mem->map + (offset - (uint32_t)pPriv->video_mem->offset); - offset -= pNv->VRAMPhysical; /* We need to enlarge the copied rectangle by a pixel so the HW * filtering doesn't pick up junk laying outside of the source */ diff --git a/src/nv_xaa.c b/src/nv_xaa.c index 851e3bf..0d07e70 100644 --- a/src/nv_xaa.c +++ b/src/nv_xaa.c @@ -105,10 +105,6 @@ static const int NVPatternROP[16] = 0xFF }; -static CARD32 getOffset(NVPtr pNv, NVAllocRec *mem) { - return (mem->offset - pNv->VRAMPhysical); -} - void NVWaitVSync(NVPtr pNv) { @@ -418,7 +414,7 @@ NVSubsequentScanlineImageWriteRect( NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_PITCH, 2); NVDmaNext (pNv, (_image_dstpitch << 16) | image_srcpitch); - NVDmaNext (pNv, getOffset(pNv, pNv->ScratchBuffer)); + NVDmaNext (pNv, pNv->ScratchBuffer->offset); } static void NVSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) @@ -437,7 +433,7 @@ static void NVSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) } else { NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_PITCH, 2); NVDmaNext (pNv, _image_dstpitch | (_image_dstpitch << 16)); - NVDmaNext (pNv, getOffset(pNv, pNv->FB)); + NVDmaNext (pNv, pNv->FB->offset); } } -- cgit v1.2.1 From c39089b3d686eecef11db2b5a2d606ba1ca2dc0c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 24 Jun 2007 17:21:27 +1000 Subject: Match drm 0.0.7 interface changes --- src/Makefile.am | 1 + src/nv_accel_common.c | 46 +------------ src/nv_dma.c | 180 ++++++++++++-------------------------------------- src/nv_dma.h | 2 +- src/nv_dri.c | 2 +- src/nv_driver.c | 23 ++++--- src/nv_exa.c | 13 ++-- src/nv_mem.c | 4 ++ src/nv_notifier.c | 126 +++++++++++++++++++++++++++++++++++ src/nv_proto.h | 16 +++-- src/nv_type.h | 4 +- 11 files changed, 209 insertions(+), 208 deletions(-) create mode 100644 src/nv_notifier.c diff --git a/src/Makefile.am b/src/Makefile.am index bc9e745..783a284 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,7 @@ nouveau_drv_la_SOURCES = \ nv_dripriv.h \ nv_local.h \ nv_mem.c \ + nv_notifier.c \ nv_proto.h \ nvreg.h \ nv_setup.c \ diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index b1ba672..f04d507 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -16,24 +16,6 @@ NVAccelInitNullObject(ScrnInfoPtr pScrn) return TRUE; } -static Bool -NVAccelInitDmaFB(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - static int have_object = FALSE; - - if (!have_object) { - if (!NVDmaCreateDMAObject(pNv, NvDmaFB, NV_DMA_IN_MEMORY, - NOUVEAU_MEM_FB, 0, - pNv->VRAMSize, - NOUVEAU_MEM_ACCESS_RW)) - return FALSE; - have_object = TRUE; - } - - return TRUE; -} - uint32_t NVAccelGetPixmapOffset(NVPtr pNv, PixmapPtr pPix) { @@ -50,30 +32,6 @@ NVAccelGetPixmapOffset(NVPtr pNv, PixmapPtr pPix) return offset; } -static Bool -NVAccelInitDmaAGP(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - static int have_object = FALSE; - - if (!pNv->AGPSize) - return TRUE; - - if (!have_object) { - if (!NVDmaCreateDMAObject(pNv, NvDmaAGP, NV_DMA_IN_MEMORY, - NOUVEAU_MEM_AGP, 0, - pNv->AGPSize, - NOUVEAU_MEM_ACCESS_RW)) { - ErrorF("Couldn't create AGP object, disabling AGP\n"); - NVFreeMemory(pNv, pNv->AGPScratch); - pNv->AGPScratch = NULL; - } - have_object = TRUE; - } - - return TRUE; -} - static Bool NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn) { @@ -81,7 +39,7 @@ NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn) static int have_object = FALSE; if (!have_object) { - pNv->Notifier0 = NVDmaCreateNotifier(pNv, NvDmaNotifier0); + pNv->Notifier0 = NVNotifierAlloc(pScrn, NvDmaNotifier0); if (!pNv->Notifier0) return FALSE; have_object = TRUE; @@ -450,8 +408,6 @@ NVAccelCommonInit(ScrnInfoPtr pScrn) if(pNv->NoAccel) return TRUE; INIT_CONTEXT_OBJECT(NullObject); - INIT_CONTEXT_OBJECT(DmaFB); - INIT_CONTEXT_OBJECT(DmaAGP); INIT_CONTEXT_OBJECT(DmaNotifier0); INIT_CONTEXT_OBJECT(ContextSurfaces); diff --git a/src/nv_dma.c b/src/nv_dma.c index cc5bdd6..a9d0127 100644 --- a/src/nv_dma.c +++ b/src/nv_dma.c @@ -191,137 +191,15 @@ void NVResetGraphics(ScrnInfoPtr pScrn) /*NVDmaKickoff(pNv);*/ } -Bool NVDmaCreateDMAObject(NVPtr pNv, uint32_t handle, int class, - int target, - CARD32 offset, CARD32 size, int access) -{ - drm_nouveau_dma_object_init_t dma; - int ret; - - dma.channel = pNv->fifo.channel; - dma.handle = handle; - dma.class = class; - dma.access = access; - dma.target = target; - dma.size = size; - dma.offset = offset; - ret = drmCommandWrite(pNv->drm_fd, DRM_NOUVEAU_DMA_OBJECT_INIT, - &dma, sizeof(dma)); - - return ret == 0; -} - -Bool NVDmaCreateDMAObjectFromMem(NVPtr pNv, uint32_t handle, int class, - NVAllocRec *mem, int access) -{ - int target; - - target = mem->type & (NOUVEAU_MEM_FB | NOUVEAU_MEM_AGP); - if (!target) - return FALSE; - - return NVDmaCreateDMAObject(pNv, handle, class, target, - mem->offset, mem->size, access); -} - -/* -A DMA notifier is a DMA object that references a small (32 byte it -seems, we use 256 for saftey) memory area that will be used by the HW to give feedback -about a DMA operation. -*/ -NVAllocRec *NVDmaCreateNotifier(NVPtr pNv, int handle) -{ - NVAllocRec *notifier = NULL; - -#ifndef __powerpc__ - notifier = NVAllocateMemory(pNv, NOUVEAU_MEM_AGP | - NOUVEAU_MEM_FB_ACCEPTABLE, - 256); -#else - notifier = NVAllocateMemory(pNv, NOUVEAU_MEM_FB, 256); -#endif - - if (!notifier) - return NULL; - - if (!NVDmaCreateDMAObjectFromMem(pNv, handle, NV_DMA_IN_MEMORY, - notifier, - NOUVEAU_MEM_ACCESS_RW)) { - NVFreeMemory(pNv, notifier); - return NULL; - } - - return notifier; -} - -/* How do we wait for DMA completion (by notifiers) ? - * - * Either repeatedly read the notifier address and wait until it changes, - * or enable a 'wakeup' interrupt by writing NOTIFY_WRITE_LE_AWAKEN into - * the 'notify' field of the object in the channel. My guess is that - * this causes an interrupt in PGRAPH/NOTIFY as soon as the transfer is - * completed. Clients probably can use poll on the nv* devices to get this - * event. All this is a guess. I don't know any details, and I have not - * tested is. Also, I have no idea how the 'nvdriver' reacts if it gets - * notify events that are not registered. - * - * Writing NV_NOTIFY_WRITE_LE_AWAKEN into the 'Notify' field of an object - * in a channel really causes an interrupt in the PGRAPH engine. Thus - * we can determine whether a DMA transfer has finished in the interrupt - * handler. - * - * We can't use interrupts in user land, so we do the simple polling approach. - * The method returns FALSE in case of an error. - */ -Bool NVDmaWaitForNotifier(NVPtr pNv, void *notifier) -{ - int t_start, timeout = 0; - volatile CARD32 *n; - - n = (volatile CARD32 *)notifier; - NVDEBUG("NVDmaWaitForNotifier @%p", n); - t_start = GetTimeInMillis(); - while (1) { - CARD32 a = n[0]; - CARD32 b = n[1]; - CARD32 c = n[2]; - CARD32 status = n[3]; - NVDEBUG("status: n[0]=%x, n[1]=%x, n[2]=%x, n[3]=%x\n", a, b, c, status); - NVDEBUG("status: GET: 0x%08x\n", READ_GET(pNv)); - - if (GetTimeInMillis() - t_start >= 2000) { - /* We've timed out, call NVSync() to detect lockups */ - if (timeout++ == 0) { - NVDoSync(pNv); - /* If we're still here, wait another second for notifier.. */ - t_start = GetTimeInMillis() + 1000; - break; - } - /* Still haven't recieved notification, log error */ - ErrorF("Notifier timeout\n"); - return FALSE; - } - - if (status == 0xffffffff) - continue; - if (!status) - break; - if (status & 0xffff) - return FALSE; - } - - return TRUE; -} - Bool NVDmaCreateContextObject(NVPtr pNv, int handle, int class) { - drm_nouveau_object_init_t cto; + drm_nouveau_grobj_alloc_t cto; int ret; cto.channel = pNv->fifo.channel; cto.handle = handle; cto.class = class; - ret = drmCommandWrite(pNv->drm_fd, DRM_NOUVEAU_OBJECT_INIT, + ret = drmCommandWrite(pNv->drm_fd, DRM_NOUVEAU_GROBJ_ALLOC, &cto, sizeof(cto)); return ret == 0; } @@ -360,32 +238,60 @@ static void NVInitDmaCB(ScrnInfoPtr pScrn) Bool NVInitDma(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); - int i; + int i, ret; NVInitDmaCB(pScrn); - if(pNv->NoAccel) return TRUE; + if (pNv->NoAccel) + return TRUE; + + pNv->fifo.fb_ctxdma_handle = NvDmaFB; + pNv->fifo.tt_ctxdma_handle = NvDmaTT; + ret = drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_FIFO_ALLOC, + &pNv->fifo, sizeof(pNv->fifo)); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not allocate GPU channel: %d\n", ret); + return FALSE; + } - if (drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_FIFO_ALLOC, &pNv->fifo, sizeof(pNv->fifo)) != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not initialise kernel module\n"); + ret = drmMap(pNv->drm_fd, pNv->fifo.cmdbuf, pNv->fifo.cmdbuf_size, + (drmAddressPtr)&pNv->dmaBase); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to map DMA push buffer: %d\n", ret); return FALSE; } - if (drmMap(pNv->drm_fd, pNv->fifo.cmdbuf, pNv->fifo.cmdbuf_size, (drmAddressPtr)&pNv->dmaBase)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to map DMA command buffer\n"); + ret = drmMap(pNv->drm_fd, pNv->fifo.ctrl, pNv->fifo.ctrl_size, + (drmAddressPtr)&pNv->FIFO); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to map FIFO control regs: %d\n", ret); return FALSE; } - if (drmMap(pNv->drm_fd, pNv->fifo.ctrl, pNv->fifo.ctrl_size, (drmAddressPtr)&pNv->FIFO)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to map FIFO control regs\n"); + ret = drmMap(pNv->drm_fd, pNv->fifo.notifier, pNv->fifo.notifier_size, + (drmAddressPtr)&pNv->NotifierBlock); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to map notifier block: %d\n", ret); return FALSE; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using FIFO channel %d\n", pNv->fifo.channel); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Control registers : %p (0x%08x)\n", pNv->FIFO, pNv->fifo.ctrl); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, " DMA command buffer: %p (0x%08x)\n", pNv->dmaBase, pNv->fifo.cmdbuf); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, " DMA cmdbuf length : %d KiB\n", pNv->fifo.cmdbuf_size / 1024); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, " DMA base PUT : 0x%08x\n", pNv->fifo.put_base); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using FIFO channel %d\n", pNv->fifo.channel); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " Control registers : %p (0x%08x)\n", + pNv->FIFO, pNv->fifo.ctrl); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " DMA command buffer: %p (0x%08x)\n", + pNv->dmaBase, pNv->fifo.cmdbuf); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " DMA cmdbuf length : %d KiB\n", + pNv->fifo.cmdbuf_size / 1024); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " DMA base PUT : 0x%08x\n", pNv->fifo.put_base); pNv->dmaPut = pNv->dmaCurrent = READ_GET(pNv); pNv->dmaMax = (pNv->fifo.cmdbuf_size >> 2) - 1; diff --git a/src/nv_dma.h b/src/nv_dma.h index 3d43fcd..29695e2 100644 --- a/src/nv_dma.h +++ b/src/nv_dma.h @@ -67,7 +67,7 @@ enum DMAObjects { NvMemFormat = 0x80000018, Nv3D = 0x80000019, NvDmaFB = 0xD8000001, - NvDmaAGP = 0xD8000002, + NvDmaTT = 0xD8000002, NvDmaNotifier0 = 0xD8000003 }; diff --git a/src/nv_dri.c b/src/nv_dri.c index b6c38b0..857fb42 100644 --- a/src/nv_dri.c +++ b/src/nv_dri.c @@ -244,7 +244,7 @@ Bool NVDRIGetVersion(ScrnInfoPtr pScrn) } /* temporary lock step versioning */ -#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 6 +#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 7 #error nouveau_drm.h doesn't match expected patchlevel, update libdrm. #endif if (pNv->pKernelDRMVersion->version_patchlevel != diff --git a/src/nv_driver.c b/src/nv_driver.c index 61c89e3..f437bee 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -1718,9 +1718,8 @@ NVMapMem(ScrnInfoPtr pScrn) return FALSE; } xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Allocated %lldMiB VRAM for framebuffer + offscreen pixmaps\n", - pNv->FB->size >> 20 - ); + "Allocated %dMiB VRAM for framebuffer + offscreen pixmaps\n", + (unsigned int)(pNv->FB->size >> 20)); /*XXX: have to get these after we've allocated something, otherwise * they're uninitialised in the DRM! @@ -1733,8 +1732,9 @@ NVMapMem(ScrnInfoPtr pScrn) if (pNv->AGPSize) { int gart_scratch_size; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AGP: %dMiB available\n", - (unsigned int)pNv->AGPSize >> 20); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "GART: %dMiB available\n", + (unsigned int)(pNv->AGPSize >> 20)); if (pNv->AGPSize > (16*1024*1024)) gart_scratch_size = 16*1024*1024; @@ -1743,14 +1743,15 @@ NVMapMem(ScrnInfoPtr pScrn) pNv->AGPScratch = NVAllocateMemory(pNv, NOUVEAU_MEM_AGP, gart_scratch_size); - if (!pNv->AGPScratch) + if (!pNv->AGPScratch) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unable to allocate AGP memory\n"); - else + "Unable to allocate GART memory\n"); + } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "AGP: mapped %dMiB at %p\n", - (unsigned int)pNv->AGPScratch->size>>20, - pNv->AGPScratch->map); + "GART: mapped %dMiB at %p\n", + (unsigned int)(pNv->AGPScratch->size >> 20), + pNv->AGPScratch->map); + } } pNv->Cursor = NVAllocateMemory(pNv, NOUVEAU_MEM_FB, 64*1024); diff --git a/src/nv_exa.c b/src/nv_exa.c index ae5a14a..c01a4c6 100644 --- a/src/nv_exa.c +++ b/src/nv_exa.c @@ -53,8 +53,8 @@ static void setM2MFDirection(NVPtr pNv, int dir) { if (pNv->M2MFDirection != dir) { NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2); - NVDmaNext (pNv, dir ? NvDmaAGP : NvDmaFB); - NVDmaNext (pNv, dir ? NvDmaFB : NvDmaAGP); + NVDmaNext (pNv, dir ? NvDmaTT : NvDmaFB); + NVDmaNext (pNv, dir ? NvDmaFB : NvDmaTT); pNv->M2MFDirection = dir; } } @@ -285,7 +285,7 @@ static Bool NVDownloadFromScreen(PixmapPtr pSrc, NVDEBUG(" max_lines=%d, h=%d\n", max_lines, h); /* reset the notification object */ - memset(pNv->Notifier0->map, 0xff, pNv->Notifier0->size); + NVNotifierReset(pScrn, pNv->Notifier0); NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_NOTIFY, 1); NVDmaNext (pNv, 0); @@ -300,7 +300,7 @@ static Bool NVDownloadFromScreen(PixmapPtr pSrc, NVDmaNext (pNv, 0); NVDmaKickoff(pNv); - if (!NVDmaWaitForNotifier(pNv, pNv->Notifier0->map)) { + if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000)) { ret = FALSE; goto error; } @@ -347,7 +347,8 @@ static Bool NVUploadToScreen(PixmapPtr pDst, int nlines = h > max_lines ? max_lines : h; /* reset the notification object */ - memset(pNv->Notifier0->map, 0xff, pNv->Notifier0->size); + NVNotifierReset(pScrn, pNv->Notifier0); + memcpy(pNv->AGPScratch->map, src, nlines*src_pitch); NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_NOTIFY, 1); NVDmaNext (pNv, 0); @@ -363,7 +364,7 @@ static Bool NVUploadToScreen(PixmapPtr pDst, NVDmaNext (pNv, 0); NVDmaKickoff(pNv); - if (!NVDmaWaitForNotifier(pNv, pNv->Notifier0->map)) { + if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000)) { ret = FALSE; goto error; } diff --git a/src/nv_mem.c b/src/nv_mem.c index 0ecd71a..99cb8bc 100644 --- a/src/nv_mem.c +++ b/src/nv_mem.c @@ -54,6 +54,10 @@ void NVFreeMemory(NVPtr pNv, NVAllocRec *mem) memfree.flags = mem->type; memfree.region_offset = mem->offset; + if (mem->type & NOUVEAU_MEM_FB) + memfree.region_offset += pNv->VRAMPhysical; + else if (mem->type & NOUVEAU_MEM_AGP) + memfree.region_offset += pNv->AGPPhysical; if (drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_MEM_FREE, &memfree, sizeof(memfree))) { diff --git a/src/nv_notifier.c b/src/nv_notifier.c new file mode 100644 index 0000000..88f0edb --- /dev/null +++ b/src/nv_notifier.c @@ -0,0 +1,126 @@ +#include "nv_include.h" + +#define NV_NOTIFIER_SIZE 32 +#define NV_NOTIFY_TIME_0 0x00000000 +#define NV_NOTIFY_TIME_1 0x00000004 +#define NV_NOTIFY_RETURN_VALUE 0x00000008 +#define NV_NOTIFY_STATE 0x0000000C +#define NV_NOTIFY_STATE_STATUS_MASK 0xFF000000 +#define NV_NOTIFY_STATE_STATUS_SHIFT 24 +#define NV_NOTIFY_STATE_STATUS_COMPLETED 0x00 +#define NV_NOTIFY_STATE_STATUS_IN_PROCESS 0x01 +#define NV_NOTIFY_STATE_ERROR_CODE_MASK 0x0000FFFF +#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT 0 + +#define NOTIFIER(__v) \ + NVPtr pNv = NVPTR(pScrn); \ + volatile uint32_t *__v = (void*)pNv->NotifierBlock + notifier->offset + +drm_nouveau_notifier_alloc_t * +NVNotifierAlloc(ScrnInfoPtr pScrn, uint32_t handle) +{ + NVPtr pNv = NVPTR(pScrn); + drm_nouveau_notifier_alloc_t *notifier; + int ret; + + notifier = xcalloc(1, sizeof(*notifier)); + if (!notifier) { + NVNotifierDestroy(pScrn, notifier); + return NULL; + } + + notifier->channel = pNv->fifo.channel; + notifier->handle = handle; + notifier->count = 1; + ret = drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_NOTIFIER_ALLOC, + notifier, sizeof(*notifier)); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to create notifier 0x%08x: %d\n", + handle, ret); + NVNotifierDestroy(pScrn, notifier); + return NULL; + } + + return notifier; +} + +void +NVNotifierDestroy(ScrnInfoPtr pScrn, drm_nouveau_notifier_alloc_t *notifier) +{ + if (notifier) { + /*XXX: destroy notifier object */ + xfree(notifier); + } +} + +void +NVNotifierReset(ScrnInfoPtr pScrn, drm_nouveau_notifier_alloc_t *notifier) +{ + NOTIFIER(n); + + n[NV_NOTIFY_TIME_0 /4] = + n[NV_NOTIFY_TIME_1 /4] = + n[NV_NOTIFY_RETURN_VALUE/4] = 0; + n[NV_NOTIFY_STATE /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS << + NV_NOTIFY_STATE_STATUS_SHIFT); +} + +uint32_t +NVNotifierStatus(ScrnInfoPtr pScrn, drm_nouveau_notifier_alloc_t *notifier) +{ + NOTIFIER(n); + + return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT; +} + +uint32_t +NVNotifierErrorCode(ScrnInfoPtr pScrn, drm_nouveau_notifier_alloc_t *notifier) +{ + NOTIFIER(n); + + return n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK; +} + +uint32_t +NVNotifierReturnVal(ScrnInfoPtr pScrn, drm_nouveau_notifier_alloc_t *notifier) +{ + NOTIFIER(n); + + return n[NV_NOTIFY_RETURN_VALUE/4]; +} + +Bool +NVNotifierWaitStatus(ScrnInfoPtr pScrn, drm_nouveau_notifier_alloc_t *notifier, + unsigned int status, unsigned int timeout) +{ + NOTIFIER(n); + unsigned int t_start, time = 0; + + t_start = GetTimeInMillis(); + while (time <= timeout) { +#if 0 + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "N(0x%08x)/%d = 0x%08x/0x%08x/0x%08x/0x%08x\n", + notifier->handle, time, n[0], n[1], n[2], n[3]); +#endif + if (n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Notifier returned error: 0x%04x\n", + NVNotifierErrorCode(pScrn, notifier)); + return FALSE; + } + + if ((n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT) + == status) + return TRUE; + + if (timeout) + time = GetTimeInMillis() - t_start; + } + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Notifier (0x%08x) timeout!\n", notifier->handle); + return FALSE; +} + diff --git a/src/nv_proto.h b/src/nv_proto.h index d40a1cf..a5da5f3 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -19,6 +19,16 @@ Bool NVI2CInit(ScrnInfoPtr pScrn); NVAllocRec *NVAllocateMemory(NVPtr pNv, int type, int size); void NVFreeMemory(NVPtr pNv, NVAllocRec *mem); +/* in nv_notifier.c */ +drm_nouveau_notifier_alloc_t *NVNotifierAlloc(ScrnInfoPtr, uint32_t handle); +void NVNotifierDestroy(ScrnInfoPtr, drm_nouveau_notifier_alloc_t *); +void NVNotifierReset(ScrnInfoPtr, drm_nouveau_notifier_alloc_t *); +uint32_t NVNotifierStatus(ScrnInfoPtr, drm_nouveau_notifier_alloc_t *); +uint32_t NVNotifierErrorCode(ScrnInfoPtr, drm_nouveau_notifier_alloc_t *); +uint32_t NVNotifierReturnVal(ScrnInfoPtr, drm_nouveau_notifier_alloc_t *); +Bool NVNotifierWaitStatus(ScrnInfoPtr, drm_nouveau_notifier_alloc_t *, + uint32_t status, uint32_t timeout); + /* in nv_dri.c */ unsigned int NVDRMGetParam(NVPtr pNv, unsigned int param); Bool NVDRMSetParam(NVPtr pNv, unsigned int param, unsigned int value); @@ -56,12 +66,6 @@ void NVDmaWait(NVPtr pNv, int size); void NVDoSync(NVPtr pNv); void NVSync(ScrnInfoPtr pScrn); void NVResetGraphics(ScrnInfoPtr pScrn); -Bool NVDmaCreateDMAObject(NVPtr pNv, uint32_t handle, int class, int target, - CARD32 base_address, CARD32 size, int access); -Bool NVDmaCreateDMAObjectFromMem(NVPtr pNv, uint32_t handle, int class, - NVAllocRec *mem, int access); -NVAllocRec *NVDmaCreateNotifier(NVPtr pNv, int handle); -Bool NVDmaWaitForNotifier(NVPtr pNv, void *notifier); Bool NVDmaCreateContextObject(NVPtr pNv, int handle, int class); Bool NVInitDma(ScrnInfoPtr pScrn); diff --git a/src/nv_type.h b/src/nv_type.h index ec54053..c56c9f5 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -233,7 +233,9 @@ typedef struct _NVRec { int IRQ; Bool LockedUp; - NVAllocRec * Notifier0; + volatile void * NotifierBlock; + drm_nouveau_notifier_alloc_t *Notifier0; + drm_nouveau_fifo_alloc_t fifo; CARD32 dmaPut; CARD32 dmaCurrent; -- cgit v1.2.1 From 35806975047aa8c0dbc059709bb823f475ee7368 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 24 Jun 2007 17:27:42 +1000 Subject: Wait on notifier instead of PGRAPH_STATUS When multiple channels are in use, PGRAPH_STATUS may report busy even if the ddx's channel is idle. --- src/nv_accel_common.c | 13 ++-- src/nv_dma.c | 62 ++++++++++++------- src/nv_dma.h | 2 +- src/nv_exa.c | 20 ++++--- src/nv_proto.h | 9 ++- src/nv_video.c | 162 +++++++++++++++++++++++++------------------------- src/nv_xaa.c | 4 +- 7 files changed, 149 insertions(+), 123 deletions(-) diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index f04d507..e1c0f8e 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -17,8 +17,10 @@ NVAccelInitNullObject(ScrnInfoPtr pScrn) } uint32_t -NVAccelGetPixmapOffset(NVPtr pNv, PixmapPtr pPix) +NVAccelGetPixmapOffset(PixmapPtr pPix) { + ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); CARD32 offset; if (pPix->drawable.type == DRAWABLE_WINDOW) { @@ -123,14 +125,17 @@ NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPict, int *fmt_ret) } Bool -NVAccelSetCtxSurf2D(NVPtr pNv, PixmapPtr psPix, PixmapPtr pdPix, int format) +NVAccelSetCtxSurf2D(PixmapPtr psPix, PixmapPtr pdPix, int format) { + ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 4); NVDmaNext (pNv, format); NVDmaNext (pNv, ((uint32_t)exaGetPixmapPitch(pdPix) << 16) | (uint32_t)exaGetPixmapPitch(psPix)); - NVDmaNext (pNv, NVAccelGetPixmapOffset(pNv, psPix)); - NVDmaNext (pNv, NVAccelGetPixmapOffset(pNv, pdPix)); + NVDmaNext (pNv, NVAccelGetPixmapOffset(psPix)); + NVDmaNext (pNv, NVAccelGetPixmapOffset(pdPix)); return TRUE; } diff --git a/src/nv_dma.c b/src/nv_dma.c index a9d0127..6f66e9d 100644 --- a/src/nv_dma.c +++ b/src/nv_dma.c @@ -23,8 +23,9 @@ void NVDmaKickoffCallback(NVPtr pNv) */ #define SKIPS 8 -void NVDmaWait (NVPtr pNv, int size) +void NVDmaWait (ScrnInfoPtr pScrn, int size) { + NVPtr pNv = NVPTR(pScrn); int t_start; int dmaGet; @@ -43,7 +44,7 @@ void NVDmaWait (NVPtr pNv, int size) WRITE_PUT(pNv, SKIPS + 1); do { if (GetTimeInMillis() - t_start > 2000) - NVDoSync(pNv); + NVSync(pScrn); dmaGet = READ_GET(pNv); } while(dmaGet <= SKIPS); } @@ -55,7 +56,7 @@ void NVDmaWait (NVPtr pNv, int size) pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1; if (GetTimeInMillis() - t_start > 2000) - NVDoSync(pNv); + NVSync(pScrn); } } @@ -70,34 +71,51 @@ static void NVDumpLockupInfo(NVPtr pNv) xf86DrvMsg(0, X_INFO, "End of fifo dump\n"); } -void NVDoSync(NVPtr pNv) +static void +NVLockedUp(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + + /* avoid re-entering FatalError on shutdown */ + if (pNv->LockedUp) + return; + pNv->LockedUp = TRUE; + + NVDumpLockupInfo(pNv); + + FatalError("DMA queue hang: dmaPut=%x, current=%x, status=%x\n", + pNv->dmaPut, READ_GET(pNv), pNv->PGRAPH[NV_PGRAPH_STATUS/4]); +} + +void NVSync(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); int t_start, timeout = 2000; + if(pNv->NoAccel) + return; + if(pNv->DMAKickoffCallback) (*pNv->DMAKickoffCallback)(pNv); - t_start = GetTimeInMillis(); /* Wait for entire FIFO to be processed */ - while((GetTimeInMillis() - t_start) < timeout && (READ_GET(pNv) != pNv->dmaPut)); - /* Wait for PGRAPH to go completely idle */ - while((GetTimeInMillis() - t_start) < timeout && pNv->PGRAPH[NV_PGRAPH_STATUS/4]); - + t_start = GetTimeInMillis(); + while((GetTimeInMillis() - t_start) < timeout && + (READ_GET(pNv) != pNv->dmaPut)); if ((GetTimeInMillis() - t_start) >= timeout) { - if (pNv->LockedUp) - return; - NVDumpLockupInfo(pNv); - pNv->LockedUp = TRUE; /* avoid re-entering FatalError on shutdown */ - FatalError("DMA queue hang: dmaPut=%x, current=%x, status=%x\n", - pNv->dmaPut, READ_GET(pNv), pNv->PGRAPH[NV_PGRAPH_STATUS/4]); + NVLockedUp(pScrn); + return; } -} -void NVSync(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - if(pNv->NoAccel) return; - NVDoSync(pNv); + /* Wait for channel to go completely idle */ + NVNotifierReset(pScrn, pNv->Notifier0); + NVDmaStart(pNv, NvSubImageBlit, 0x104, 1); + NVDmaNext (pNv, 0); + NVDmaStart(pNv, NvSubImageBlit, 0x100, 1); + NVDmaNext (pNv, 0); + NVDmaKickoff(pNv); + if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, timeout)) + NVLockedUp(pScrn); } void NVResetGraphics(ScrnInfoPtr pScrn) @@ -116,7 +134,7 @@ void NVResetGraphics(ScrnInfoPtr pScrn) /* assert there's enough room for the skips */ if(pNv->dmaFree <= SKIPS) - NVDmaWait(pNv, SKIPS); + NVDmaWait(pScrn, SKIPS); for (i=0; idmaBase[i]=0; diff --git a/src/nv_dma.h b/src/nv_dma.h index 29695e2..d09b35f 100644 --- a/src/nv_dma.h +++ b/src/nv_dma.h @@ -100,7 +100,7 @@ enum DMASubchannel { #define NVDmaStart(pNv, subchannel, tag, size) do { \ if((pNv)->dmaFree <= (size)) \ - NVDmaWait(pNv, size); \ + NVDmaWait(pScrn, size); \ NVDEBUG("NVDmaStart: subc=%d, cmd=%x, num=%d\n", (subchannel), (tag), (size)); \ NVDmaNext(pNv, ((size) << 18) | ((subchannel) << 13) | (tag)); \ (pNv)->dmaFree -= ((size) + 1); \ diff --git a/src/nv_exa.c b/src/nv_exa.c index c01a4c6..39585e4 100644 --- a/src/nv_exa.c +++ b/src/nv_exa.c @@ -49,8 +49,10 @@ #include -static void setM2MFDirection(NVPtr pNv, int dir) +static void setM2MFDirection(ScrnInfoPtr pScrn, int dir) { + NVPtr pNv = NVPTR(pScrn); + if (pNv->M2MFDirection != dir) { NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2); NVDmaNext (pNv, dir ? NvDmaTT : NvDmaFB); @@ -112,7 +114,7 @@ static Bool NVExaPrepareSolid(PixmapPtr pPixmap, if (fmt == SURFACE_FORMAT_A8R8G8B8) fmt = 0xb; - if (!NVAccelSetCtxSurf2D(pNv, pPixmap, pPixmap, fmt)) + if (!NVAccelSetCtxSurf2D(pPixmap, pPixmap, fmt)) return FALSE; NVDmaStart(pNv, NvSubRectangle, RECT_FORMAT, 1); @@ -172,7 +174,7 @@ static Bool NVExaPrepareCopy(PixmapPtr pSrcPixmap, if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap, &fmt)) return FALSE; - if (!NVAccelSetCtxSurf2D(pNv, pSrcPixmap, pDstPixmap, fmt)) + if (!NVAccelSetCtxSurf2D(pSrcPixmap, pDstPixmap, fmt)) return FALSE; pNv->DMAKickoffCallback = NVDmaKickoffCallback; @@ -269,13 +271,13 @@ static Bool NVDownloadFromScreen(PixmapPtr pSrc, Bool ret = TRUE; pitch_in = exaGetPixmapPitch(pSrc); - offset_in = NVAccelGetPixmapOffset(pNv, pSrc); + offset_in = NVAccelGetPixmapOffset(pSrc); offset_in += y*pitch_in; offset_in += x * (pSrc->drawable.bitsPerPixel >> 3); max_lines = 65536/dst_pitch + 1; line_length = w * (pSrc->drawable.bitsPerPixel >> 3); - setM2MFDirection(pNv, 0); + setM2MFDirection(pScrn, 0); NVDEBUG("NVDownloadFromScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h); NVDEBUG(" pitch_in=%x dst_pitch=%x offset_in=%x", @@ -332,14 +334,14 @@ static Bool NVUploadToScreen(PixmapPtr pDst, #endif pitch_out = exaGetPixmapPitch(pDst); - offset_out = NVAccelGetPixmapOffset(pNv, pDst); + offset_out = NVAccelGetPixmapOffset(pDst); offset_out += y*pitch_out; offset_out += x * (pDst->drawable.bitsPerPixel >> 3); max_lines = 65536/src_pitch + 1; line_length = w * (pDst->drawable.bitsPerPixel >> 3); - setM2MFDirection(pNv, 1); + setM2MFDirection(pScrn, 1); NVDEBUG("NVUploadToScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h); while (h > 0) { @@ -437,7 +439,7 @@ static Bool NVPrepareComposite(int op, if (!NVAccelGetCtxSurf2DFormatFromPicture(pDstPicture, &dstFormat)) return FALSE; - if (!NVAccelSetCtxSurf2D(pNv, pDst, pDst, dstFormat)) + if (!NVAccelSetCtxSurf2D(pDst, pDst, dstFormat)) return FALSE; NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 2); @@ -450,7 +452,7 @@ static Bool NVPrepareComposite(int op, src_pitch = exaGetPixmapPitch(pSrc) | (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER << 16) | (STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE << 24); - src_offset = NVAccelGetPixmapOffset(pNv, pSrc); + src_offset = NVAccelGetPixmapOffset(pSrc); return TRUE; } diff --git a/src/nv_proto.h b/src/nv_proto.h index a5da5f3..fcf487f 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -5,10 +5,10 @@ /* in nv_accel_common.c */ Bool NVAccelCommonInit(ScrnInfoPtr pScrn); -uint32_t NVAccelGetPixmapOffset(NVPtr pNv, PixmapPtr pPix); +uint32_t NVAccelGetPixmapOffset(PixmapPtr pPix); Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret); Bool NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPix, int *fmt_ret); -Bool NVAccelSetCtxSurf2D(NVPtr pNv, PixmapPtr psPix, PixmapPtr pdPix, int fmt); +Bool NVAccelSetCtxSurf2D(PixmapPtr psPix, PixmapPtr pdPix, int fmt); /* in nv_driver.c */ Bool NVSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); @@ -62,8 +62,7 @@ Bool NVCursorInit(ScreenPtr pScreen); /* in nv_dma.c */ void NVDmaKickoff(NVPtr pNv); void NVDmaKickoffCallback(NVPtr pNv); -void NVDmaWait(NVPtr pNv, int size); -void NVDoSync(NVPtr pNv); +void NVDmaWait(ScrnInfoPtr pScrn, int size); void NVSync(ScrnInfoPtr pScrn); void NVResetGraphics(ScrnInfoPtr pScrn); Bool NVDmaCreateContextObject(NVPtr pNv, int handle, int class); @@ -71,7 +70,7 @@ Bool NVInitDma(ScrnInfoPtr pScrn); /* in nv_xaa.c */ Bool NVXaaInit(ScreenPtr pScreen); -void NVWaitVSync(NVPtr pNv); +void NVWaitVSync(ScrnInfoPtr pScrn); void NVSetRopSolid(ScrnInfoPtr pScrn, CARD32 rop, CARD32 planemask); /* in nv_exa.c */ diff --git a/src/nv_video.c b/src/nv_video.c index 3865142..d8622a5 100644 --- a/src/nv_video.c +++ b/src/nv_video.c @@ -141,9 +141,9 @@ static XF86ImageRec NVImages[NUM_IMAGES_ALL] = }; static void -NVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv) +NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); pPriv->brightness = 0; pPriv->contrast = 4096; @@ -157,9 +157,9 @@ NVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv) void -NVResetVideo (ScrnInfoPtr pScrnInfo) +NVResetVideo (ScrnInfoPtr pScrn) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); int satSine, satCosine; double angle; @@ -187,9 +187,9 @@ NVResetVideo (ScrnInfoPtr pScrnInfo) static void -NVStopOverlay (ScrnInfoPtr pScrnInfo) +NVStopOverlay (ScrnInfoPtr pScrn) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1); } @@ -215,9 +215,9 @@ NVAllocateOverlayMemory(ScrnInfoPtr pScrn, NVAllocRec *mem, int size) } static void -NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo) +NVFreeOverlayMemory(ScrnInfoPtr pScrn) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); if(pPriv->video_mem) { @@ -228,9 +228,9 @@ NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo) static void -NVFreeBlitMemory(ScrnInfoPtr pScrnInfo) +NVFreeBlitMemory(ScrnInfoPtr pScrn) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv); if(pPriv->video_mem) { @@ -240,14 +240,14 @@ NVFreeBlitMemory(ScrnInfoPtr pScrnInfo) } static void -NVVideoTimerCallback(ScrnInfoPtr pScrnInfo, Time currentTime) +NVVideoTimerCallback(ScrnInfoPtr pScrn, Time currentTime) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pOverPriv = NULL; NVPortPrivPtr pBlitPriv = NULL; Bool needCallback = FALSE; - if (!pScrnInfo->vtSema) + if (!pScrn->vtSema) return; if (pNv->overlayAdaptor) { @@ -265,13 +265,13 @@ NVVideoTimerCallback(ScrnInfoPtr pScrnInfo, Time currentTime) if (pOverPriv) { if (pOverPriv->videoTime < currentTime) { if (pOverPriv->videoStatus & OFF_TIMER) { - NVStopOverlay(pScrnInfo); + NVStopOverlay(pScrn); pOverPriv->videoStatus = FREE_TIMER; pOverPriv->videoTime = currentTime + FREE_DELAY; needCallback = TRUE; } else if (pOverPriv->videoStatus & FREE_TIMER) { - NVFreeOverlayMemory(pScrnInfo); + NVFreeOverlayMemory(pScrn); pOverPriv->videoStatus = 0; } } else { @@ -281,7 +281,7 @@ NVVideoTimerCallback(ScrnInfoPtr pScrnInfo, Time currentTime) if (pBlitPriv) { if (pBlitPriv->videoTime < currentTime) { - NVFreeBlitMemory(pScrnInfo); + NVFreeBlitMemory(pScrn); pBlitPriv->videoStatus = 0; } else { needCallback = TRUE; @@ -292,7 +292,7 @@ NVVideoTimerCallback(ScrnInfoPtr pScrnInfo, Time currentTime) } static void -NVPutOverlayImage(ScrnInfoPtr pScrnInfo, int offset, int id, +NVPutOverlayImage(ScrnInfoPtr pScrn, int offset, int id, int dstPitch, BoxPtr dstBox, int x1, int y1, int x2, int y2, short width, short height, @@ -300,17 +300,17 @@ NVPutOverlayImage(ScrnInfoPtr pScrnInfo, int offset, int id, short drw_w, short drw_h, RegionPtr clipBoxes) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); int buffer = pPriv->currentBuffer; /* paint the color key */ if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L || - !REGION_EQUAL(pScrnInfo->pScreen, &pPriv->clip, clipBoxes))) { + !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) { /* we always paint V4L's color key */ if (!pPriv->grabbedByV4L) - REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes); - xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes); + REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); + xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); } if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) { @@ -359,7 +359,7 @@ extern void exaMoveInPixmap(PixmapPtr pPixmap); #endif static void -NVPutBlitImage(ScrnInfoPtr pScrnInfo, int src_offset, int id, +NVPutBlitImage(ScrnInfoPtr pScrn, int src_offset, int id, int src_pitch, BoxPtr dstBox, int x1, int y1, int x2, int y2, short width, short height, @@ -368,7 +368,7 @@ NVPutBlitImage(ScrnInfoPtr pScrnInfo, int src_offset, int id, RegionPtr clipBoxes, DrawablePtr pDraw) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv); BoxPtr pbox; int nbox; @@ -377,7 +377,7 @@ NVPutBlitImage(ScrnInfoPtr pScrnInfo, int src_offset, int id, CARD32 src_point, src_format; if (pNv->useEXA) { - ScreenPtr pScreen = pScrnInfo->pScreen; + ScreenPtr pScreen = pScrn->pScreen; PixmapPtr pPix = exaGetDrawablePixmap(pDraw); int dst_format; @@ -392,18 +392,18 @@ NVPutBlitImage(ScrnInfoPtr pScrnInfo, int src_offset, int id, * with BadAlloc would be better? */ if (!exaPixmapIsOffscreen(pPix)) { - xf86DrvMsg(pScrnInfo->scrnIndex, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XV: couldn't move dst surface into vram\n"); pPix = pScreen->GetScreenPixmap(pScreen); } NVAccelGetCtxSurf2DFormatFromPixmap(pPix, &dst_format); - NVAccelSetCtxSurf2D(pNv, pPix, pPix, dst_format); + NVAccelSetCtxSurf2D(pPix, pPix, dst_format); #ifdef COMPOSITE /* Adjust coordinates if drawing to an offscreen pixmap */ if (pPix->screen_x || pPix->screen_y) { - REGION_TRANSLATE(pScrnInfo->pScreen, clipBoxes, + REGION_TRANSLATE(pScrn->pScreen, clipBoxes, -pPix->screen_x, -pPix->screen_y); dstBox->x1 -= pPix->screen_x; @@ -450,7 +450,7 @@ NVPutBlitImage(ScrnInfoPtr pScrnInfo, int src_offset, int id, if(pPriv->SyncToVBlank) { NVDmaKickoff(pNv); - NVWaitVSync(pNv); + NVWaitVSync(pScrn); } if(pNv->BlendingPossible) { @@ -494,7 +494,7 @@ NVPutBlitImage(ScrnInfoPtr pScrnInfo, int src_offset, int id, NVDmaKickoff(pNv); if (pNv->useEXA) - exaMarkSync(pScrnInfo->pScreen); + exaMarkSync(pScrn->pScreen); else SET_SYNC_FLAG(pNv->AccelInfoRec); @@ -507,19 +507,19 @@ NVPutBlitImage(ScrnInfoPtr pScrnInfo, int src_offset, int id, * StopVideo */ static void -NVStopOverlayVideo(ScrnInfoPtr pScrnInfo, pointer data, Bool Exit) +NVStopOverlayVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = (NVPortPrivPtr)data; if(pPriv->grabbedByV4L) return; - REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); if(Exit) { if (pPriv->videoStatus & CLIENT_VIDEO_ON) - NVStopOverlay(pScrnInfo); - NVFreeOverlayMemory(pScrnInfo); + NVStopOverlay(pScrn); + NVFreeOverlayMemory(pScrn); pPriv->videoStatus = 0; } else { if (pPriv->videoStatus & CLIENT_VIDEO_ON) { @@ -531,12 +531,12 @@ NVStopOverlayVideo(ScrnInfoPtr pScrnInfo, pointer data, Bool Exit) } static void -NVStopBlitVideo(ScrnInfoPtr pScrnInfo, pointer data, Bool Exit) +NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit) { } static int -NVSetOverlayPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, +NVSetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { NVPortPrivPtr pPriv = (NVPortPrivPtr)data; @@ -569,7 +569,7 @@ NVSetOverlayPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, } else if (attribute == xvColorKey) { pPriv->colorKey = value; - REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } else if (attribute == xvAutopaintColorKey) { if ((value < 0) || (value > 1)) @@ -582,17 +582,17 @@ NVSetOverlayPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, pPriv->iturbt_709 = value; } else if (attribute == xvSetDefaults) { - NVSetPortDefaults(pScrnInfo, pPriv); + NVSetPortDefaults(pScrn, pPriv); } else return BadMatch; - NVResetVideo(pScrnInfo); + NVResetVideo(pScrn); return Success; } static int -NVGetOverlayPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, +NVGetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data) { NVPortPrivPtr pPriv = (NVPortPrivPtr)data; @@ -620,11 +620,11 @@ NVGetOverlayPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, } static int -NVSetBlitPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, +NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { NVPortPrivPtr pPriv = (NVPortPrivPtr)data; - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) { if ((value < 0) || (value > 1)) @@ -640,7 +640,7 @@ NVSetBlitPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, } static int -NVGetBlitPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, +NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data) { NVPortPrivPtr pPriv = (NVPortPrivPtr)data; @@ -658,7 +658,7 @@ NVGetBlitPortAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, * QueryBestSize */ static void -NVQueryBestSize(ScrnInfoPtr pScrnInfo, Bool motion, +NVQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, @@ -797,7 +797,7 @@ NVCopyDataRGB(unsigned char *src, unsigned char *dst, * PutImage */ static int -NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y, +NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y, short src_w, short src_h, short drw_w, short drw_h, @@ -811,7 +811,7 @@ NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y, ) { NVPortPrivPtr pPriv = (NVPortPrivPtr)data; - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); INT32 xa, xb, ya, yb; unsigned char *dst_start; int newSize, offset, s2offset, s3offset; @@ -857,13 +857,13 @@ NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y, return Success; if (!pPriv->blitter) { - dstBox.x1 -= pScrnInfo->frameX0; - dstBox.x2 -= pScrnInfo->frameX0; - dstBox.y1 -= pScrnInfo->frameY0; - dstBox.y2 -= pScrnInfo->frameY0; + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; } - bpp = pScrnInfo->bitsPerPixel >> 3; + bpp = pScrn->bitsPerPixel >> 3; switch(id) { case FOURCC_YV12: @@ -891,7 +891,7 @@ NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y, if (pPriv->doubleBuffer) newSize <<= 1; - pPriv->video_mem = NVAllocateOverlayMemory(pScrnInfo, pPriv->video_mem, + pPriv->video_mem = NVAllocateOverlayMemory(pScrn, pPriv->video_mem, newSize); if (!pPriv->video_mem) return BadAlloc; @@ -929,7 +929,7 @@ NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y, bottom = (yb + 0x0001ffff) >> 16; if (bottom > height) bottom = height; - if(pPriv->blitter) NVSync(pScrnInfo); + if(pPriv->blitter) NVSync(pScrn); switch(id) { case FOURCC_YV12: @@ -984,14 +984,14 @@ NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y, if (!skip) { if (pPriv->blitter) { - NVPutBlitImage(pScrnInfo, offset, id, + NVPutBlitImage(pScrn, offset, id, dstPitch, &dstBox, xa, ya, xb, yb, width, height, src_w, src_h, drw_w, drw_h, clipBoxes, pDraw); } else { - NVPutOverlayImage(pScrnInfo, offset, id, + NVPutOverlayImage(pScrn, offset, id, dstPitch, &dstBox, xa, ya, xb, yb, width, height, @@ -1007,7 +1007,7 @@ NVPutImage(ScrnInfoPtr pScrnInfo, short src_x, short src_y, * QueryImageAttributes */ static int -NVQueryImageAttributes(ScrnInfoPtr pScrnInfo, int id, +NVQueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets) { @@ -1066,15 +1066,15 @@ NVQueryImageAttributes(ScrnInfoPtr pScrnInfo, int id, static int -NVAllocSurface(ScrnInfoPtr pScrnInfo, int id, +NVAllocSurface(ScrnInfoPtr pScrn, int id, unsigned short w, unsigned short h, XF86SurfacePtr surface) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); int size, bpp; - bpp = pScrnInfo->bitsPerPixel >> 3; + bpp = pScrn->bitsPerPixel >> 3; if (pPriv->grabbedByV4L) return BadAlloc; @@ -1086,7 +1086,7 @@ NVAllocSurface(ScrnInfoPtr pScrnInfo, int id, pPriv->pitch = ((w << 1) + 63) & ~63; size = h * pPriv->pitch / bpp; - pPriv->video_mem = NVAllocateOverlayMemory(pScrnInfo, + pPriv->video_mem = NVAllocateOverlayMemory(pScrn, pPriv->video_mem, size); if (!pPriv->video_mem) @@ -1096,16 +1096,16 @@ NVAllocSurface(ScrnInfoPtr pScrnInfo, int id, surface->width = w; surface->height = h; - surface->pScrn = pScrnInfo; + surface->pScrn = pScrn; surface->pitches = &pPriv->pitch; surface->offsets = &pPriv->offset; surface->devPrivate.ptr = (pointer)pPriv; surface->id = id; /* grab the video */ - NVStopOverlay(pScrnInfo); + NVStopOverlay(pScrn); pPriv->videoStatus = 0; - REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip); + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); pPriv->grabbedByV4L = TRUE; return Success; @@ -1139,22 +1139,22 @@ NVFreeSurface(XF86SurfacePtr surface) } static int -NVGetSurfaceAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, INT32 *value) +NVGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); - return NVGetOverlayPortAttribute(pScrnInfo, attribute, + return NVGetOverlayPortAttribute(pScrn, attribute, value, (pointer)pPriv); } static int -NVSetSurfaceAttribute(ScrnInfoPtr pScrnInfo, Atom attribute, INT32 value) +NVSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value) { - NVPtr pNv = NVPTR(pScrnInfo); + NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); - return NVSetOverlayPortAttribute(pScrnInfo, attribute, + return NVSetOverlayPortAttribute(pScrn, attribute, value, (pointer)pPriv); } @@ -1166,7 +1166,7 @@ NVDisplaySurface(XF86SurfacePtr surface, short drw_w, short drw_h, RegionPtr clipBoxes) { - ScrnInfoPtr pScrnInfo = surface->pScrn; + ScrnInfoPtr pScrn = surface->pScrn; NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr); INT32 xa, xb, ya, yb; BoxRec dstBox; @@ -1194,14 +1194,14 @@ NVDisplaySurface(XF86SurfacePtr surface, surface->width, surface->height)) return Success; - dstBox.x1 -= pScrnInfo->frameX0; - dstBox.x2 -= pScrnInfo->frameX0; - dstBox.y1 -= pScrnInfo->frameY0; - dstBox.y2 -= pScrnInfo->frameY0; + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; pPriv->currentBuffer = 0; - NVPutOverlayImage(pScrnInfo, surface->offsets[0], surface->id, + NVPutOverlayImage(pScrn, surface->offsets[0], surface->id, surface->pitches[0], &dstBox, xa, ya, xb, yb, surface->width, surface->height, src_w, src_h, drw_w, drw_h, clipBoxes); @@ -1212,8 +1212,8 @@ NVDisplaySurface(XF86SurfacePtr surface, static XF86VideoAdaptorPtr NVSetupBlitVideo (ScreenPtr pScreen) { - ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum]; - NVPtr pNv = NVPTR(pScrnInfo); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); XF86VideoAdaptorPtr adapt; NVPortPrivPtr pPriv; int i; @@ -1274,8 +1274,8 @@ NVSetupBlitVideo (ScreenPtr pScreen) static XF86VideoAdaptorPtr NV10SetupOverlayVideo(ScreenPtr pScreen) { - ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum]; - NVPtr pNv = NVPTR(pScrnInfo); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); XF86VideoAdaptorPtr adapt; NVPortPrivPtr pPriv; @@ -1318,7 +1318,7 @@ NV10SetupOverlayVideo(ScreenPtr pScreen) pPriv->grabbedByV4L = FALSE; pPriv->blitter = FALSE; - NVSetPortDefaults (pScrnInfo, pPriv); + NVSetPortDefaults (pScrn, pPriv); /* gotta uninit this someplace */ REGION_NULL(pScreen, &pPriv->clip); @@ -1335,7 +1335,7 @@ NV10SetupOverlayVideo(ScreenPtr pScreen) xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); xvITURBT709 = MAKE_ATOM("XV_ITURBT_709"); - NVResetVideo(pScrnInfo); + NVResetVideo(pScrn); return adapt; } diff --git a/src/nv_xaa.c b/src/nv_xaa.c index 0d07e70..9c32910 100644 --- a/src/nv_xaa.c +++ b/src/nv_xaa.c @@ -106,8 +106,10 @@ static const int NVPatternROP[16] = }; void -NVWaitVSync(NVPtr pNv) +NVWaitVSync(ScrnInfoPtr pScrn) { + NVPtr pNv = NVPTR(pScrn); + NVDmaStart(pNv, 5, 0x0000012C, 1); NVDmaNext (pNv, 0); NVDmaStart(pNv, 5, 0x00000134, 1); -- cgit v1.2.1 From 2e2e95fc3b650ca633294bf4c11c9ba28f45b743 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 24 Jun 2007 17:34:10 +1000 Subject: Slightly saner UploadToScreen implementation --- src/nv_exa.c | 104 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/src/nv_exa.c b/src/nv_exa.c index 39585e4..3096e29 100644 --- a/src/nv_exa.c +++ b/src/nv_exa.c @@ -318,65 +318,85 @@ error: return ret; } -static Bool NVUploadToScreen(PixmapPtr pDst, - int x, int y, int w, int h, - char *src, int src_pitch) +Bool +NVAccelUploadM2MF(ScrnInfoPtr pScrn, uint64_t dst_offset, const char *src, + int dst_pitch, int src_pitch, + int line_len, int line_count) { - ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); - CARD32 offset_out, pitch_out, max_lines, line_length; - Bool ret = TRUE; -#if 0 - x = 0; - y = 0; - w = pDst->drawable.width; - h = pDst->drawable.height; -#endif - pitch_out = exaGetPixmapPitch(pDst); - offset_out = NVAccelGetPixmapOffset(pDst); - offset_out += y*pitch_out; - offset_out += x * (pDst->drawable.bitsPerPixel >> 3); + setM2MFDirection(pScrn, 1); - max_lines = 65536/src_pitch + 1; - line_length = w * (pDst->drawable.bitsPerPixel >> 3); + while (line_count) { + char *dst = pNv->AGPScratch->map; + int lc, i; - setM2MFDirection(pScrn, 1); + /* Determine max amount of data we can DMA at once */ + if (line_count * line_len <= pNv->AGPScratch->size) { + lc = line_count; + } else { + lc = pNv->AGPScratch->size / line_len; + if (lc > line_count) + lc = line_count; + } + /*XXX: and hw limitations? */ - NVDEBUG("NVUploadToScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h); - while (h > 0) { - NVDEBUG(" max_lines=%d, h=%d\n", max_lines, h); - int nlines = h > max_lines ? max_lines : h; + /* Upload to GART */ + if (src_pitch == line_len) { + memcpy(dst, src, src_pitch * lc); + } else { + for (i = 0; i < lc; i++) { + memcpy(dst, src, line_len); + src += src_pitch; + dst += line_len; + } + } - /* reset the notification object */ + /* DMA to VRAM */ NVNotifierReset(pScrn, pNv->Notifier0); - - memcpy(pNv->AGPScratch->map, src, nlines*src_pitch); - NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_NOTIFY, 1); + NVDmaStart(pNv, NvSubMemFormat, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); NVDmaNext (pNv, 0); - NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_OFFSET_IN, 8); + NVDmaStart(pNv, NvSubMemFormat, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); NVDmaNext (pNv, (uint32_t)pNv->AGPScratch->offset); - NVDmaNext (pNv, offset_out); - NVDmaNext (pNv, src_pitch); - NVDmaNext (pNv, pitch_out); - NVDmaNext (pNv, line_length); - NVDmaNext (pNv, nlines); - NVDmaNext (pNv, 0x101); + NVDmaNext (pNv, (uint32_t)dst_offset); + NVDmaNext (pNv, line_len); + NVDmaNext (pNv, dst_pitch); + NVDmaNext (pNv, line_len); + NVDmaNext (pNv, lc); + NVDmaNext (pNv, (1<<8)|1); NVDmaNext (pNv, 0); NVDmaKickoff(pNv); - if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000)) { - ret = FALSE; - goto error; - } + if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0)) + return FALSE; - h -= nlines; - offset_out += nlines*pitch_out; - src += nlines*src_pitch; + line_count -= lc; } -error: + return TRUE; +} + +static Bool NVUploadToScreen(PixmapPtr pDst, + int x, int y, int w, int h, + char *src, int src_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + int dst_offset, dst_pitch, bpp; + Bool ret; + + dst_offset = NVAccelGetPixmapOffset(pDst); + dst_pitch = exaGetPixmapPitch(pDst); + bpp = pDst->drawable.bitsPerPixel >> 3; + + if (1) { + dst_offset += (y * dst_pitch) + (x * bpp); + ret = NVAccelUploadM2MF(pScrn, dst_offset, src, + dst_pitch, src_pitch, + w * bpp, h); + } exaMarkSync(pDst->drawable.pScreen); return ret; } -- cgit v1.2.1 From 824331e3fce36098e8dec31746204f7c13038abb Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 24 Jun 2007 17:48:33 +1000 Subject: Implement NV40 EXA composite hooks with 3D engine. Named NV30EXA, but won't work on NV30 just yet. This should change at some point in the future. Will likely break non-voodoo'd NV4X cards (if the latest drm changes didn't already break them). Use EXANoComposite xorg.conf option to disable the hook if that's the case. --- src/Makefile.am | 3 +- src/nv30_exa.c | 700 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/nv_accel_common.c | 9 + src/nv_dma.h | 10 +- src/nv_exa.c | 24 +- src/nv_proto.h | 8 + src/nv_shaders.h | 102 ++++++++ 7 files changed, 842 insertions(+), 14 deletions(-) create mode 100644 src/nv30_exa.c create mode 100644 src/nv_shaders.h diff --git a/src/Makefile.am b/src/Makefile.am index 783a284..7e4f5b1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,7 +53,8 @@ nouveau_drv_la_SOURCES = \ nv_shadow.c \ nv_type.h \ nv_video.c \ - nv_xaa.c + nv_xaa.c \ + nv30_exa.c #riva128_la_LTLIBRARIES = riva128.la #riva128_la_LDFLAGS = -module -avoid-version diff --git a/src/nv30_exa.c b/src/nv30_exa.c new file mode 100644 index 0000000..66901d3 --- /dev/null +++ b/src/nv30_exa.c @@ -0,0 +1,700 @@ +#include "nv_include.h" +#include "nv_shaders.h" + +#define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2F_X(d) (0x00001880 + d * 0x0008) +#define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2F_Y(d) (0x00001884 + d * 0x0008) +#define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2I(d) (0x00001900 + d * 0x0004) + +typedef struct nv_pict_surface_format { + int pict_fmt; + uint32_t card_fmt; +} nv_pict_surface_format_t; + +typedef struct nv_pict_texture_format { + int pict_fmt; + uint32_t card_fmt; + uint32_t card_swz; +} nv_pict_texture_format_t; + +typedef struct nv_pict_op { + Bool src_alpha; + Bool dst_alpha; + uint32_t src_card_op; + uint32_t dst_card_op; +} nv_pict_op_t; + +typedef struct nv30_exa_state { + Bool have_mask; + + struct { + PictTransformPtr transform; + float width; + float height; + } unit[2]; +} nv30_exa_state_t; +static nv30_exa_state_t exa_state; +#define NV30EXA_STATE nv30_exa_state_t *state = &exa_state + +static nv_pict_surface_format_t +NV30SurfaceFormat[] = { + { PICT_a8r8g8b8 , 0x148 }, + { PICT_x8r8g8b8 , 0x145 }, + { PICT_r5g6b5 , 0x143 }, +// { PICT_a8 , 0x149 }, + { -1, ~0 } +}; + +static nv_pict_surface_format_t * +NV30_GetPictSurfaceFormat(int format) +{ + int i = 0; + + while (NV30SurfaceFormat[i].pict_fmt != -1) { + if (NV30SurfaceFormat[i].pict_fmt == format) + return &NV30SurfaceFormat[i]; + i++; + } + + return NULL; +} + + +/* should be in nouveau_reg.h at some point.. */ +#define NV30TCL_TX_SWIZZLE_UNIT_S0_X_SHIFT 14 +#define NV30TCL_TX_SWIZZLE_UNIT_S0_X_ZERO 0 +#define NV30TCL_TX_SWIZZLE_UNIT_S0_X_ONE 1 +#define NV30TCL_TX_SWIZZLE_UNIT_S0_X_S1 2 +#define NV30TCL_TX_SWIZZLE_UNIT_S0_Y_SHIFT 12 +#define NV30TCL_TX_SWIZZLE_UNIT_S0_Z_SHIFT 10 +#define NV30TCL_TX_SWIZZLE_UNIT_S0_W_SHIFT 8 +#define NV30TCL_TX_SWIZZLE_UNIT_S1_X_SHIFT 6 +#define NV30TCL_TX_SWIZZLE_UNIT_S1_X_X 3 +#define NV30TCL_TX_SWIZZLE_UNIT_S1_X_Y 2 +#define NV30TCL_TX_SWIZZLE_UNIT_S1_X_Z 1 +#define NV30TCL_TX_SWIZZLE_UNIT_S1_X_W 0 +#define NV30TCL_TX_SWIZZLE_UNIT_S1_Y_SHIFT 4 +#define NV30TCL_TX_SWIZZLE_UNIT_S1_Z_SHIFT 2 +#define NV30TCL_TX_SWIZZLE_UNIT_S1_W_SHIFT 0 + +#define _(r,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \ + { \ + PICT_##r, \ + (tf), \ + (NV30TCL_TX_SWIZZLE_UNIT_S0_X_##ts0x << NV30TCL_TX_SWIZZLE_UNIT_S0_X_SHIFT)|\ + (NV30TCL_TX_SWIZZLE_UNIT_S0_X_##ts0y << NV30TCL_TX_SWIZZLE_UNIT_S0_Y_SHIFT)|\ + (NV30TCL_TX_SWIZZLE_UNIT_S0_X_##ts0z << NV30TCL_TX_SWIZZLE_UNIT_S0_Z_SHIFT)|\ + (NV30TCL_TX_SWIZZLE_UNIT_S0_X_##ts0w << NV30TCL_TX_SWIZZLE_UNIT_S0_W_SHIFT)|\ + (NV30TCL_TX_SWIZZLE_UNIT_S1_X_##ts1x << NV30TCL_TX_SWIZZLE_UNIT_S1_X_SHIFT)|\ + (NV30TCL_TX_SWIZZLE_UNIT_S1_X_##ts1y << NV30TCL_TX_SWIZZLE_UNIT_S1_Y_SHIFT)|\ + (NV30TCL_TX_SWIZZLE_UNIT_S1_X_##ts1z << NV30TCL_TX_SWIZZLE_UNIT_S1_Z_SHIFT)|\ + (NV30TCL_TX_SWIZZLE_UNIT_S1_X_##ts1w << NV30TCL_TX_SWIZZLE_UNIT_S1_W_SHIFT)\ + } +static nv_pict_texture_format_t +NV30TextureFormat[] = { + _(a8r8g8b8, 0x85, S1, S1, S1, S1, X, Y, Z, W), + _(x8r8g8b8, 0x85, S1, S1, S1, ONE, X, Y, Z, W), + _(x8b8g8r8, 0x85, S1, S1, S1, ONE, Z, Y, X, W), + _(a1r5g5b5, 0x82, S1, S1, S1, S1, X, Y, Z, W), + _(x1r5g5b5, 0x82, S1, S1, S1, ONE, X, Y, Z, W), + _( r5g6b5, 0x84, S1, S1, S1, S1, X, Y, Z, W), + _( a8, 0x81, ZERO, ZERO, ZERO, S1, X, X, X, X), + { -1, ~0, ~0 } +}; + +static nv_pict_texture_format_t * +NV30_GetPictTextureFormat(int format) +{ + int i = 0; + + while (NV30TextureFormat[i].pict_fmt != -1) { + if (NV30TextureFormat[i].pict_fmt == format) + return &NV30TextureFormat[i]; + i++; + } + + return NULL; +} + +#define NV30_TCL_PRIMITIVE_3D_BF_ZERO 0x0000 +#define NV30_TCL_PRIMITIVE_3D_BF_ONE 0x0001 +#define NV30_TCL_PRIMITIVE_3D_BF_SRC_COLOR 0x0300 +#define NV30_TCL_PRIMITIVE_3D_BF_ONE_MINUS_SRC_COLOR 0x0301 +#define NV30_TCL_PRIMITIVE_3D_BF_SRC_ALPHA 0x0302 +#define NV30_TCL_PRIMITIVE_3D_BF_ONE_MINUS_SRC_ALPHA 0x0303 +#define NV30_TCL_PRIMITIVE_3D_BF_DST_ALPHA 0x0304 +#define NV30_TCL_PRIMITIVE_3D_BF_ONE_MINUS_DST_ALPHA 0x0305 +#define NV30_TCL_PRIMITIVE_3D_BF_DST_COLOR 0x0306 +#define NV30_TCL_PRIMITIVE_3D_BF_ONE_MINUS_DST_COLOR 0x0307 +#define NV30_TCL_PRIMITIVE_3D_BF_ALPHA_SATURATE 0x0308 +#define BF(bf) NV30_TCL_PRIMITIVE_3D_BF_##bf + +static nv_pict_op_t +NV30PictOp[] = { +/* Clear */ { 0, 0, BF( ZERO), BF( ZERO) }, +/* Src */ { 0, 0, BF( ONE), BF( ZERO) }, +/* Dst */ { 0, 0, BF( ZERO), BF( ONE) }, +/* Over */ { 1, 0, BF( ONE), BF(ONE_MINUS_SRC_ALPHA) }, +/* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ONE) }, +/* In */ { 0, 1, BF( DST_ALPHA), BF( ZERO) }, +/* InReverse */ { 1, 0, BF( ZERO), BF( SRC_ALPHA) }, +/* Out */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ZERO) }, +/* OutReverse */ { 1, 0, BF( ZERO), BF(ONE_MINUS_SRC_ALPHA) }, +/* Atop */ { 1, 1, BF( DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) }, +/* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF( SRC_ALPHA) }, +/* Xor */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) }, +/* Add */ { 0, 0, BF( ONE), BF( ONE) } +}; + +static nv_pict_op_t * +NV30_GetPictOpRec(int op) +{ + if (op >= PictOpSaturate) + return NULL; + return &NV30PictOp[op]; +} + +#if 0 +#define FALLBACK(fmt,args...) do { \ + ErrorF("FALLBACK %s:%d> " fmt, __func__, __LINE__, ##args); \ + return FALSE; \ +} while(0) +#else +#define FALLBACK(fmt,args...) do { \ + return FALSE; \ +} while(0) +#endif + +static void +NV30_LoadVtxProg(ScrnInfoPtr pScrn, nv_shader_t *shader) +{ + NVPtr pNv = NVPTR(pScrn); + static int next_hw_id = 0; + int i; + + if (!shader->hw_id) { + shader->hw_id = next_hw_id; + + NVDmaStart(pNv, NvSub3D, + NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID, 1); + NVDmaNext (pNv, (shader->hw_id)); + + for (i=0; isize; i+=4) { + NVDmaStart(pNv, NvSub3D, + NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, + 4); + NVDmaNext (pNv, shader->data[i + 0]); + NVDmaNext (pNv, shader->data[i + 1]); + NVDmaNext (pNv, shader->data[i + 2]); + NVDmaNext (pNv, shader->data[i + 3]); + next_hw_id++; + } + } + + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID, 1); + NVDmaNext (pNv, (shader->hw_id)); + + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_IN_REG, 2); + NVDmaNext (pNv, shader->card_priv.NV30VP.vp_in_reg); + NVDmaNext (pNv, shader->card_priv.NV30VP.vp_out_reg); +} + +static void +NV30_LoadFragProg(ScrnInfoPtr pScrn, nv_shader_t *shader) +{ + NVPtr pNv = NVPTR(pScrn); + static NVAllocRec *fp_mem = NULL; + static int next_hw_id_offset = 0; + + if (!fp_mem) { + fp_mem = NVAllocateMemory(pNv, NOUVEAU_MEM_FB, 0x1000); + if (!fp_mem) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't alloc fragprog buffer!\n"); + return; + } + } + + if (!shader->hw_id) { + memcpy(fp_mem->map + next_hw_id_offset, shader->data, + shader->size * + sizeof(uint32_t)); + + shader->hw_id = fp_mem->offset; + shader->hw_id += next_hw_id_offset; + + next_hw_id_offset += (shader->size * sizeof(uint32_t)); + next_hw_id_offset = (next_hw_id_offset + 63) & ~63; + } + + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1); + NVDmaNext (pNv, shader->hw_id | 1); + + if (pNv->Architecture == NV_30) { + NVDmaStart(pNv, NvSub3D, 0x1d60, 1); + NVDmaNext (pNv, 0); /* USES_KIL (1<<7) == 0 */ + NVDmaStart(pNv, NvSub3D, 0x1450, 1); + NVDmaNext (pNv, shader->card_priv.NV30FP.num_regs << 16); + } else { + NVDmaStart(pNv, NvSub3D, 0x1d60, 1); + NVDmaNext (pNv, (0<<7) /* !USES_KIL */ | + (shader->card_priv.NV30FP.num_regs << 24)); + } +} + +static void +NV30_SetupBlend(ScrnInfoPtr pScrn, nv_pict_op_t *blend, Bool dest_has_alpha, + Bool component_alpha) +{ + NVPtr pNv = NVPTR(pScrn); + uint32_t sblend, dblend; + + sblend = blend->src_card_op; + dblend = blend->dst_card_op; + + if (!dest_has_alpha && blend->dst_alpha) { + if (sblend == BF(DST_ALPHA)) + sblend = BF(ONE); + else if (sblend == BF(ONE_MINUS_DST_ALPHA)) + sblend = BF(ZERO); + } + + if (component_alpha && blend->src_alpha) { + if (dblend == BF(SRC_ALPHA)) + dblend = BF(SRC_COLOR); + else if (dblend == BF(ONE_MINUS_SRC_ALPHA)) + dblend = BF(ONE_MINUS_SRC_COLOR); + } + + if (sblend == BF(ONE) && dblend == BF(ZERO)) { + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1); + NVDmaNext (pNv, 0); + } else { + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 5); + NVDmaNext (pNv, 1); + NVDmaNext (pNv, (sblend << 16) | sblend); + NVDmaNext (pNv, (dblend << 16) | dblend); + NVDmaNext (pNv, 0x00000000); /* Blend colour */ + NVDmaNext (pNv, (0x8006 << 16) | 0x8006); /* FUNC_ADD, FUNC_ADD */ + } +} + +static Bool +NV30EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit) +{ + NVPtr pNv = NVPTR(pScrn); + nv_pict_texture_format_t *fmt; + uint32_t card_filter, card_repeat; + NV30EXA_STATE; + + fmt = NV30_GetPictTextureFormat(pPict->format); + if (!fmt) + return FALSE; + + if (pPict->repeat && pPict->repeatType == RepeatNormal) + card_repeat = 1; + else + card_repeat = 3; + + if (pPict->filter == PictFilterBilinear) + card_filter = 2; + else + card_filter = 1; + + NVDmaStart(pNv, NvSub3D, + NV30_TCL_PRIMITIVE_3D_TX_ADDRESS_UNIT(unit), 8); + NVDmaNext (pNv, NVAccelGetPixmapOffset(pPix)); + NVDmaNext (pNv, (2 << 4) /* 2D */ | + (fmt->card_fmt << 8) | + (1 << 13) /* NPOT */ | + (1<<16) /* 1 mipmap level */ | + (1<<0) /* NvDmaFB */ | + (1<<3) /* border disable? */); + NVDmaNext (pNv, (card_repeat << 0) /* S */ | + (card_repeat << 8) /* T */ | + (card_repeat << 16) /* R */); + NVDmaNext (pNv, 0x80000000); + NVDmaNext (pNv, fmt->card_swz); + NVDmaNext (pNv, (card_filter << 16) /* min */ | + (card_filter << 24) /* mag */ | + 0x3fd6 /* engine lock */); + NVDmaNext (pNv, (pPix->drawable.width << 16) | pPix->drawable.height); + NVDmaNext (pNv, 0); /* border ARGB */ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_TX_DEPTH_UNIT(unit), 1); + NVDmaNext (pNv, (1 << 20) /* depth */ | + (uint32_t)exaGetPixmapPitch(pPix)); + + state->unit[unit].width = (float)pPix->drawable.width; + state->unit[unit].height = (float)pPix->drawable.height; + state->unit[unit].transform = pPict->transform; + + return TRUE; +} + +static Bool +NV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PictFormatShort format) +{ + NVPtr pNv = NVPTR(pScrn); + nv_pict_surface_format_t *fmt; + + fmt = NV30_GetPictSurfaceFormat(format); + if (!fmt) { + ErrorF("AIII no format\n"); + return FALSE; + } + + NVDmaStart(pNv, NvSub3D, 0x208, 3); + NVDmaNext (pNv, fmt->card_fmt); + NVDmaNext (pNv, (uint32_t)exaGetPixmapPitch(pPix)); + NVDmaNext (pNv, NVAccelGetPixmapOffset(pPix)); + + return TRUE; +} + +static Bool +NV30EXACheckCompositeTexture(PicturePtr pPict) +{ + nv_pict_texture_format_t *fmt; + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + + if ((w > 4096) || (h>4096)) + FALLBACK("picture too large, %dx%d\n", w, h); + + fmt = NV30_GetPictTextureFormat(pPict->format); + if (!fmt) + FALLBACK("picture format 0x%08x not supported\n", + pPict->format); + + if (pPict->filter != PictFilterNearest && + pPict->filter != PictFilterBilinear) + FALLBACK("filter 0x%x not supported\n", pPict->filter); + + if (pPict->repeat && (pPict->repeat != RepeatNormal && + pPict->repeatType != RepeatNone)) + FALLBACK("repeat 0x%x not supported\n", pPict->repeatType); + + return TRUE; +} + +Bool +NV30EXACheckComposite(int op, PicturePtr psPict, + PicturePtr pmPict, + PicturePtr pdPict) +{ + nv_pict_surface_format_t *fmt; + nv_pict_op_t *opr; + + opr = NV30_GetPictOpRec(op); + if (!opr) + FALLBACK("unsupported blend op 0x%x\n", op); + + fmt = NV30_GetPictSurfaceFormat(pdPict->format); + if (!fmt) + FALLBACK("dst picture format 0x%08x not supported\n", + pdPict->format); + + if (!NV30EXACheckCompositeTexture(psPict)) + FALLBACK("src picture\n"); + if (pmPict) { + if (pmPict->componentAlpha && + PICT_FORMAT_RGB(pmPict->format) && + opr->src_alpha && opr->src_card_op != BF(ZERO)) + FALLBACK("mask CA + SA\n"); + if (!NV30EXACheckCompositeTexture(pmPict)) + FALLBACK("mask picture\n"); + } + + return TRUE; +} + +Bool +NV30EXAPrepareComposite(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); + nv_pict_op_t *blend; + NV30EXA_STATE; + + blend = NV30_GetPictOpRec(op); + + NV30_SetupBlend(pScrn, blend, PICT_FORMAT_A(pdPict->format), + (pmPict && pmPict->componentAlpha && + PICT_FORMAT_RGB(pmPict->format))); + + NV30_SetupSurface(pScrn, pdPix, pdPict->format); + NV30EXATexture(pScrn, psPix, psPict, 0); + + NV30_LoadVtxProg(pScrn, &nv40_vp_exa_render); + if (pmPict) { + NV30EXATexture(pScrn, pmPix, pmPict, 1); + + if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { + if (blend->src_alpha) + NV30_LoadFragProg(pScrn, &nv30_fp_composite_mask_sa_ca); + else + NV30_LoadFragProg(pScrn, &nv30_fp_composite_mask_ca); + } else { + NV30_LoadFragProg(pScrn, &nv30_fp_composite_mask); + } + + state->have_mask = TRUE; + } else { + NV30_LoadFragProg(pScrn, &nv30_fp_pass_tex0); + + state->have_mask = FALSE; + } + + /* Appears to be some kind of cache flush, needed here at least + * sometimes.. funky text rendering otherwise :) + */ + NVDmaStart(pNv, NvSub3D, 0x1fd8, 1); + NVDmaNext (pNv, 2); + NVDmaStart(pNv, NvSub3D, 0x1fd8, 1); + NVDmaNext (pNv, 1); + + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_BEGIN_END, 1); + NVDmaNext (pNv, 8); /* GL_QUADS */ + + return TRUE; +} + +#define xFixedToFloat(v) \ + ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0)) + +static void +NV30EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy, + float *x_ret, float *y_ret) +{ + PictVector v; + + if (t) { + v.vector[0] = IntToxFixed(x); + v.vector[1] = IntToxFixed(y); + v.vector[2] = xFixed1; + PictureTransformPoint(t, &v); + *x_ret = xFixedToFloat(v.vector[0]) / sx; + *y_ret = xFixedToFloat(v.vector[1]) / sy; + } else { + *x_ret = (float)x / sx; + *y_ret = (float)y / sy; + } +} + +#define CV_OUTm(sx,sy,mx,my,dx,dy) do { \ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2F_X(8), 4); \ + NVDmaFloat(pNv, (sx)); NVDmaFloat(pNv, (sy)); \ + NVDmaFloat(pNv, (mx)); NVDmaFloat(pNv, (my)); \ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2I(0), 1); \ + NVDmaNext (pNv, ((dy)<<16)|(dx)); \ +} while(0) +#define CV_OUT(sx,sy,dx,dy) do { \ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2F_X(8), 2); \ + NVDmaFloat(pNv, (sx)); NVDmaFloat(pNv, (sy)); \ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_VTX_ATTR_2I(0), 1); \ + NVDmaNext (pNv, ((dy)<<16)|(dx)); \ +} while(0) + +void +NV30EXAComposite(PixmapPtr pdPix, int srcX , int srcY, + int maskX, int maskY, + int dstX , int dstY, + int width, int height) +{ + ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + float sX0, sX1, sY0, sY1; + float mX0, mX1, mY0, mY1; + NV30EXA_STATE; + + NV30EXATransformCoord(state->unit[0].transform, srcX, srcY, + state->unit[0].width, + state->unit[0].height, &sX0, &sY0); + NV30EXATransformCoord(state->unit[0].transform, + srcX + width, srcY + height, + state->unit[0].width, + state->unit[0].height, &sX1, &sY1); + + if (state->have_mask) { + NV30EXATransformCoord(state->unit[1].transform, maskX, maskY, + state->unit[1].width, + state->unit[1].height, &mX0, &mY0); + NV30EXATransformCoord(state->unit[1].transform, + maskX + width, maskY + height, + state->unit[1].width, + state->unit[1].height, &mX1, &mY1); + CV_OUTm(sX0 , sY0 , mX0, mY0, dstX , dstY); + CV_OUTm(sX1 , sY0 , mX1, mY0, dstX + width, dstY); + CV_OUTm(sX1 , sY1 , mX1, mY1, dstX + width, dstY + height); + CV_OUTm(sX0 , sY1 , mX0, mY1, dstX , dstY + height); + } else { + CV_OUT(sX0 , sY0 , dstX , dstY); + CV_OUT(sX1 , sY0 , dstX + width, dstY); + CV_OUT(sX1 , sY1 , dstX + width, dstY + height); + CV_OUT(sX0 , sY1 , dstX , dstY + height); + } + + NVDmaKickoff(pNv); +} + +void +NV30EXADoneComposite(PixmapPtr pdPix) +{ + ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_BEGIN_END, 1); + NVDmaNext (pNv, 0); +} + +Bool +NVAccelInitNV40TCL(ScrnInfoPtr pScrn) +{ + NVPtr pNv = NVPTR(pScrn); + static int have_object = FALSE; + uint32_t class = 0, chipset; + int i; + +#undef NV40_TCL_PRIMITIVE_3D +#define NV40_TCL_PRIMITIVE_3D 0x4097 +#define NV40_TCL_PRIMITIVE_3D_CHIPSET_4X_MASK 0x00000baf +#define NV44_TCL_PRIMITIVE_3D 0x4497 +#define NV44_TCL_PRIMITIVE_3D_CHIPSET_4X_MASK 0x00005450 + + chipset = (nvReadMC(pNv, 0) >> 20) & 0xff; + if ((chipset & 0xf0) != 0x40) + return TRUE; + chipset &= 0xf; + + if (NV40_TCL_PRIMITIVE_3D_CHIPSET_4X_MASK & (1<scrnIndex, X_ERROR, + "NV30EXA: Unknown chipset NV%02x\n", chipset); + return FALSE; + } + + if (!have_object) { + if (!NVDmaCreateContextObject(pNv, Nv3D, class)) + return FALSE; + have_object = TRUE; + } + + NVDmaSetObjectOnSubchannel(pNv, NvSub3D, Nv3D); + + NVDmaStart(pNv, NvSub3D, 0x180, 1); + NVDmaNext (pNv, NvDmaNotifier0); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 2); + NVDmaNext (pNv, NvDmaFB); + NVDmaNext (pNv, NvDmaFB); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1); + NVDmaNext (pNv, NvDmaFB); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2); + NVDmaNext (pNv, NvDmaFB); + NVDmaNext (pNv, NvDmaFB); + + /* voodoo */ + NVDmaStart(pNv, NvSub3D, 0x1ea4, 3); + NVDmaNext(pNv, 0x00000010); + NVDmaNext(pNv, 0x01000100); + NVDmaNext(pNv, 0xff800006); + NVDmaStart(pNv, NvSub3D, 0x1fc4, 1); + NVDmaNext(pNv, 0x06144321); + NVDmaStart(pNv, NvSub3D, 0x1fc8, 2); + NVDmaNext(pNv, 0xedcba987); + NVDmaNext(pNv, 0x00000021); + NVDmaStart(pNv, NvSub3D, 0x1fd0, 1); + NVDmaNext(pNv, 0x00171615); + NVDmaStart(pNv, NvSub3D, 0x1fd4, 1); + NVDmaNext(pNv, 0x001b1a19); + NVDmaStart(pNv, NvSub3D, 0x1ef8, 1); + NVDmaNext(pNv, 0x0020ffff); + NVDmaStart(pNv, NvSub3D, 0x1d64, 1); + NVDmaNext(pNv, 0x00d30000); + NVDmaStart(pNv, NvSub3D, 0x1e94, 1); + NVDmaNext(pNv, 0x00000001); + + /* identity viewport transform */ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8); + NVDmaFloat(pNv, 0.0); + NVDmaFloat(pNv, 0.0); + NVDmaFloat(pNv, 0.0); + NVDmaFloat(pNv, 0.0); + NVDmaFloat(pNv, 1.0); + NVDmaFloat(pNv, 1.0); + NVDmaFloat(pNv, 1.0); + NVDmaFloat(pNv, 0.0); + + /* default 3D state */ + /*XXX: replace with the same state that the DRI emits on startup */ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1); + NVDmaNext (pNv, 0); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1); + NVDmaNext (pNv, 0); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1); + NVDmaNext (pNv, 0); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 2); + NVDmaNext (pNv, 0); /* wr disable */ + NVDmaNext (pNv, 0); /* test disable */ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_MASK, 1); + NVDmaNext (pNv, 0x01010101); /* TR,TR,TR,TR */ + NVDmaStart(pNv, NvSub3D, NV40_TCL_PRIMITIVE_3D_COLOR_MASK_BUFFER123, 1); + NVDmaNext (pNv, 0x0000fff0); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1); + NVDmaNext (pNv, 0); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1); + NVDmaNext (pNv, 0); + NVDmaStart(pNv, NvSub3D, + NV30_TCL_PRIMITIVE_3D_LOGIC_OP_ENABLE, 2); + NVDmaNext (pNv, 0); + NVDmaNext (pNv, 0x1503); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1); + NVDmaNext (pNv, 0); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_SHADE_MODEL, 1); + NVDmaNext (pNv, 0x1d01); /* GL_SMOOTH */ + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR,2); + NVDmaFloat(pNv, 0.0); + NVDmaFloat(pNv, 0.0); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 2); + NVDmaNext (pNv, 0x1b02); /* FRONT = GL_FILL */ + NVDmaNext (pNv, 0x1b02); /* BACK = GL_FILL */ + NVDmaStart(pNv, NvSub3D, + NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 0x20); + for (i=0;i<0x20;i++) + NVDmaNext(pNv, 0xFFFFFFFF); + for (i=0;i<16;i++) { + NVDmaStart(pNv, NvSub3D, + NV30_TCL_PRIMITIVE_3D_TX_ENABLE_UNIT(i), 1); + NVDmaNext(pNv, 0); + } + + NVDmaStart(pNv, NvSub3D, 0x1d78, 1); + NVDmaNext (pNv, 0x110); + + NVDmaStart(pNv, NvSub3D, 0x0220, 1); + NVDmaNext (pNv, 1); + NVDmaStart(pNv, NvSub3D, + NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 2); + NVDmaNext (pNv, (4096 << 16)); + NVDmaNext (pNv, (4096 << 16)); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2); + NVDmaNext (pNv, (4096 << 16)); + NVDmaNext (pNv, (4096 << 16)); + NVDmaStart(pNv, NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2); + NVDmaNext (pNv, (4096 << 16)); + NVDmaNext (pNv, (4096 << 16)); + NVDmaStart(pNv, NvSub3D, + NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2); + NVDmaNext (pNv, (4095 << 16)); + NVDmaNext (pNv, (4095 << 16)); + + return TRUE; +} + diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index e1c0f8e..51bb5a7 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -429,6 +429,15 @@ NVAccelCommonInit(ScrnInfoPtr pScrn) /* EXA-only */ INIT_CONTEXT_OBJECT(MemFormat); + /* 3D init */ + switch (pNv->Architecture) { + case NV_ARCH_40: + INIT_CONTEXT_OBJECT(NV40TCL); + break; + default: + break; + } + return TRUE; } diff --git a/src/nv_dma.h b/src/nv_dma.h index d09b35f..16be1fd 100644 --- a/src/nv_dma.h +++ b/src/nv_dma.h @@ -93,9 +93,13 @@ enum DMASubchannel { (pNv)->dmaBase[(pNv)->dmaCurrent++] = (data); \ } while(0) -#define NVDmaFloat(pNv, data) do { \ - float f = (data); \ - NVDmaNext((pNv), *(CARD32*)&f); \ +#define NVDmaFloat(pNv, data) do { \ + union { \ + float v; \ + uint32_t u; \ + } c; \ + c.v = (data); \ + NVDmaNext((pNv), c.u); \ } while(0) #define NVDmaStart(pNv, subchannel, tag, size) do { \ diff --git a/src/nv_exa.c b/src/nv_exa.c index 3096e29..7e5c929 100644 --- a/src/nv_exa.c +++ b/src/nv_exa.c @@ -565,17 +565,21 @@ Bool NVExaInit(ScreenPtr pScreen) pNv->EXADriverPtr->Solid = NVExaSolid; pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid; - /*darktama: Hard-disabled these for now, I get lockups often when - * starting e17 with them enabled. - *marcheu: Doesn't crash for me... was it related to the setup being - * called twice before ? - */ - if (pNv->BlendingPossible) { - /* install composite hooks */ - pNv->EXADriverPtr->CheckComposite = NVCheckComposite; + switch (pNv->Architecture) { + case NV_ARCH_40: + pNv->EXADriverPtr->CheckComposite = NV30EXACheckComposite; + pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite; + pNv->EXADriverPtr->Composite = NV30EXAComposite; + pNv->EXADriverPtr->DoneComposite = NV30EXADoneComposite; + break; + default: + if (!pNv->BlendingPossible) + break; + pNv->EXADriverPtr->CheckComposite = NVCheckComposite; pNv->EXADriverPtr->PrepareComposite = NVPrepareComposite; - pNv->EXADriverPtr->Composite = NVComposite; - pNv->EXADriverPtr->DoneComposite = NVDoneComposite; + pNv->EXADriverPtr->Composite = NVComposite; + pNv->EXADriverPtr->DoneComposite = NVDoneComposite; + break; } /* If we're going to try and use 3D, let the card-specific function diff --git a/src/nv_proto.h b/src/nv_proto.h index fcf487f..83748c4 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -100,5 +100,13 @@ void NVPointerMoved(int index, int x, int y); /* in nv_bios.c */ unsigned int NVParseBios(ScrnInfoPtr pScrn); +/* in nv30_exa.c */ +Bool NVAccelInitNV40TCL(ScrnInfoPtr pScrn); +Bool NV30EXACheckComposite(int, PicturePtr, PicturePtr, PicturePtr); +Bool NV30EXAPrepareComposite(int, PicturePtr, PicturePtr, PicturePtr, + PixmapPtr, PixmapPtr, PixmapPtr); +void NV30EXAComposite(PixmapPtr, int, int, int, int, int, int, int, int); +void NV30EXADoneComposite(PixmapPtr); + #endif /* __NV_PROTO_H__ */ diff --git a/src/nv_shaders.h b/src/nv_shaders.h new file mode 100644 index 0000000..d1a769f --- /dev/null +++ b/src/nv_shaders.h @@ -0,0 +1,102 @@ +#ifndef __NV_SHADERS_H__ +#define __NV_SHADERS_H__ + +#define NV_SHADER_MAX_PROGRAM_LENGTH 256 + +typedef struct nv_shader { + uint32_t hw_id; + uint32_t size; + union { + struct { + uint32_t vp_in_reg; + uint32_t vp_out_reg; + } NV30VP; + struct { + uint32_t num_regs; + } NV30FP; + } card_priv; + uint32_t data[NV_SHADER_MAX_PROGRAM_LENGTH]; +} nv_shader_t; + +/******************************************************************************* + * NV40/G70 vertex shaders + */ + +static nv_shader_t nv40_vp_exa_render = { + .card_priv.NV30VP.vp_in_reg = 0x00000309, + .card_priv.NV30VP.vp_out_reg = 0x0000c001, + .size = (3*4), + .data = { + /* MOV result.position, vertex.position */ + 0x40041c6c, 0x0040000d, 0x8106c083, 0x6041ff80, + /* MOV result.texcoord[0], vertex.texcoord[0] */ + 0x401f9c6c, 0x0040080d, 0x8106c083, 0x6041ff9c, + /* MOV result.texcoord[1], vertex.texcoord[1] */ + 0x401f9c6c, 0x0040090d, 0x8106c083, 0x6041ffa1, + } +}; + +/******************************************************************************* + * NV30/NV40/G70 fragment shaders + */ + +static nv_shader_t nv30_fp_pass_col0 = { + .card_priv.NV30FP.num_regs = 2, + .size = (1*4), + .data = { + /* MOV R0, fragment.color */ + 0x01403e81, 0x1c9dc801, 0x0001c800, 0x3fe1c800 + } +}; + +static nv_shader_t nv30_fp_pass_tex0 = { + .card_priv.NV30FP.num_regs = 2, + .size = (2*4), + .data = { + /* TEX R0, fragment.texcoord[0], texture[0], 2D */ + 0x17009e00, 0x1c9dc801, 0x0001c800, 0x3fe1c800, + /* MOV R0, R0 */ + 0x01401e81, 0x1c9dc800, 0x0001c800, 0x0001c800 + } +}; + +static nv_shader_t nv30_fp_composite_mask = { + .card_priv.NV30FP.num_regs = 2, + .size = (3*4), + .data = { + /* TEXC0 R1.w , fragment.texcoord[1], texture[1], 2D */ + 0x1702b102, 0x1c9dc801, 0x0001c800, 0x3fe1c800, + /* TEX R0 (NE0.wwww), fragment.texcoord[0], texture[0], 2D */ + 0x17009e00, 0x1ff5c801, 0x0001c800, 0x3fe1c800, + /* MUL R0 , R0, R1.w */ + 0x02001e81, 0x1c9dc800, 0x0001fe04, 0x0001c800 + } +}; + +static nv_shader_t nv30_fp_composite_mask_sa_ca = { + .card_priv.NV30FP.num_regs = 2, + .size = (3*4), + .data = { + /* TEXC0 R1.w , fragment.texcoord[0], texture[0], 2D */ + 0x17009102, 0x1c9dc801, 0x0001c800, 0x3fe1c800, + /* TEX R0 (NE0.wwww), fragment.texcoord[1], texture[1], 2D */ + 0x1702be00, 0x1ff5c801, 0x0001c800, 0x3fe1c800, + /* MUL R0 , R1,wwww, R0 */ + 0x02001e81, 0x1c9dfe04, 0x0001c800, 0x0001c800 + } +}; + +static nv_shader_t nv30_fp_composite_mask_ca = { + .card_priv.NV30FP.num_regs = 2, + .size = (3*4), + .data = { + /* TEXC0 R0 , fragment.texcoord[0], texture[0], 2D */ + 0x17009f00, 0x1c9dc801, 0x0001c800, 0x3fe1c800, + /* TEX R1 (NE0.xyzw), fragment.texcoord[1], texture[1], 2D */ + 0x1702be02, 0x1c95c801, 0x0001c800, 0x3fe1c800, + /* MUL R0 , R0, R1 */ + 0x02001e81, 0x1c9dc800, 0x0001c804, 0x0001c800 + } +}; + +#endif -- cgit v1.2.1 From 8f1c9af02651404f8b4800b150a86bb47062fd68 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 25 Jun 2007 12:44:12 +1000 Subject: Check PRAMIN for BIOS image if not found in PROM. --- src/nv_bios.c | 95 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 25 deletions(-) diff --git a/src/nv_bios.c b/src/nv_bios.c index 286e85f..d093100 100644 --- a/src/nv_bios.c +++ b/src/nv_bios.c @@ -47,6 +47,70 @@ typedef struct { CARD16 io_flag_condition_offset; } bios_t; +static Bool NVValidBios(ScrnInfoPtr pScrn, const unsigned char *data) +{ + /* check for BIOS signature */ + if (!(data[0] == 0x55 && data[1] == 0xAA)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "...BIOS signature not found\n"); + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "...appears to be valid\n"); + return TRUE; +} + +static void NVDownloadBiosPROM(ScrnInfoPtr pScrn, unsigned char *data) +{ + NVPtr pNv = NVPTR(pScrn); + int i; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Attempting to locate BIOS image in PROM\n"); + + /* enable ROM access */ + nvWriteMC(pNv, 0x1850, 0x0); + for (i=0; iPROM[i]; + data[i] = pNv->PROM[i]; + data[i] = pNv->PROM[i]; + data[i] = pNv->PROM[i]; + data[i] = pNv->PROM[i]; + } + /* disable ROM access */ + nvWriteMC(pNv, 0x1850, 0x1); +} + +static void NVDownloadBiosPRAMIN(ScrnInfoPtr pScrn, unsigned char *data) +{ + NVPtr pNv = NVPTR(pScrn); + const unsigned char *pramin = (void*)&pNv->REGS[0x00700000/4]; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Attempting to locate BIOS image in PRAMIN\n"); + memcpy(data, pramin, 65536); +} + +static Bool NVDownloadBios(ScrnInfoPtr pScrn, bios_t *bios) +{ + NVPtr pNv = NVPTR(pScrn); + + bios->data = xcalloc(1, 65536); + + NVDownloadBiosPROM(pScrn, bios->data); + if (NVValidBios(pScrn, bios->data)) + return TRUE; + + NVDownloadBiosPRAMIN(pScrn, bios->data); + if (NVValidBios(pScrn, bios->data)) + return TRUE; + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to locate BIOS image\n"); + xfree(bios->data); + return FALSE; +} typedef struct { char* name; @@ -1507,39 +1571,20 @@ unsigned int NVParseBios(ScrnInfoPtr pScrn) unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0}; unsigned char bit_signature[]={'B','I','T'}; NVPtr pNv; - int i; + int i, ret; pNv = NVPTR(pScrn); - bios.data=xalloc(NV_PROM_SIZE); - - /* enable ROM access */ - nvWriteMC(pNv, 0x1850, 0x0); - for(i=0;iPROM[i]; - bios.data[i]=pNv->PROM[i]; - bios.data[i]=pNv->PROM[i]; - bios.data[i]=pNv->PROM[i]; - bios.data[i]=pNv->PROM[i]; - } - /* disable ROM access */ - nvWriteMC(pNv, 0x1850, 0x1); - - /* check for BIOS signature */ - if (!(bios.data[0] == 0x55 && bios.data[1] == 0xAA)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS signature not found!\n"); - xfree(bios.data); + if (!NVDownloadBios(pScrn, &bios)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid BIOS image found.\n"); return 0; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS signature found.\n"); - /* check for known signatures */ - if (bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature))) { + if ((bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature)))) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found.\n"); parse_bit_structure(pScrn, &bios, bit_offset + 4); - } else if (bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature))) { + } else if ((bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature)))) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found.\n"); parse_pins_structure(pScrn, &bios, bit_offset); } else { -- cgit v1.2.1 From fce3edda42d10a9c3249c6eae4218a51a981493f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 25 Jun 2007 12:45:31 +1000 Subject: Bump required xorg-server version to 1.3 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 412f37f..64eae31 100644 --- a/configure.ac +++ b/configure.ac @@ -67,7 +67,7 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) # Checks for pkg-config packages -PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.99.901] xproto fontsproto libdrm xf86driproto $REQUIRED_MODULES) +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.3] xproto fontsproto libdrm xf86driproto $REQUIRED_MODULES) sdkdir=$(pkg-config --variable=sdkdir xorg-server) # Checks for libraries. -- cgit v1.2.1 From e81c9a29e6d1c6573892df8601f0361c2b09c659 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 28 Jun 2007 15:16:35 +1000 Subject: Bail if GlxSetVisualConfigs isn't found. --- src/nv_dri.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/nv_dri.c b/src/nv_dri.c index 857fb42..a489e68 100644 --- a/src/nv_dri.c +++ b/src/nv_dri.c @@ -257,6 +257,19 @@ Bool NVDRIGetVersion(ScrnInfoPtr pScrn) return TRUE; } +Bool NVDRICheckModules(ScrnInfoPtr pScrn) +{ + if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] GlxSetVisualConfigs not found.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + " NVIDIA's glx present, or glx not loaded.\n"); + return FALSE; + } + + return TRUE; +} + Bool NVDRIScreenInit(ScrnInfoPtr pScrn) { DRIInfoPtr pDRIInfo; @@ -267,6 +280,9 @@ Bool NVDRIScreenInit(ScrnInfoPtr pScrn) int drm_page_size; int irq; + if (!NVDRICheckModules(pScrn)) + return FALSE; + drm_page_size = getpagesize(); if (!(pDRIInfo = DRICreateInfoRec())) return FALSE; -- cgit v1.2.1