From 46df75ccd4647ea033583130253a2a2218b34a20 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 13:45:06 -0800 Subject: [PATCH 01/37] Bug #7524: Major improvements to EXA/XAA static memory allocation. With this, we no longer allocate XV through the XF86 linear allocator in the EXA case. We also no longer allocate extra space for the XF86 2D allocator that we don't use in EXA mode, or space for the EXA allocator in XAA mode. The EXA offscreen allocator now gets enough space for several screenfuls of pixmaps plus one 1920x1088 movie. A large duplicated section of code for allocating each framebuffer in the old dual-screen mode was also factored out. --- src/i830_driver.c | 34 ++-- src/i830_memory.c | 397 +++++++++++++++++++--------------------------- src/i830_video.c | 203 ++++++++++++++++-------- src/i830_video.h | 15 +- 4 files changed, 334 insertions(+), 315 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index d30af07c..e2653c15 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2855,20 +2855,28 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) DPRINTF(PFX, "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n"); - if (I830IsPrimary(pScrn)) { - if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to init memory manager\n"); - } + if (!pI830->useEXA) { + if (I830IsPrimary(pScrn)) { + if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to init memory manager\n"); + } - if (pI830->LinearAlloc && xf86InitFBManagerLinear(pScreen, pI830->LinearMem.Offset / pI830->cpp, pI830->LinearMem.Size / pI830->cpp)) - xf86DrvMsg(scrnIndex, X_INFO, - "Using %ld bytes of offscreen memory for linear (offset=0x%lx)\n", pI830->LinearMem.Size, pI830->LinearMem.Offset); - - } else { - if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to init memory manager\n"); + if (pI830->LinearAlloc && + xf86InitFBManagerLinear(pScreen, + pI830->LinearMem.Offset / pI830->cpp, + pI830->LinearMem.Size / pI830->cpp)) + { + xf86DrvMsg(scrnIndex, X_INFO, + "Using %ld bytes of offscreen memory for linear " + "(offset=0x%lx)\n", pI830->LinearMem.Size, + pI830->LinearMem.Offset); + } + } else { + if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to init memory manager\n"); + } } } diff --git a/src/i830_memory.c b/src/i830_memory.c index 7b0c6fe4..b41a73d2 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -602,11 +602,141 @@ GetFreeSpace(ScrnInfoPtr pScrn) return extra; } +/** + * Allocates a framebuffer for a screen. + * + * Used once for each X screen, so once with RandR 1.2 and twice with classic + * dualhead. + * + * \param pScrn ScrnInfoPtr for the screen being allocated + * \param pI830 I830Ptr for the screen being allocated. + * \param FbMemBox + */ +static Bool +I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, + I830MemRange *FrontBuffer, I830MemPool *StolenPool, + Bool secondary, const int flags) +{ + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + unsigned long minspace, avail, lineSize; + int cacheLines, maxCacheLines; + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + Bool tileable; + int align, alignflags; + long size, alloced, fb_height; + + /* Clear everything first. */ + memset(FbMemBox, 0, sizeof(*FbMemBox)); + memset(FrontBuffer, 0, sizeof(*FrontBuffer)); + FrontBuffer->Key = -1; + + /* We'll allocate the fb such that the root window will fit regardless of + * rotation. + */ + if (pScrn->virtualX > pScrn->virtualY) + fb_height = pScrn->virtualX; + else + fb_height = pScrn->virtualY; + + FbMemBox->x1 = 0; + FbMemBox->x2 = pScrn->displayWidth; + FbMemBox->y1 = 0; + FbMemBox->y2 = fb_height; + + /* Calculate how much framebuffer memory to allocate. For the + * initial allocation, calculate a reasonable minimum. This is + * enough for the virtual screen size, plus some pixmap cache + * space if we're using XAA. + */ + + lineSize = pScrn->displayWidth * pI830->cpp; + minspace = lineSize * pScrn->virtualY; + avail = pScrn->videoRam * 1024; + + if (!pI830->useEXA) { + maxCacheLines = (avail - minspace) / lineSize; + /* This shouldn't happen. */ + if (maxCacheLines < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Internal Error: " + "maxCacheLines < 0 in I830Allocate2DMemory()\n"); + maxCacheLines = 0; + } + if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY)) + maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY; + + if (pI830->CacheLines >= 0) { + cacheLines = pI830->CacheLines; + } else { +#if 1 + /* Make sure there is enough for two DVD sized YUV buffers */ + cacheLines = (pScrn->depth == 24) ? 256 : 384; + if (pScrn->displayWidth <= 1024) + cacheLines *= 2; +#else + /* + * Make sure there is enough for two DVD sized YUV buffers. + * Make that 1.5MB, which is around what was allocated with + * the old algorithm + */ + cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth; +#endif + } + if (cacheLines > maxCacheLines) + cacheLines = maxCacheLines; + + FbMemBox->y2 += cacheLines; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocating at least %d scanlines for pixmap cache\n", + s, cacheLines); + } else { + /* For EXA, we have a separate allocation for the linear allocator which + * also does the pixmap cache. + */ + cacheLines = 0; + } + + tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && + IsTileable(pScrn->displayWidth * pI830->cpp); + if (tileable) { + if (IS_I9XX(pI830)) + align = MB(1); + else + align = KB(512); + alignflags = ALIGN_BOTH_ENDS; + } else { + align = KB(64); + alignflags = 0; + } + + size = lineSize * (fb_height + cacheLines); + size = ROUND_TO_PAGE(size); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sInitial %sframebuffer allocation size: %ld kByte\n", + s, secondary ? "secondary " : "", + size / 1024); + alloced = I830AllocVidMem(pScrn, FrontBuffer, + StolenPool, size, align, + flags | alignflags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "%sframebuffer. Is your VideoRAM set too low?\n", + secondary ? "secondary " : ""); + } + return FALSE; + } + + return TRUE; +} + /* * Allocate memory for 2D operation. This includes the (front) framebuffer, * ring buffer, scratch memory, HW cursor. */ - Bool I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) { @@ -648,8 +778,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->StolenPool.Free.Size); if (flags & ALLOC_INITIAL) { - unsigned long minspace, avail, lineSize; - int cacheLines, maxCacheLines; if (pI830->NeedRingBufferLow) AllocateRingBuffer(pScrn, flags | FORCE_LOW); @@ -660,242 +788,45 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) I830EntPtr pI830Ent = pI830->entityPrivate; I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2); - /* Clear everything first. */ - memset(&(pI830->FbMemBox2), 0, sizeof(pI830->FbMemBox2)); - memset(&(pI830->FrontBuffer2), 0, sizeof(pI830->FrontBuffer2)); - pI830->FrontBuffer2.Key = -1; - -#if 1 /* ROTATION */ - pI830->FbMemBox2.x1 = 0; - pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; - pI830->FbMemBox2.y1 = 0; - if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualX; - else - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; -#else - pI830->FbMemBox2.x1 = 0; - pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; - pI830->FbMemBox2.y1 = 0; - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; -#endif - - /* - * Calculate how much framebuffer memory to allocate. For the - * initial allocation, calculate a reasonable minimum. This is - * enough for the virtual screen size, plus some pixmap cache - * space. - */ - - lineSize = pI830Ent->pScrn_2->displayWidth * pI8302->cpp; - minspace = lineSize * pI830Ent->pScrn_2->virtualY; - avail = pI830Ent->pScrn_2->videoRam * 1024; - maxCacheLines = (avail - minspace) / lineSize; - /* This shouldn't happen. */ - if (maxCacheLines < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Internal Error: " - "maxCacheLines < 0 in I830Allocate2DMemory()\n"); - maxCacheLines = 0; - } - if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY)) - maxCacheLines = MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY; - - if (pI8302->CacheLines >= 0) { - cacheLines = pI8302->CacheLines; - } else { -#if 1 - /* Make sure there is enough for two DVD sized YUV buffers */ - cacheLines = (pI830Ent->pScrn_2->depth == 24) ? 256 : 384; - if (pI830Ent->pScrn_2->displayWidth <= 1024) - cacheLines *= 2; -#else - /* - * Make sure there is enough for two DVD sized YUV buffers. - * Make that 1.5MB, which is around what was allocated with - * the old algorithm - */ - cacheLines = (MB(1) + KB(512)) / pI8302->cpp / pI830Ent->pScrn_2->displayWidth; -#endif - } - if (cacheLines > maxCacheLines) - cacheLines = maxCacheLines; - - pI830->FbMemBox2.y2 += cacheLines; - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocating at least %d scanlines for pixmap cache\n", - s, cacheLines); - - tileable = !(flags & ALLOC_NO_TILING) && pI8302->allowPageFlip && - IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); - if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - -#if 1 /* ROTATION */ - if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) - size = lineSize * (pI830Ent->pScrn_2->virtualX + cacheLines); - else - size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#else - size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#endif - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sSecondary framebuffer allocation size: %ld kByte\n", s, - size / 1024); - alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer2), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pI830Ent->pScrn_2->scrnIndex, X_ERROR, - "Failed to allocate secondary framebuffer.\n"); - } - return FALSE; - } - } - - /* Clear everything first. */ - memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox)); - memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer)); - pI830->FrontBuffer.Key = -1; - -#if 1 /* ROTATION */ - pI830->FbMemBox.x1 = 0; - pI830->FbMemBox.x2 = pScrn->displayWidth; - pI830->FbMemBox.y1 = 0; - if (pScrn->virtualX > pScrn->virtualY) - pI830->FbMemBox.y2 = pScrn->virtualX; - else - pI830->FbMemBox.y2 = pScrn->virtualY; -#else - pI830->FbMemBox.x1 = 0; - pI830->FbMemBox.x2 = pScrn->displayWidth; - pI830->FbMemBox.y1 = 0; - pI830->FbMemBox.y2 = pScrn->virtualY; -#endif - - /* - * Calculate how much framebuffer memory to allocate. For the - * initial allocation, calculate a reasonable minimum. This is - * enough for the virtual screen size, plus some pixmap cache - * space. - */ - - lineSize = pScrn->displayWidth * pI830->cpp; - minspace = lineSize * pScrn->virtualY; - avail = pScrn->videoRam * 1024; - maxCacheLines = (avail - minspace) / lineSize; - /* This shouldn't happen. */ - if (maxCacheLines < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Internal Error: " - "maxCacheLines < 0 in I830Allocate2DMemory()\n"); - maxCacheLines = 0; - } - if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY)) - maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY; - - if (pI830->CacheLines >= 0) { - cacheLines = pI830->CacheLines; - } else { -#if 1 - /* Make sure there is enough for two DVD sized YUV buffers */ - cacheLines = (pScrn->depth == 24) ? 256 : 384; - if (pScrn->displayWidth <= 1024) - cacheLines *= 2; -#else - /* - * Make sure there is enough for two DVD sized YUV buffers. - * Make that 1.5MB, which is around what was allocated with - * the old algorithm - */ - cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth; -#endif - } - if (cacheLines > maxCacheLines) - cacheLines = maxCacheLines; - - pI830->FbMemBox.y2 += cacheLines; - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocating at least %d scanlines for pixmap cache\n", - s, cacheLines); - - tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && - IsTileable(pScrn->displayWidth * pI830->cpp); - if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - -#if 1 /* ROTATION */ - if (pScrn->virtualX > pScrn->virtualY) - size = lineSize * (pScrn->virtualX + cacheLines); - else - size = lineSize * (pScrn->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#else - size = lineSize * (pScrn->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#endif - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sInitial framebuffer allocation size: %ld kByte\n", s, - size / 1024); - alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " - "framebuffer. Is your VideoRAM set too low ??\n"); + if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302, + &pI830->FbMemBox2, + &pI830->FrontBuffer2, &pI830->StolenPool, + TRUE, flags)) + { + return FALSE; } + } + if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox, + &pI830->FrontBuffer, &pI830->StolenPool, + FALSE, flags)) + { return FALSE; } + #ifdef I830_USE_EXA - size = lineSize * pScrn->virtualY; - size = ROUND_TO_PAGE(size); + if (pI830->useEXA) { + /* Default EXA to having 3 screens worth of offscreen memory space + * (for pixmaps), plus a double-buffered, 1920x1088 video's worth. + */ + size = 3 * pScrn->displayWidth * pI830->cpp * pScrn->virtualY; + size += 1920 * 1088 * 2 * 2; + size = ROUND_TO_PAGE(size); - if (tileable) { - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - - alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " - "offscreen memory. Not enough VRAM?\n"); + alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen), + &(pI830->StolenPool), size, 1, + flags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "offscreen memory. Not enough VRAM?\n"); + } + return FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocation of " + "EXA offscreen memory at 0x%lx, size %ld KB\n", + pI830->Offscreen.Start, pI830->Offscreen.Size/1024); } - return FALSE; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocate " - "offscreen memory at 0x%lx, size %ld KB\n", - pI830->Offscreen.Start, pI830->Offscreen.Size/1024); } #endif } else { diff --git a/src/i830_video.c b/src/i830_video.c index d10fd168..946a447e 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -120,8 +120,8 @@ static int I830QueryImageAttributesTextured(ScrnInfoPtr, int, unsigned short *, static void I830BlockHandler(int, pointer, pointer, pointer); -static FBLinearPtr -I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size); +static void +I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -715,7 +715,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) pPriv->contrast = 64; pPriv->saturation = 128; pPriv->pipe = 0; /* XXX must choose pipe wisely */ - pPriv->linear = NULL; + memset(&pPriv->linear, 0, sizeof(pPriv->linear)); pPriv->currentBuf = 0; pPriv->gamma5 = 0xc0c0c0; pPriv->gamma4 = 0x808080; @@ -838,7 +838,7 @@ I830SetupImageVideoTextured(ScreenPtr pScreen) pPriv->textured = TRUE; pPriv->videoStatus = 0; - pPriv->linear = NULL; + memset(&pPriv->linear, 0, sizeof(pPriv->linear)); pPriv->currentBuf = 0; pPriv->doubleBuffer = 0; @@ -902,10 +902,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; } - if (pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; - } + I830FreeMemory(pScrn, &pPriv->linear); pPriv->videoStatus = 0; } else { if (pPriv->videoStatus & CLIENT_VIDEO_ON) { @@ -2224,9 +2221,7 @@ BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, /* * Use the extra space allocated at the end of the Xv buffer */ - state_base_offset = (pPriv->YBuf0offset + - pPriv->linear->size * pI830->cpp - - BRW_LINEAR_EXTRA); + state_base_offset = pPriv->extra_offset; state_base_offset = ALIGN(state_base_offset, 64); state_base = (char *)(pI830->FbBase + state_base_offset); @@ -2798,44 +2793,119 @@ BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, #endif } -static FBLinearPtr -I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) +#ifdef I830_USE_EXA +static void +I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) { - ScreenPtr pScreen; - FBLinearPtr new_linear = NULL; + struct linear_alloc *linear = area->privData; - if (linear) { - if (linear->size >= size) - return linear; + linear->exa = NULL; + linear->offset = 0; +} +#endif /* I830_USE_EXA */ - if (xf86ResizeOffscreenLinear(linear, size)) - return linear; +/** + * Allocates linear memory using the XFree86 (XAA) or EXA allocator. + * + * \param pPriv adaptor the memory is being allocated for. + * \param size size of the allocation, in bytes. + * \param alignment offset alignment of the allocation, in bytes. + * \return offset of the allocated memory. + */ +static void +I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, + int align) +{ + ScreenPtr pScreen = pScrn->pScreen; + I830Ptr pI830 = I830PTR(pScrn); - xf86FreeOffscreenLinear(linear); +#ifdef I830_USE_EXA + if (pI830->useEXA) { + if (linear->exa != NULL) { + if (linear->exa->size >= size) + return; + + exaOffscreenFree(pScreen, linear->exa); + linear->offset = 0; + } + + linear->exa = exaOffscreenAlloc(pScreen, size, align, TRUE, + I830VideoSave, linear); + if (linear->exa == NULL) + return; + linear->offset = linear->exa->offset; } - - pScreen = screenInfo.screens[pScrn->scrnIndex]; - - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, - NULL, NULL, NULL); - - if (!new_linear) { +#endif /* I830_USE_EXA */ +#ifdef I830_USE_XAA + if (!pI830->useEXA) { int max_size; - xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, + /* The XFree86 linear allocator operates in units of screen pixels, + * sadly. + */ + size = (size + pI830->cpp - 1) / pI830->cpp; + align = (align + pI830->cpp - 1) / pI830->cpp; + + if (linear->xaa != NULL) { + if (linear->xaa->size >= size) { + linear->offset = linear->xaa->offset * pI830->cpp; + return; + } + + if (xf86ResizeOffscreenLinear(linear->xaa, size)) { + linear->offset = linear->xaa->offset * pI830->cpp; + return; + } + + xf86FreeOffscreenLinear(linear->xaa); + } + + linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align, + NULL, NULL, NULL); + if (linear->xaa != NULL) { + linear->offset = linear->xaa->offset * pI830->cpp; + return; + } + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, align, PRIORITY_EXTREME); if (max_size < size) { - ErrorF("No memory available\n"); - return NULL; + ErrorF("No memory available\n"); + linear->offset = 0; + return; } xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, - NULL, NULL, NULL); + linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4, + NULL, NULL, NULL); + linear->offset = linear->xaa->offset * pI830->cpp; } +#endif /* I830_USE_XAA */ +} - return new_linear; +static void +I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear) +{ + I830Ptr pI830 = I830PTR(pScrn); + +#ifdef I830_USE_EXA + if (pI830->useEXA) { + if (linear->exa != NULL) { + exaOffscreenFree(pScrn->pScreen, linear->exa); + linear->exa = NULL; + } + } +#endif /* I830_USE_EXA */ +#ifdef I830_USE_XAA + if (!pI830->useEXA) { + if (linear->xaa != NULL) { + xf86FreeOffscreenLinear(linear->xaa); + linear->xaa = NULL; + } + } +#endif /* I830_USE_XAA */ + linear->offset = 0; } /* @@ -2981,19 +3051,21 @@ I830PutImage(ScrnInfoPtr pScrn, extraLinear = 0; /* size is multiplied by 2 because we have two buffers that are flipping */ - pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, - (extraLinear + - (pPriv->doubleBuffer ? size * 2 : size)) / - pI830->cpp); + I830AllocateMemory(pScrn, &pPriv->linear, + extraLinear + (pPriv->doubleBuffer ? size * 2 : size), + 16); - if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY)) + if (pPriv->linear.offset == 0) return BadAlloc; + pPriv->extra_offset = pPriv->linear.offset + + pPriv->doubleBuffer ? size * 2 : size; + /* fixup pointers */ #if 0 - pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp; + pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear.offset; #else - pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp; + pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear.offset; #endif if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); @@ -3236,10 +3308,7 @@ I830BlockHandler(int i, } } else { /* FREE_TIMER */ if (pPriv->freeTime < now) { - if (pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; - } + I830FreeMemory(pScrn, &pPriv->linear); pPriv->videoStatus = 0; } } @@ -3251,7 +3320,7 @@ I830BlockHandler(int i, ***************************************************************************/ typedef struct { - FBLinearPtr linear; + struct linear_alloc linear; Bool isOn; } OffscreenPrivRec, *OffscreenPrivPtr; @@ -3261,8 +3330,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn, unsigned short w, unsigned short h, XF86SurfacePtr surface) { - FBLinearPtr linear; - int pitch, fbpitch, size, bpp; + int pitch, fbpitch, size; OffscreenPrivPtr pPriv; I830Ptr pI830 = I830PTR(pScrn); @@ -3280,41 +3348,40 @@ I830AllocateSurface(ScrnInfoPtr pScrn, if (pI830->rotation != RR_Rotate_0) return BadAlloc; - w = (w + 1) & ~1; - pitch = ((w << 1) + 15) & ~15; - bpp = pScrn->bitsPerPixel >> 3; - fbpitch = bpp * pScrn->displayWidth; - size = ((pitch * h) + bpp - 1) / bpp; - - if (!(linear = I830AllocateMemory(pScrn, NULL, size))) + if (!(surface->pitches = xalloc(sizeof(int)))) return BadAlloc; - - surface->width = w; - surface->height = h; - - if (!(surface->pitches = xalloc(sizeof(int)))) { - xf86FreeOffscreenLinear(linear); - return BadAlloc; - } if (!(surface->offsets = xalloc(sizeof(int)))) { xfree(surface->pitches); - xf86FreeOffscreenLinear(linear); return BadAlloc; } if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { xfree(surface->pitches); xfree(surface->offsets); - xf86FreeOffscreenLinear(linear); return BadAlloc; } - pPriv->linear = linear; + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + fbpitch = pI830->cpp * pScrn->displayWidth; + size = pitch * h; + + I830AllocateMemory(pScrn, &pPriv->linear, size, 16); + if (pPriv->linear.offset == 0) { + xfree(surface->pitches); + xfree(surface->offsets); + xfree(pPriv); + return BadAlloc; + } + + surface->width = w; + surface->height = h; + pPriv->isOn = FALSE; surface->pScrn = pScrn; surface->id = id; surface->pitches[0] = pitch; - surface->offsets[0] = linear->offset * bpp; + surface->offsets[0] = pPriv->linear.offset; surface->devPrivate.ptr = (pointer) pPriv; #if 0 @@ -3358,7 +3425,7 @@ I830FreeSurface(XF86SurfacePtr surface) if (pPriv->isOn) { I830StopSurface(surface); } - xf86FreeOffscreenLinear(pPriv->linear); + I830FreeMemory(surface->pScrn, &pPriv->linear); xfree(surface->pitches); xfree(surface->offsets); xfree(surface->devPrivate.ptr); diff --git a/src/i830_video.h b/src/i830_video.h index 6a09a258..12a5bda2 100644 --- a/src/i830_video.h +++ b/src/i830_video.h @@ -27,6 +27,18 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86.h" #include "xf86_OSproc.h" +/* Ugly mess to support the old XF86 allocator or EXA using the same code. + */ +struct linear_alloc { +#ifdef I830_USE_XAA + FBLinearPtr xaa; +#endif +#ifdef I830_USE_EXA + ExaOffscreenArea *exa; +#endif + unsigned int offset; +}; + typedef struct { CARD32 YBuf0offset; CARD32 UBuf0offset; @@ -57,7 +69,8 @@ typedef struct { CARD32 videoStatus; Time offTime; Time freeTime; - FBLinearPtr linear; + struct linear_alloc linear; + unsigned int extra_offset; Bool overlayOK; int oneLineMode; From 05066632b068ae91d7be77e3a199ea0d337d975b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 17:41:45 -0800 Subject: [PATCH 02/37] Move 965 textured-video out to a separate file. --- src/Makefile.am | 1 + src/i830_video.c | 793 +-------------------------------------------- src/i830_video.h | 8 + src/i965_video.c | 827 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 839 insertions(+), 790 deletions(-) create mode 100644 src/i965_video.c diff --git a/src/Makefile.am b/src/Makefile.am index 976a95a4..d843ecff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,6 +88,7 @@ i810_drv_la_SOURCES = \ i915_3d.h \ i915_reg.h \ i915_video.c \ + i965_video.c \ i830_exa.c \ i830_xaa.c \ i830_exa_render.c \ diff --git a/src/i830_video.c b/src/i830_video.c index 946a447e..2e4a85bd 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -84,8 +84,6 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xaalocal.h" #include "dixstruct.h" #include "fourcc.h" -#include "brw_defines.h" -#include "brw_structs.h" #ifndef USE_USLEEP_FOR_VIDEO #define USE_USLEEP_FOR_VIDEO 0 @@ -2007,791 +2005,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, OVERLAY_UPDATE; } -static const CARD32 sip_kernel_static[][4] = { -/* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */ - { 0x00000030, 0x20000108, 0x00001220, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -/* nop (4) g0<1>UD { align1 + } */ - { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, -}; - -/* - * this program computes dA/dx and dA/dy for the texture coordinates along - * with the base texture coordinate. It was extracted from the Mesa driver. - * It uses about 10 GRF registers. - */ - -#define SF_KERNEL_NUM_GRF 16 -#define SF_MAX_THREADS 1 - -static const CARD32 sf_kernel_static[][4] = { -#include "sf_prog.h" -}; - -/* - * Ok, this kernel picks up the required data flow values in g0 and g1 - * and passes those along in m0 and m1. In m2-m9, it sticks constant - * values (bright pink). - */ - -/* Our PS kernel uses less than 32 GRF registers (about 20) */ -#define PS_KERNEL_NUM_GRF 32 -#define PS_MAX_THREADS 32 - -#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1) - -static const CARD32 ps_kernel_static[][4] = { -#include "wm_prog.h" -}; - -#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -#define WM_BINDING_TABLE_ENTRIES 2 - -static CARD32 float_to_uint (float f) { - union {CARD32 i; float f;} x; - x.f = f; - return x.i; -} - -#if 0 -static struct { - CARD32 svg_ctl; - char *name; -} svg_ctl_bits[] = { - { BRW_SVG_CTL_GS_BA, "General State Base Address" }, - { BRW_SVG_CTL_SS_BA, "Surface State Base Address" }, - { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" }, - { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" }, - { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" }, - { BRW_SVG_CTL_SIP, "System Instruction Pointer" }, - { 0, 0 }, -}; - -static void -brw_debug (ScrnInfoPtr pScrn, char *when) -{ - I830Ptr pI830 = I830PTR(pScrn); - int i; - CARD32 v; - - I830Sync (pScrn); - ErrorF("brw_debug: %s\n", when); - for (i = 0; svg_ctl_bits[i].name; i++) { - OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl); - v = INREG(BRW_SVG_RDATA); - ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v); - } -} -#endif - -#define WATCH_SF 0 -#define WATCH_WIZ 0 -#define WATCH_STATS 0 - -static void -BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, - RegionPtr dstRegion, - short width, short height, int video_pitch, - int x1, int y1, int x2, int y2, - short src_w, short src_h, - short drw_w, short drw_h, - DrawablePtr pDraw) -{ - I830Ptr pI830 = I830PTR(pScrn); - BoxPtr pbox; - int nbox, dxo, dyo; - int urb_vs_start, urb_vs_size; - int urb_gs_start, urb_gs_size; - int urb_clip_start, urb_clip_size; - int urb_sf_start, urb_sf_size; - int urb_cs_start, urb_cs_size; - struct brw_surface_state *dest_surf_state; - struct brw_surface_state *src_surf_state; - struct brw_sampler_state *src_sampler_state; - struct brw_vs_unit_state *vs_state; - struct brw_sf_unit_state *sf_state; - struct brw_wm_unit_state *wm_state; - struct brw_cc_unit_state *cc_state; - struct brw_cc_viewport *cc_viewport; - struct brw_instruction *sf_kernel; - struct brw_instruction *ps_kernel; - struct brw_instruction *sip_kernel; - float *vb; - CARD32 *binding_table; - Bool first_output = TRUE; - int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset; - int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset; - int wm_scratch_offset; - int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset; - int binding_table_offset; - int next_offset, total_state_size; - int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */ - char *state_base; - int state_base_offset; - -#if 0 - ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height, - video_pitch); -#endif - - /* enable debug */ - OUTREG (INST_PM, - (1 << (16 + 4)) | - (1 << 4)); -#if 0 - ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM)); -#endif - - assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2)); - - /* Tell the rotation code that we have stomped its invariant state by - * setting a high bit. We don't use any invariant 3D state for video, so we - * don't have to worry about it ourselves. - */ - *pI830->used3D |= 1 << 30; - -#ifdef XF86DRI - /* Tell the DRI that we're smashing its state. */ - if (pI830->directRenderingEnabled) { - drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - - pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); - } -#endif /* XF86DRI */ - - next_offset = 0; - - /* Set up our layout of state in framebuffer. First the general state: */ - vs_offset = ALIGN(next_offset, 64); - next_offset = vs_offset + sizeof(*vs_state); - sf_offset = ALIGN(next_offset, 32); - next_offset = sf_offset + sizeof(*sf_state); - wm_offset = ALIGN(next_offset, 32); - next_offset = wm_offset + sizeof(*wm_state); - wm_scratch_offset = ALIGN(next_offset, 1024); - next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS; - cc_offset = ALIGN(next_offset, 32); - next_offset = cc_offset + sizeof(*cc_state); - - sf_kernel_offset = ALIGN(next_offset, 64); - next_offset = sf_kernel_offset + sizeof (sf_kernel_static); - ps_kernel_offset = ALIGN(next_offset, 64); - next_offset = ps_kernel_offset + sizeof (ps_kernel_static); - sip_kernel_offset = ALIGN(next_offset, 64); - next_offset = sip_kernel_offset + sizeof (sip_kernel_static); - cc_viewport_offset = ALIGN(next_offset, 32); - next_offset = cc_viewport_offset + sizeof(*cc_viewport); - - src_sampler_offset = ALIGN(next_offset, 32); - next_offset = src_sampler_offset + sizeof(*src_sampler_state); - - /* Align VB to native size of elements, for safety */ - vb_offset = ALIGN(next_offset, 8); - next_offset = vb_offset + vb_size; - - /* And then the general state: */ - dest_surf_offset = ALIGN(next_offset, 32); - next_offset = dest_surf_offset + sizeof(*dest_surf_state); - src_surf_offset = ALIGN(next_offset, 32); - next_offset = src_surf_offset + sizeof(*src_surf_state); - binding_table_offset = ALIGN(next_offset, 32); - next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4); - - /* Allocate an area in framebuffer for our state layout we just set up */ - total_state_size = next_offset; - assert (total_state_size < BRW_LINEAR_EXTRA); - - /* - * Use the extra space allocated at the end of the Xv buffer - */ - state_base_offset = pPriv->extra_offset; - state_base_offset = ALIGN(state_base_offset, 64); - - state_base = (char *)(pI830->FbBase + state_base_offset); - /* Set up our pointers to state structures in framebuffer. It would probably - * be a good idea to fill these structures out in system memory and then dump - * them there, instead. - */ - vs_state = (void *)(state_base + vs_offset); - sf_state = (void *)(state_base + sf_offset); - wm_state = (void *)(state_base + wm_offset); - cc_state = (void *)(state_base + cc_offset); - sf_kernel = (void *)(state_base + sf_kernel_offset); - ps_kernel = (void *)(state_base + ps_kernel_offset); - sip_kernel = (void *)(state_base + sip_kernel_offset); - - cc_viewport = (void *)(state_base + cc_viewport_offset); - dest_surf_state = (void *)(state_base + dest_surf_offset); - src_surf_state = (void *)(state_base + src_surf_offset); - src_sampler_state = (void *)(state_base + src_sampler_offset); - binding_table = (void *)(state_base + binding_table_offset); - vb = (void *)(state_base + vb_offset); - - /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it. - * A VUE consists of a 256-bit vertex header followed by the vertex data, - * which in our case is 4 floats (128 bits), thus a single 512-bit URB - * entry. - */ -#define URB_VS_ENTRIES 8 -#define URB_VS_ENTRY_SIZE 1 - -#define URB_GS_ENTRIES 0 -#define URB_GS_ENTRY_SIZE 0 - -#define URB_CLIP_ENTRIES 0 -#define URB_CLIP_ENTRY_SIZE 0 - - /* The SF kernel we use outputs only 4 256-bit registers, leading to an - * entry size of 2 512-bit URBs. We don't need to have many entries to - * output as we're generally working on large rectangles and don't care - * about having WM threads running on different rectangles simultaneously. - */ -#define URB_SF_ENTRIES 1 -#define URB_SF_ENTRY_SIZE 2 - -#define URB_CS_ENTRIES 0 -#define URB_CS_ENTRY_SIZE 0 - - urb_vs_start = 0; - urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; - urb_gs_start = urb_vs_start + urb_vs_size; - urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; - urb_clip_start = urb_gs_start + urb_gs_size; - urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; - urb_sf_start = urb_clip_start + urb_clip_size; - urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; - urb_cs_start = urb_sf_start + urb_sf_size; - urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; - - /* We'll be poking the state buffers that could be in use by the 3d hardware - * here, but we should have synced the 3D engine already in I830PutImage. - */ - - memset (cc_viewport, 0, sizeof (*cc_viewport)); - cc_viewport->min_depth = -1.e35; - cc_viewport->max_depth = 1.e35; - - /* Color calculator state */ - memset(cc_state, 0, sizeof(*cc_state)); - cc_state->cc0.stencil_enable = 0; /* disable stencil */ - cc_state->cc2.depth_test = 0; /* disable depth test */ - cc_state->cc2.logicop_enable = 1; /* enable logic op */ - cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */ - cc_state->cc3.blend_enable = 0; /* disable color blend */ - cc_state->cc3.alpha_test = 0; /* disable alpha test */ - cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5; - cc_state->cc5.dither_enable = 0; /* disable dither */ - cc_state->cc5.logicop_func = 0xc; /* WHITE */ - cc_state->cc5.statistics_enable = 1; - cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; - cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE; - cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE; - - /* Upload system kernel */ - memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static)); - - /* Set up the state buffer for the destination surface */ - memset(dest_surf_state, 0, sizeof(*dest_surf_state)); - dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; - dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; - if (pI830->cpp == 2) { - dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; - } else { - dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - } - dest_surf_state->ss0.writedisable_alpha = 0; - dest_surf_state->ss0.writedisable_red = 0; - dest_surf_state->ss0.writedisable_green = 0; - dest_surf_state->ss0.writedisable_blue = 0; - dest_surf_state->ss0.color_blend = 1; - dest_surf_state->ss0.vert_line_stride = 0; - dest_surf_state->ss0.vert_line_stride_ofs = 0; - dest_surf_state->ss0.mipmap_layout_mode = 0; - dest_surf_state->ss0.render_cache_read_mode = 0; - - dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start; - dest_surf_state->ss2.height = pScrn->virtualY - 1; - dest_surf_state->ss2.width = pScrn->virtualX - 1; - dest_surf_state->ss2.mip_count = 0; - dest_surf_state->ss2.render_target_rotation = 0; - dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1; - - /* Set up the source surface state buffer */ - memset(src_surf_state, 0, sizeof(*src_surf_state)); - src_surf_state->ss0.surface_type = BRW_SURFACE_2D; -/* src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; */ - switch (id) { - case FOURCC_YUY2: - src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL; - break; - case FOURCC_UYVY: - src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY; - break; - } - src_surf_state->ss0.writedisable_alpha = 0; - src_surf_state->ss0.writedisable_red = 0; - src_surf_state->ss0.writedisable_green = 0; - src_surf_state->ss0.writedisable_blue = 0; - src_surf_state->ss0.color_blend = 1; - src_surf_state->ss0.vert_line_stride = 0; - src_surf_state->ss0.vert_line_stride_ofs = 0; - src_surf_state->ss0.mipmap_layout_mode = 0; - src_surf_state->ss0.render_cache_read_mode = 0; - - src_surf_state->ss1.base_addr = pPriv->YBuf0offset; - src_surf_state->ss2.width = width - 1; - src_surf_state->ss2.height = height - 1; - src_surf_state->ss2.mip_count = 0; - src_surf_state->ss2.render_target_rotation = 0; - src_surf_state->ss3.pitch = video_pitch - 1; - - /* Set up a binding table for our two surfaces. Only the PS will use it */ - /* XXX: are these offset from the right place? */ - binding_table[0] = state_base_offset + dest_surf_offset; - binding_table[1] = state_base_offset + src_surf_offset; - - /* Set up the packed YUV source sampler. Doesn't do colorspace conversion. - */ - memset(src_sampler_state, 0, sizeof(*src_sampler_state)); - src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; - src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; - src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; - src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; - src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; - - /* Set up the vertex shader to be disabled (passthrough) */ - memset(vs_state, 0, sizeof(*vs_state)); - vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES; - vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; - vs_state->vs6.vs_enable = 0; - vs_state->vs6.vert_cache_disable = 1; - - /* Set up the SF kernel to do coord interp: for each attribute, - * calculate dA/dx and dA/dy. Hand these interpolation coefficients - * back to SF which then hands pixels off to WM. - */ - - memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); - memset(sf_state, 0, sizeof(*sf_state)); -#if 0 - ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); -#endif - sf_state->thread0.kernel_start_pointer = - (state_base_offset + sf_kernel_offset) >> 6; - sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); - sf_state->sf1.single_program_flow = 1; /* XXX */ - sf_state->sf1.binding_table_entry_count = 0; - sf_state->sf1.thread_priority = 0; - sf_state->sf1.floating_point_mode = 0; /* Mesa does this */ - sf_state->sf1.illegal_op_exception_enable = 1; - sf_state->sf1.mask_stack_exception_enable = 1; - sf_state->sf1.sw_exception_enable = 1; - sf_state->thread2.per_thread_scratch_space = 0; - sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */ - sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */ - sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */ - sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ - sf_state->thread3.urb_entry_read_offset = 0; - sf_state->thread3.dispatch_grf_start_reg = 3; - sf_state->thread4.max_threads = SF_MAX_THREADS - 1; - sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; - sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES; - sf_state->thread4.stats_enable = 1; - sf_state->sf5.viewport_transform = FALSE; /* skip viewport */ - sf_state->sf6.cull_mode = BRW_CULLMODE_NONE; - sf_state->sf6.scissor = 0; - sf_state->sf7.trifan_pv = 2; - sf_state->sf6.dest_org_vbias = 0x8; - sf_state->sf6.dest_org_hbias = 0x8; - - memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static)); -#if 0 - ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); -#endif - memset (wm_state, 0, sizeof (*wm_state)); - wm_state->thread0.kernel_start_pointer = - (state_base_offset + ps_kernel_offset) >> 6; - wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF); - wm_state->thread1.single_program_flow = 1; /* XXX */ - wm_state->thread1.binding_table_entry_count = 2; - /* Though we never use the scratch space in our WM kernel, it has to be - * set, and the minimum allocation is 1024 bytes. - */ - wm_state->thread2.scratch_space_base_pointer = (state_base_offset + - wm_scratch_offset) >> 10; - wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */ - wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */ - wm_state->thread3.const_urb_entry_read_length = 0; - wm_state->thread3.const_urb_entry_read_offset = 0; - wm_state->thread3.urb_entry_read_length = 1; /* XXX */ - wm_state->thread3.urb_entry_read_offset = 0; /* XXX */ - wm_state->wm4.stats_enable = 1; - wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; - wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */ - wm_state->wm5.max_threads = PS_MAX_THREADS - 1; - wm_state->wm5.thread_dispatch_enable = 1; - wm_state->wm5.enable_16_pix = 1; - wm_state->wm5.enable_8_pix = 0; - wm_state->wm5.early_depth_test = 1; - - { - BEGIN_LP_RING(2); - OUT_RING(MI_FLUSH | - MI_STATE_INSTRUCTION_CACHE_FLUSH | - BRW_MI_GLOBAL_SNAPSHOT_RESET); - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); - } - -/* brw_debug (pScrn, "before base address modify"); */ - { BEGIN_LP_RING(12); - /* Match Mesa driver setup */ - OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); - - /* Mesa does this. Who knows... */ - OUT_RING(BRW_CS_URB_STATE | 0); - OUT_RING((0 << 4) | /* URB Entry Allocation Size */ - (0 << 0)); /* Number of URB Entries */ - - /* Zero out the two base address registers so all offsets are absolute */ - OUT_RING(BRW_STATE_BASE_ADDRESS | 4); - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */ - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */ - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */ - OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* general state max addr, disabled */ - OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* media object state max addr, disabled */ - - /* Set system instruction pointer */ - OUT_RING(BRW_STATE_SIP | 0); - OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */ - - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); } - -/* brw_debug (pScrn, "after base address modify"); */ - - { BEGIN_LP_RING(42); - /* Enable VF statistics */ - OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1); - - /* Pipe control */ - OUT_RING(BRW_PIPE_CONTROL | - BRW_PIPE_CONTROL_NOWRITE | - BRW_PIPE_CONTROL_IS_FLUSH | - 2); - OUT_RING(0); /* Destination address */ - OUT_RING(0); /* Immediate data low DW */ - OUT_RING(0); /* Immediate data high DW */ - - /* Binding table pointers */ - OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); - OUT_RING(0); /* vs */ - OUT_RING(0); /* gs */ - OUT_RING(0); /* clip */ - OUT_RING(0); /* sf */ - /* Only the PS uses the binding table */ - OUT_RING(state_base_offset + binding_table_offset); /* ps */ - - /* Blend constant color (magenta is fun) */ - OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3); - OUT_RING(float_to_uint (1.0)); - OUT_RING(float_to_uint (0.0)); - OUT_RING(float_to_uint (1.0)); - OUT_RING(float_to_uint (1.0)); - - /* The drawing rectangle clipping is always on. Set it to values that - * shouldn't do any clipping. - */ - OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */ - OUT_RING(0x00000000); /* ymin, xmin */ - OUT_RING((pScrn->virtualX - 1) | - (pScrn->virtualY - 1) << 16); /* ymax, xmax */ - OUT_RING(0x00000000); /* yorigin, xorigin */ - - /* skip the depth buffer */ - /* skip the polygon stipple */ - /* skip the polygon stipple offset */ - /* skip the line stipple */ - - /* Set the pointers to the 3d pipeline state */ - OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5); - OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */ - OUT_RING(BRW_GS_DISABLE); /* disable GS, resulting in passthrough */ - OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */ - OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */ - OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */ - OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */ - - /* URB fence */ - OUT_RING(BRW_URB_FENCE | - UF0_CS_REALLOC | - UF0_SF_REALLOC | - UF0_CLIP_REALLOC | - UF0_GS_REALLOC | - UF0_VS_REALLOC | - 1); - OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | - ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | - ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); - OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | - ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); - - /* Constant buffer state */ - OUT_RING(BRW_CS_URB_STATE | 0); - OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */ - (URB_CS_ENTRIES << 0)); /* Number of URB Entries */ - - /* Set up the pointer to our vertex buffer */ - OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2); - OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) | - VB0_VERTEXDATA | - ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */ - OUT_RING(state_base_offset + vb_offset); - OUT_RING(3); /* four corners to our rectangle */ - - /* Set up our vertex elements, sourced from the single vertex buffer. */ - OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3); - /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */ - OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | - (0 << VE0_OFFSET_SHIFT)); - OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | - (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); - /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */ - OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | - (8 << VE0_OFFSET_SHIFT)); - OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | - (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); - - OUT_RING(MI_NOOP); /* pad to quadword */ - ADVANCE_LP_RING(); } - - dxo = dstRegion->extents.x1; - dyo = dstRegion->extents.y1; - - pbox = REGION_RECTS(dstRegion); - nbox = REGION_NUM_RECTS(dstRegion); - while (nbox--) - { - int box_x1 = pbox->x1; - int box_y1 = pbox->y1; - int box_x2 = pbox->x2; - int box_y2 = pbox->y2; - int i; - float src_scale_x, src_scale_y; - - if (!first_output) { - /* Since we use the same little vertex buffer over and over, sync for - * subsequent rectangles. - */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } - } - - pbox++; - - /* Use normalized texture coordinates */ - src_scale_x = (float)1.0 / (float)drw_w; - src_scale_y = (float)1.0 / (float)drw_h; - - i = 0; - vb[i++] = (box_x2 - dxo) * src_scale_x; - vb[i++] = (box_y2 - dyo) * src_scale_y; - vb[i++] = (float) box_x2; - vb[i++] = (float) box_y2; - - vb[i++] = (box_x1 - dxo) * src_scale_x; - vb[i++] = (box_y2 - dyo) * src_scale_y; - vb[i++] = (float) box_x1; - vb[i++] = (float) box_y2; - - vb[i++] = (box_x1 - dxo) * src_scale_x; - vb[i++] = (box_y1 - dyo) * src_scale_y; - vb[i++] = (float) box_x1; - vb[i++] = (float) box_y1; - -#if 0 - ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", - INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), - INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); - - OUTREG(BRW_VF_CTL, - BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID | - BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX | - BRW_VF_CTL_SNAPSHOT_ENABLE); - OUTREG(BRW_VF_STRG_VAL, 0); -#endif - -#if 0 - OUTREG(BRW_VS_CTL, - BRW_VS_CTL_SNAPSHOT_ALL_THREADS | - BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT | - BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE); - - OUTREG(BRW_VS_STRG_VAL, 0); -#endif - -#if WATCH_SF - OUTREG(BRW_SF_CTL, - BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT | - BRW_SF_CTL_SNAPSHOT_ALL_THREADS | - BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE); - OUTREG(BRW_SF_STRG_VAL, 0); -#endif - -#if WATCH_WIZ - OUTREG(BRW_WIZ_CTL, - BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE | - BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS | - BRW_WIZ_CTL_SNAPSHOT_ENABLE); - OUTREG(BRW_WIZ_STRG_VAL, - (box_x1) | (box_y1 << 16)); -#endif - -#if 0 - OUTREG(BRW_TS_CTL, - BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR | - BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS | - BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS | - BRW_TS_CTL_SNAPSHOT_ENABLE); -#endif - - BEGIN_LP_RING(6); - OUT_RING(BRW_3DPRIMITIVE | - BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | - (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | - (0 << 9) | /* CTG - indirect vertex count */ - 4); - OUT_RING(3); /* vertex count per instance */ - OUT_RING(0); /* start vertex offset */ - OUT_RING(1); /* single instance */ - OUT_RING(0); /* start instance location */ - OUT_RING(0); /* index buffer offset, ignored */ - ADVANCE_LP_RING(); - -#if 0 - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_VF_CTL); - if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_VF_RDATA); - OUTREG(BRW_VF_CTL, 0); - ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata); -#endif - -#if 0 - for (j = 0; j < 1000000; j++) { - ctl = INREG(BRW_VS_CTL); - if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_VS_RDATA); - for (k = 0; k <= 3; k++) { - OUTREG(BRW_VS_CTL, - BRW_VS_CTL_SNAPSHOT_COMPLETE | - (k << 8)); - rdata = INREG(BRW_VS_RDATA); - ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata); - } - - OUTREG(BRW_VS_CTL, 0); -#endif - -#if WATCH_SF - for (j = 0; j < 1000000; j++) { - ctl = INREG(BRW_SF_CTL); - if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE) - break; - } - - for (k = 0; k <= 7; k++) { - OUTREG(BRW_SF_CTL, - BRW_SF_CTL_SNAPSHOT_COMPLETE | - (k << 8)); - rdata = INREG(BRW_SF_RDATA); - ErrorF ("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata); - } - - OUTREG(BRW_SF_CTL, 0); -#endif - -#if WATCH_WIZ - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_WIZ_CTL); - if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_WIZ_RDATA); - OUTREG(BRW_WIZ_CTL, 0); - ErrorF ("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata); -#endif - -#if 0 - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_TS_CTL); - if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_TS_RDATA); - OUTREG(BRW_TS_CTL, 0); - ErrorF ("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata); - - ErrorF ("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", - INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), - INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); -#endif - -#if 0 - for (j = 0; j < 256; j++) { - OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT); - rdata = INREG(BRW_TD_RDATA); - ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata); - } -#endif - first_output = FALSE; - if (pI830->AccelInfoRec) - pI830->AccelInfoRec->NeedToSync = TRUE; - } - - if (pI830->AccelInfoRec) - (*pI830->AccelInfoRec->Sync)(pScrn); -#if WATCH_STATS - i830_dump_error_state (pScrn); -#endif -} #ifdef I830_USE_EXA static void @@ -3162,9 +2375,9 @@ I830PutImage(ScrnInfoPtr pScrn, I830DisplayVideo(pScrn, destId, width, height, dstPitch, x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); } else if (IS_I965G(pI830)) { - BroadwaterDisplayVideoTextured (pScrn, pPriv, destId, clipBoxes, width, height, - dstPitch, x1, y1, x2, y2, - src_w, src_h, drw_w, drw_h, pDraw); + I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, + dstPitch, x1, y1, x2, y2, + src_w, src_h, drw_w, drw_h, pDraw); } else { I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, dstPitch, x1, y1, x2, y2, diff --git a/src/i830_video.h b/src/i830_video.h index 12a5bda2..a00cd508 100644 --- a/src/i830_video.h +++ b/src/i830_video.h @@ -88,3 +88,11 @@ void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, short src_w, short src_h, short drw_w, short drw_h, DrawablePtr pDraw); + +void I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, + int id, RegionPtr dstRegion, short width, + short height, int video_pitch, + int x1, int y1, int x2, int y2, + short src_w, short src_h, + short drw_w, short drw_h, + DrawablePtr pDraw); diff --git a/src/i965_video.c b/src/i965_video.c new file mode 100644 index 00000000..3677d9d3 --- /dev/null +++ b/src/i965_video.c @@ -0,0 +1,827 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * Keith Packard + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86xv.h" +#include "fourcc.h" + +#include "i830.h" +#include "i830_video.h" +#include "brw_defines.h" +#include "brw_structs.h" + +static const CARD32 sip_kernel_static[][4] = { +/* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */ + { 0x00000030, 0x20000108, 0x00001220, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +}; + +/* + * this program computes dA/dx and dA/dy for the texture coordinates along + * with the base texture coordinate. It was extracted from the Mesa driver. + * It uses about 10 GRF registers. + */ + +#define SF_KERNEL_NUM_GRF 16 +#define SF_MAX_THREADS 1 + +static const CARD32 sf_kernel_static[][4] = { +#include "sf_prog.h" +}; + +/* + * Ok, this kernel picks up the required data flow values in g0 and g1 + * and passes those along in m0 and m1. In m2-m9, it sticks constant + * values (bright pink). + */ + +/* Our PS kernel uses less than 32 GRF registers (about 20) */ +#define PS_KERNEL_NUM_GRF 32 +#define PS_MAX_THREADS 32 + +#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1) + +static const CARD32 ps_kernel_static[][4] = { +#include "wm_prog.h" +}; + +#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define WM_BINDING_TABLE_ENTRIES 2 + +static CARD32 float_to_uint (float f) { + union {CARD32 i; float f;} x; + x.f = f; + return x.i; +} + +#if 0 +static struct { + CARD32 svg_ctl; + char *name; +} svg_ctl_bits[] = { + { BRW_SVG_CTL_GS_BA, "General State Base Address" }, + { BRW_SVG_CTL_SS_BA, "Surface State Base Address" }, + { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" }, + { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" }, + { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" }, + { BRW_SVG_CTL_SIP, "System Instruction Pointer" }, + { 0, 0 }, +}; + +static void +brw_debug (ScrnInfoPtr pScrn, char *when) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + CARD32 v; + + I830Sync (pScrn); + ErrorF("brw_debug: %s\n", when); + for (i = 0; svg_ctl_bits[i].name; i++) { + OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl); + v = INREG(BRW_SVG_RDATA); + ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v); + } +} +#endif + +#define WATCH_SF 0 +#define WATCH_WIZ 0 +#define WATCH_STATS 0 + +void +I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, + RegionPtr dstRegion, + short width, short height, int video_pitch, + int x1, int y1, int x2, int y2, + short src_w, short src_h, + short drw_w, short drw_h, + DrawablePtr pDraw) +{ + I830Ptr pI830 = I830PTR(pScrn); + BoxPtr pbox; + int nbox, dxo, dyo; + int urb_vs_start, urb_vs_size; + int urb_gs_start, urb_gs_size; + int urb_clip_start, urb_clip_size; + int urb_sf_start, urb_sf_size; + int urb_cs_start, urb_cs_size; + struct brw_surface_state *dest_surf_state; + struct brw_surface_state *src_surf_state; + struct brw_sampler_state *src_sampler_state; + struct brw_vs_unit_state *vs_state; + struct brw_sf_unit_state *sf_state; + struct brw_wm_unit_state *wm_state; + struct brw_cc_unit_state *cc_state; + struct brw_cc_viewport *cc_viewport; + struct brw_instruction *sf_kernel; + struct brw_instruction *ps_kernel; + struct brw_instruction *sip_kernel; + float *vb; + CARD32 *binding_table; + Bool first_output = TRUE; + int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset; + int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset; + int wm_scratch_offset; + int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset; + int binding_table_offset; + int next_offset, total_state_size; + int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */ + char *state_base; + int state_base_offset; + +#if 0 + ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height, + video_pitch); +#endif + + /* enable debug */ + OUTREG (INST_PM, + (1 << (16 + 4)) | + (1 << 4)); +#if 0 + ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM)); +#endif + + assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2)); + + /* Tell the rotation code that we have stomped its invariant state by + * setting a high bit. We don't use any invariant 3D state for video, so we + * don't have to worry about it ourselves. + */ + *pI830->used3D |= 1 << 30; + +#ifdef XF86DRI + /* Tell the DRI that we're smashing its state. */ + if (pI830->directRenderingEnabled) { + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + + pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); + } +#endif /* XF86DRI */ + + next_offset = 0; + + /* Set up our layout of state in framebuffer. First the general state: */ + vs_offset = ALIGN(next_offset, 64); + next_offset = vs_offset + sizeof(*vs_state); + sf_offset = ALIGN(next_offset, 32); + next_offset = sf_offset + sizeof(*sf_state); + wm_offset = ALIGN(next_offset, 32); + next_offset = wm_offset + sizeof(*wm_state); + wm_scratch_offset = ALIGN(next_offset, 1024); + next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS; + cc_offset = ALIGN(next_offset, 32); + next_offset = cc_offset + sizeof(*cc_state); + + sf_kernel_offset = ALIGN(next_offset, 64); + next_offset = sf_kernel_offset + sizeof (sf_kernel_static); + ps_kernel_offset = ALIGN(next_offset, 64); + next_offset = ps_kernel_offset + sizeof (ps_kernel_static); + sip_kernel_offset = ALIGN(next_offset, 64); + next_offset = sip_kernel_offset + sizeof (sip_kernel_static); + cc_viewport_offset = ALIGN(next_offset, 32); + next_offset = cc_viewport_offset + sizeof(*cc_viewport); + + src_sampler_offset = ALIGN(next_offset, 32); + next_offset = src_sampler_offset + sizeof(*src_sampler_state); + + /* Align VB to native size of elements, for safety */ + vb_offset = ALIGN(next_offset, 8); + next_offset = vb_offset + vb_size; + + /* And then the general state: */ + dest_surf_offset = ALIGN(next_offset, 32); + next_offset = dest_surf_offset + sizeof(*dest_surf_state); + src_surf_offset = ALIGN(next_offset, 32); + next_offset = src_surf_offset + sizeof(*src_surf_state); + binding_table_offset = ALIGN(next_offset, 32); + next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4); + + /* Allocate an area in framebuffer for our state layout we just set up */ + total_state_size = next_offset; + assert (total_state_size < BRW_LINEAR_EXTRA); + + /* + * Use the extra space allocated at the end of the Xv buffer + */ + state_base_offset = pPriv->extra_offset; + state_base_offset = ALIGN(state_base_offset, 64); + + state_base = (char *)(pI830->FbBase + state_base_offset); + /* Set up our pointers to state structures in framebuffer. It would probably + * be a good idea to fill these structures out in system memory and then dump + * them there, instead. + */ + vs_state = (void *)(state_base + vs_offset); + sf_state = (void *)(state_base + sf_offset); + wm_state = (void *)(state_base + wm_offset); + cc_state = (void *)(state_base + cc_offset); + sf_kernel = (void *)(state_base + sf_kernel_offset); + ps_kernel = (void *)(state_base + ps_kernel_offset); + sip_kernel = (void *)(state_base + sip_kernel_offset); + + cc_viewport = (void *)(state_base + cc_viewport_offset); + dest_surf_state = (void *)(state_base + dest_surf_offset); + src_surf_state = (void *)(state_base + src_surf_offset); + src_sampler_state = (void *)(state_base + src_sampler_offset); + binding_table = (void *)(state_base + binding_table_offset); + vb = (void *)(state_base + vb_offset); + + /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it. + * A VUE consists of a 256-bit vertex header followed by the vertex data, + * which in our case is 4 floats (128 bits), thus a single 512-bit URB + * entry. + */ +#define URB_VS_ENTRIES 8 +#define URB_VS_ENTRY_SIZE 1 + +#define URB_GS_ENTRIES 0 +#define URB_GS_ENTRY_SIZE 0 + +#define URB_CLIP_ENTRIES 0 +#define URB_CLIP_ENTRY_SIZE 0 + + /* The SF kernel we use outputs only 4 256-bit registers, leading to an + * entry size of 2 512-bit URBs. We don't need to have many entries to + * output as we're generally working on large rectangles and don't care + * about having WM threads running on different rectangles simultaneously. + */ +#define URB_SF_ENTRIES 1 +#define URB_SF_ENTRY_SIZE 2 + +#define URB_CS_ENTRIES 0 +#define URB_CS_ENTRY_SIZE 0 + + urb_vs_start = 0; + urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; + urb_gs_start = urb_vs_start + urb_vs_size; + urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; + urb_clip_start = urb_gs_start + urb_gs_size; + urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; + urb_sf_start = urb_clip_start + urb_clip_size; + urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; + urb_cs_start = urb_sf_start + urb_sf_size; + urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; + + /* We'll be poking the state buffers that could be in use by the 3d hardware + * here, but we should have synced the 3D engine already in I830PutImage. + */ + + memset (cc_viewport, 0, sizeof (*cc_viewport)); + cc_viewport->min_depth = -1.e35; + cc_viewport->max_depth = 1.e35; + + /* Color calculator state */ + memset(cc_state, 0, sizeof(*cc_state)); + cc_state->cc0.stencil_enable = 0; /* disable stencil */ + cc_state->cc2.depth_test = 0; /* disable depth test */ + cc_state->cc2.logicop_enable = 1; /* enable logic op */ + cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */ + cc_state->cc3.blend_enable = 0; /* disable color blend */ + cc_state->cc3.alpha_test = 0; /* disable alpha test */ + cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5; + cc_state->cc5.dither_enable = 0; /* disable dither */ + cc_state->cc5.logicop_func = 0xc; /* WHITE */ + cc_state->cc5.statistics_enable = 1; + cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; + cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE; + cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE; + + /* Upload system kernel */ + memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static)); + + /* Set up the state buffer for the destination surface */ + memset(dest_surf_state, 0, sizeof(*dest_surf_state)); + dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; + dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; + if (pI830->cpp == 2) { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; + } else { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + } + dest_surf_state->ss0.writedisable_alpha = 0; + dest_surf_state->ss0.writedisable_red = 0; + dest_surf_state->ss0.writedisable_green = 0; + dest_surf_state->ss0.writedisable_blue = 0; + dest_surf_state->ss0.color_blend = 1; + dest_surf_state->ss0.vert_line_stride = 0; + dest_surf_state->ss0.vert_line_stride_ofs = 0; + dest_surf_state->ss0.mipmap_layout_mode = 0; + dest_surf_state->ss0.render_cache_read_mode = 0; + + dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start; + dest_surf_state->ss2.height = pScrn->virtualY - 1; + dest_surf_state->ss2.width = pScrn->virtualX - 1; + dest_surf_state->ss2.mip_count = 0; + dest_surf_state->ss2.render_target_rotation = 0; + dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1; + + /* Set up the source surface state buffer */ + memset(src_surf_state, 0, sizeof(*src_surf_state)); + src_surf_state->ss0.surface_type = BRW_SURFACE_2D; +/* src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; */ + switch (id) { + case FOURCC_YUY2: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL; + break; + case FOURCC_UYVY: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY; + break; + } + src_surf_state->ss0.writedisable_alpha = 0; + src_surf_state->ss0.writedisable_red = 0; + src_surf_state->ss0.writedisable_green = 0; + src_surf_state->ss0.writedisable_blue = 0; + src_surf_state->ss0.color_blend = 1; + src_surf_state->ss0.vert_line_stride = 0; + src_surf_state->ss0.vert_line_stride_ofs = 0; + src_surf_state->ss0.mipmap_layout_mode = 0; + src_surf_state->ss0.render_cache_read_mode = 0; + + src_surf_state->ss1.base_addr = pPriv->YBuf0offset; + src_surf_state->ss2.width = width - 1; + src_surf_state->ss2.height = height - 1; + src_surf_state->ss2.mip_count = 0; + src_surf_state->ss2.render_target_rotation = 0; + src_surf_state->ss3.pitch = video_pitch - 1; + + /* Set up a binding table for our two surfaces. Only the PS will use it */ + /* XXX: are these offset from the right place? */ + binding_table[0] = state_base_offset + dest_surf_offset; + binding_table[1] = state_base_offset + src_surf_offset; + + /* Set up the packed YUV source sampler. Doesn't do colorspace conversion. + */ + memset(src_sampler_state, 0, sizeof(*src_sampler_state)); + src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + + /* Set up the vertex shader to be disabled (passthrough) */ + memset(vs_state, 0, sizeof(*vs_state)); + vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES; + vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; + vs_state->vs6.vs_enable = 0; + vs_state->vs6.vert_cache_disable = 1; + + /* Set up the SF kernel to do coord interp: for each attribute, + * calculate dA/dx and dA/dy. Hand these interpolation coefficients + * back to SF which then hands pixels off to WM. + */ + + memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); + memset(sf_state, 0, sizeof(*sf_state)); +#if 0 + ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); +#endif + sf_state->thread0.kernel_start_pointer = + (state_base_offset + sf_kernel_offset) >> 6; + sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); + sf_state->sf1.single_program_flow = 1; /* XXX */ + sf_state->sf1.binding_table_entry_count = 0; + sf_state->sf1.thread_priority = 0; + sf_state->sf1.floating_point_mode = 0; /* Mesa does this */ + sf_state->sf1.illegal_op_exception_enable = 1; + sf_state->sf1.mask_stack_exception_enable = 1; + sf_state->sf1.sw_exception_enable = 1; + sf_state->thread2.per_thread_scratch_space = 0; + sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */ + sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */ + sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */ + sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ + sf_state->thread3.urb_entry_read_offset = 0; + sf_state->thread3.dispatch_grf_start_reg = 3; + sf_state->thread4.max_threads = SF_MAX_THREADS - 1; + sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; + sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES; + sf_state->thread4.stats_enable = 1; + sf_state->sf5.viewport_transform = FALSE; /* skip viewport */ + sf_state->sf6.cull_mode = BRW_CULLMODE_NONE; + sf_state->sf6.scissor = 0; + sf_state->sf7.trifan_pv = 2; + sf_state->sf6.dest_org_vbias = 0x8; + sf_state->sf6.dest_org_hbias = 0x8; + + memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static)); +#if 0 + ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); +#endif + memset (wm_state, 0, sizeof (*wm_state)); + wm_state->thread0.kernel_start_pointer = + (state_base_offset + ps_kernel_offset) >> 6; + wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF); + wm_state->thread1.single_program_flow = 1; /* XXX */ + wm_state->thread1.binding_table_entry_count = 2; + /* Though we never use the scratch space in our WM kernel, it has to be + * set, and the minimum allocation is 1024 bytes. + */ + wm_state->thread2.scratch_space_base_pointer = (state_base_offset + + wm_scratch_offset) >> 10; + wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */ + wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */ + wm_state->thread3.const_urb_entry_read_length = 0; + wm_state->thread3.const_urb_entry_read_offset = 0; + wm_state->thread3.urb_entry_read_length = 1; /* XXX */ + wm_state->thread3.urb_entry_read_offset = 0; /* XXX */ + wm_state->wm4.stats_enable = 1; + wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; + wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */ + wm_state->wm5.max_threads = PS_MAX_THREADS - 1; + wm_state->wm5.thread_dispatch_enable = 1; + wm_state->wm5.enable_16_pix = 1; + wm_state->wm5.enable_8_pix = 0; + wm_state->wm5.early_depth_test = 1; + + { + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | + MI_STATE_INSTRUCTION_CACHE_FLUSH | + BRW_MI_GLOBAL_SNAPSHOT_RESET); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } + +/* brw_debug (pScrn, "before base address modify"); */ + { BEGIN_LP_RING(12); + /* Match Mesa driver setup */ + OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); + + /* Mesa does this. Who knows... */ + OUT_RING(BRW_CS_URB_STATE | 0); + OUT_RING((0 << 4) | /* URB Entry Allocation Size */ + (0 << 0)); /* Number of URB Entries */ + + /* Zero out the two base address registers so all offsets are absolute */ + OUT_RING(BRW_STATE_BASE_ADDRESS | 4); + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */ + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */ + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */ + OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* general state max addr, disabled */ + OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* media object state max addr, disabled */ + + /* Set system instruction pointer */ + OUT_RING(BRW_STATE_SIP | 0); + OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */ + + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); } + +/* brw_debug (pScrn, "after base address modify"); */ + + { BEGIN_LP_RING(42); + /* Enable VF statistics */ + OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1); + + /* Pipe control */ + OUT_RING(BRW_PIPE_CONTROL | + BRW_PIPE_CONTROL_NOWRITE | + BRW_PIPE_CONTROL_IS_FLUSH | + 2); + OUT_RING(0); /* Destination address */ + OUT_RING(0); /* Immediate data low DW */ + OUT_RING(0); /* Immediate data high DW */ + + /* Binding table pointers */ + OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); + OUT_RING(0); /* vs */ + OUT_RING(0); /* gs */ + OUT_RING(0); /* clip */ + OUT_RING(0); /* sf */ + /* Only the PS uses the binding table */ + OUT_RING(state_base_offset + binding_table_offset); /* ps */ + + /* Blend constant color (magenta is fun) */ + OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3); + OUT_RING(float_to_uint (1.0)); + OUT_RING(float_to_uint (0.0)); + OUT_RING(float_to_uint (1.0)); + OUT_RING(float_to_uint (1.0)); + + /* The drawing rectangle clipping is always on. Set it to values that + * shouldn't do any clipping. + */ + OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */ + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING((pScrn->virtualX - 1) | + (pScrn->virtualY - 1) << 16); /* ymax, xmax */ + OUT_RING(0x00000000); /* yorigin, xorigin */ + + /* skip the depth buffer */ + /* skip the polygon stipple */ + /* skip the polygon stipple offset */ + /* skip the line stipple */ + + /* Set the pointers to the 3d pipeline state */ + OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5); + OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */ + OUT_RING(BRW_GS_DISABLE); /* disable GS, resulting in passthrough */ + OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */ + OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */ + OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */ + OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */ + + /* URB fence */ + OUT_RING(BRW_URB_FENCE | + UF0_CS_REALLOC | + UF0_SF_REALLOC | + UF0_CLIP_REALLOC | + UF0_GS_REALLOC | + UF0_VS_REALLOC | + 1); + OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | + ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | + ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); + OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | + ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); + + /* Constant buffer state */ + OUT_RING(BRW_CS_URB_STATE | 0); + OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */ + (URB_CS_ENTRIES << 0)); /* Number of URB Entries */ + + /* Set up the pointer to our vertex buffer */ + OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2); + OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) | + VB0_VERTEXDATA | + ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */ + OUT_RING(state_base_offset + vb_offset); + OUT_RING(3); /* four corners to our rectangle */ + + /* Set up our vertex elements, sourced from the single vertex buffer. */ + OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3); + /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */ + OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | + VE0_VALID | + (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | + (0 << VE0_OFFSET_SHIFT)); + OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | + (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | + (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */ + OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | + VE0_VALID | + (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | + (8 << VE0_OFFSET_SHIFT)); + OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | + (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | + (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + + OUT_RING(MI_NOOP); /* pad to quadword */ + ADVANCE_LP_RING(); } + + dxo = dstRegion->extents.x1; + dyo = dstRegion->extents.y1; + + pbox = REGION_RECTS(dstRegion); + nbox = REGION_NUM_RECTS(dstRegion); + while (nbox--) + { + int box_x1 = pbox->x1; + int box_y1 = pbox->y1; + int box_x2 = pbox->x2; + int box_y2 = pbox->y2; + int i; + float src_scale_x, src_scale_y; + + if (!first_output) { + /* Since we use the same little vertex buffer over and over, sync for + * subsequent rectangles. + */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + } + + pbox++; + + /* Use normalized texture coordinates */ + src_scale_x = (float)1.0 / (float)drw_w; + src_scale_y = (float)1.0 / (float)drw_h; + + i = 0; + vb[i++] = (box_x2 - dxo) * src_scale_x; + vb[i++] = (box_y2 - dyo) * src_scale_y; + vb[i++] = (float) box_x2; + vb[i++] = (float) box_y2; + + vb[i++] = (box_x1 - dxo) * src_scale_x; + vb[i++] = (box_y2 - dyo) * src_scale_y; + vb[i++] = (float) box_x1; + vb[i++] = (float) box_y2; + + vb[i++] = (box_x1 - dxo) * src_scale_x; + vb[i++] = (box_y1 - dyo) * src_scale_y; + vb[i++] = (float) box_x1; + vb[i++] = (float) box_y1; + +#if 0 + ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", + INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), + INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); + + OUTREG(BRW_VF_CTL, + BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID | + BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX | + BRW_VF_CTL_SNAPSHOT_ENABLE); + OUTREG(BRW_VF_STRG_VAL, 0); +#endif + +#if 0 + OUTREG(BRW_VS_CTL, + BRW_VS_CTL_SNAPSHOT_ALL_THREADS | + BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT | + BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE); + + OUTREG(BRW_VS_STRG_VAL, 0); +#endif + +#if WATCH_SF + OUTREG(BRW_SF_CTL, + BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT | + BRW_SF_CTL_SNAPSHOT_ALL_THREADS | + BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE); + OUTREG(BRW_SF_STRG_VAL, 0); +#endif + +#if WATCH_WIZ + OUTREG(BRW_WIZ_CTL, + BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE | + BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS | + BRW_WIZ_CTL_SNAPSHOT_ENABLE); + OUTREG(BRW_WIZ_STRG_VAL, + (box_x1) | (box_y1 << 16)); +#endif + +#if 0 + OUTREG(BRW_TS_CTL, + BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR | + BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS | + BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS | + BRW_TS_CTL_SNAPSHOT_ENABLE); +#endif + + BEGIN_LP_RING(6); + OUT_RING(BRW_3DPRIMITIVE | + BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | + (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | + (0 << 9) | /* CTG - indirect vertex count */ + 4); + OUT_RING(3); /* vertex count per instance */ + OUT_RING(0); /* start vertex offset */ + OUT_RING(1); /* single instance */ + OUT_RING(0); /* start instance location */ + OUT_RING(0); /* index buffer offset, ignored */ + ADVANCE_LP_RING(); + +#if 0 + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_VF_CTL); + if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_VF_RDATA); + OUTREG(BRW_VF_CTL, 0); + ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata); +#endif + +#if 0 + for (j = 0; j < 1000000; j++) { + ctl = INREG(BRW_VS_CTL); + if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_VS_RDATA); + for (k = 0; k <= 3; k++) { + OUTREG(BRW_VS_CTL, + BRW_VS_CTL_SNAPSHOT_COMPLETE | + (k << 8)); + rdata = INREG(BRW_VS_RDATA); + ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata); + } + + OUTREG(BRW_VS_CTL, 0); +#endif + +#if WATCH_SF + for (j = 0; j < 1000000; j++) { + ctl = INREG(BRW_SF_CTL); + if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE) + break; + } + + for (k = 0; k <= 7; k++) { + OUTREG(BRW_SF_CTL, + BRW_SF_CTL_SNAPSHOT_COMPLETE | + (k << 8)); + rdata = INREG(BRW_SF_RDATA); + ErrorF ("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata); + } + + OUTREG(BRW_SF_CTL, 0); +#endif + +#if WATCH_WIZ + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_WIZ_CTL); + if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_WIZ_RDATA); + OUTREG(BRW_WIZ_CTL, 0); + ErrorF ("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata); +#endif + +#if 0 + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_TS_CTL); + if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_TS_RDATA); + OUTREG(BRW_TS_CTL, 0); + ErrorF ("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata); + + ErrorF ("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", + INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), + INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); +#endif + +#if 0 + for (j = 0; j < 256; j++) { + OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT); + rdata = INREG(BRW_TD_RDATA); + ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata); + } +#endif + first_output = FALSE; + if (pI830->AccelInfoRec) + pI830->AccelInfoRec->NeedToSync = TRUE; + } + + if (pI830->AccelInfoRec) + (*pI830->AccelInfoRec->Sync)(pScrn); +#if WATCH_STATS + i830_dump_error_state (pScrn); +#endif +} From 150010d2f20f4a57f8507eba8762e36966b0f426 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 17:57:34 -0800 Subject: [PATCH 03/37] reformat i965_video.c to 4-space indents, 80 columns, no trailing whitespace. --- src/i965_video.c | 1246 +++++++++++++++++++++++----------------------- 1 file changed, 631 insertions(+), 615 deletions(-) diff --git a/src/i965_video.c b/src/i965_video.c index 3677d9d3..07ee3605 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -62,7 +62,7 @@ static const CARD32 sip_kernel_static[][4] = { /* nop (4) g0<1>UD { align1 + } */ { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, }; - + /* * this program computes dA/dx and dA/dy for the texture coordinates along * with the base texture coordinate. It was extracted from the Mesa driver. @@ -98,39 +98,39 @@ static const CARD32 ps_kernel_static[][4] = { #define WM_BINDING_TABLE_ENTRIES 2 static CARD32 float_to_uint (float f) { - union {CARD32 i; float f;} x; - x.f = f; - return x.i; + union {CARD32 i; float f;} x; + x.f = f; + return x.i; } #if 0 static struct { - CARD32 svg_ctl; - char *name; + CARD32 svg_ctl; + char *name; } svg_ctl_bits[] = { - { BRW_SVG_CTL_GS_BA, "General State Base Address" }, - { BRW_SVG_CTL_SS_BA, "Surface State Base Address" }, - { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" }, - { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" }, - { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" }, - { BRW_SVG_CTL_SIP, "System Instruction Pointer" }, - { 0, 0 }, + { BRW_SVG_CTL_GS_BA, "General State Base Address" }, + { BRW_SVG_CTL_SS_BA, "Surface State Base Address" }, + { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" }, + { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" }, + { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" }, + { BRW_SVG_CTL_SIP, "System Instruction Pointer" }, + { 0, 0 }, }; static void brw_debug (ScrnInfoPtr pScrn, char *when) { - I830Ptr pI830 = I830PTR(pScrn); - int i; - CARD32 v; - - I830Sync (pScrn); - ErrorF("brw_debug: %s\n", when); - for (i = 0; svg_ctl_bits[i].name; i++) { - OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl); - v = INREG(BRW_SVG_RDATA); - ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v); - } + I830Ptr pI830 = I830PTR(pScrn); + int i; + CARD32 v; + + I830Sync (pScrn); + ErrorF("brw_debug: %s\n", when); + for (i = 0; svg_ctl_bits[i].name; i++) { + OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl); + v = INREG(BRW_SVG_RDATA); + ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v); + } } #endif @@ -147,681 +147,697 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, short drw_w, short drw_h, DrawablePtr pDraw) { - I830Ptr pI830 = I830PTR(pScrn); - BoxPtr pbox; - int nbox, dxo, dyo; - int urb_vs_start, urb_vs_size; - int urb_gs_start, urb_gs_size; - int urb_clip_start, urb_clip_size; - int urb_sf_start, urb_sf_size; - int urb_cs_start, urb_cs_size; - struct brw_surface_state *dest_surf_state; - struct brw_surface_state *src_surf_state; - struct brw_sampler_state *src_sampler_state; - struct brw_vs_unit_state *vs_state; - struct brw_sf_unit_state *sf_state; - struct brw_wm_unit_state *wm_state; - struct brw_cc_unit_state *cc_state; - struct brw_cc_viewport *cc_viewport; - struct brw_instruction *sf_kernel; - struct brw_instruction *ps_kernel; - struct brw_instruction *sip_kernel; - float *vb; + I830Ptr pI830 = I830PTR(pScrn); + BoxPtr pbox; + int nbox, dxo, dyo; + int urb_vs_start, urb_vs_size; + int urb_gs_start, urb_gs_size; + int urb_clip_start, urb_clip_size; + int urb_sf_start, urb_sf_size; + int urb_cs_start, urb_cs_size; + struct brw_surface_state *dest_surf_state; + struct brw_surface_state *src_surf_state; + struct brw_sampler_state *src_sampler_state; + struct brw_vs_unit_state *vs_state; + struct brw_sf_unit_state *sf_state; + struct brw_wm_unit_state *wm_state; + struct brw_cc_unit_state *cc_state; + struct brw_cc_viewport *cc_viewport; + struct brw_instruction *sf_kernel; + struct brw_instruction *ps_kernel; + struct brw_instruction *sip_kernel; + float *vb; CARD32 *binding_table; - Bool first_output = TRUE; - int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset; - int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset; - int wm_scratch_offset; - int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset; - int binding_table_offset; - int next_offset, total_state_size; - int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */ - char *state_base; - int state_base_offset; + Bool first_output = TRUE; + int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset; + int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset; + int wm_scratch_offset; + int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset; + int binding_table_offset; + int next_offset, total_state_size; + int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */ + char *state_base; + int state_base_offset; #if 0 - ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height, - video_pitch); + ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height, + video_pitch); #endif - /* enable debug */ - OUTREG (INST_PM, - (1 << (16 + 4)) | - (1 << 4)); + /* enable debug */ + OUTREG (INST_PM, + (1 << (16 + 4)) | + (1 << 4)); #if 0 - ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM)); + ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM)); #endif - - assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2)); - /* Tell the rotation code that we have stomped its invariant state by - * setting a high bit. We don't use any invariant 3D state for video, so we - * don't have to worry about it ourselves. - */ - *pI830->used3D |= 1 << 30; + assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2)); + + /* Tell the rotation code that we have stomped its invariant state by + * setting a high bit. We don't use any invariant 3D state for video, so + * we don't have to worry about it ourselves. + */ + *pI830->used3D |= 1 << 30; #ifdef XF86DRI - /* Tell the DRI that we're smashing its state. */ - if (pI830->directRenderingEnabled) { - drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + /* Tell the DRI that we're smashing its state. */ + if (pI830->directRenderingEnabled) { + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); - } + pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); + } #endif /* XF86DRI */ - next_offset = 0; + next_offset = 0; - /* Set up our layout of state in framebuffer. First the general state: */ - vs_offset = ALIGN(next_offset, 64); - next_offset = vs_offset + sizeof(*vs_state); - sf_offset = ALIGN(next_offset, 32); - next_offset = sf_offset + sizeof(*sf_state); - wm_offset = ALIGN(next_offset, 32); - next_offset = wm_offset + sizeof(*wm_state); - wm_scratch_offset = ALIGN(next_offset, 1024); - next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS; - cc_offset = ALIGN(next_offset, 32); - next_offset = cc_offset + sizeof(*cc_state); + /* Set up our layout of state in framebuffer. First the general state: */ + vs_offset = ALIGN(next_offset, 64); + next_offset = vs_offset + sizeof(*vs_state); + sf_offset = ALIGN(next_offset, 32); + next_offset = sf_offset + sizeof(*sf_state); + wm_offset = ALIGN(next_offset, 32); + next_offset = wm_offset + sizeof(*wm_state); + wm_scratch_offset = ALIGN(next_offset, 1024); + next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS; + cc_offset = ALIGN(next_offset, 32); + next_offset = cc_offset + sizeof(*cc_state); - sf_kernel_offset = ALIGN(next_offset, 64); - next_offset = sf_kernel_offset + sizeof (sf_kernel_static); - ps_kernel_offset = ALIGN(next_offset, 64); - next_offset = ps_kernel_offset + sizeof (ps_kernel_static); - sip_kernel_offset = ALIGN(next_offset, 64); - next_offset = sip_kernel_offset + sizeof (sip_kernel_static); - cc_viewport_offset = ALIGN(next_offset, 32); - next_offset = cc_viewport_offset + sizeof(*cc_viewport); + sf_kernel_offset = ALIGN(next_offset, 64); + next_offset = sf_kernel_offset + sizeof (sf_kernel_static); + ps_kernel_offset = ALIGN(next_offset, 64); + next_offset = ps_kernel_offset + sizeof (ps_kernel_static); + sip_kernel_offset = ALIGN(next_offset, 64); + next_offset = sip_kernel_offset + sizeof (sip_kernel_static); + cc_viewport_offset = ALIGN(next_offset, 32); + next_offset = cc_viewport_offset + sizeof(*cc_viewport); - src_sampler_offset = ALIGN(next_offset, 32); - next_offset = src_sampler_offset + sizeof(*src_sampler_state); + src_sampler_offset = ALIGN(next_offset, 32); + next_offset = src_sampler_offset + sizeof(*src_sampler_state); - /* Align VB to native size of elements, for safety */ - vb_offset = ALIGN(next_offset, 8); - next_offset = vb_offset + vb_size; + /* Align VB to native size of elements, for safety */ + vb_offset = ALIGN(next_offset, 8); + next_offset = vb_offset + vb_size; - /* And then the general state: */ - dest_surf_offset = ALIGN(next_offset, 32); - next_offset = dest_surf_offset + sizeof(*dest_surf_state); - src_surf_offset = ALIGN(next_offset, 32); - next_offset = src_surf_offset + sizeof(*src_surf_state); - binding_table_offset = ALIGN(next_offset, 32); - next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4); + /* And then the general state: */ + dest_surf_offset = ALIGN(next_offset, 32); + next_offset = dest_surf_offset + sizeof(*dest_surf_state); + src_surf_offset = ALIGN(next_offset, 32); + next_offset = src_surf_offset + sizeof(*src_surf_state); + binding_table_offset = ALIGN(next_offset, 32); + next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4); - /* Allocate an area in framebuffer for our state layout we just set up */ - total_state_size = next_offset; - assert (total_state_size < BRW_LINEAR_EXTRA); + /* Allocate an area in framebuffer for our state layout we just set up */ + total_state_size = next_offset; + assert (total_state_size < BRW_LINEAR_EXTRA); - /* - * Use the extra space allocated at the end of the Xv buffer - */ - state_base_offset = pPriv->extra_offset; - state_base_offset = ALIGN(state_base_offset, 64); + /* + * Use the extra space allocated at the end of the Xv buffer + */ + state_base_offset = pPriv->extra_offset; + state_base_offset = ALIGN(state_base_offset, 64); - state_base = (char *)(pI830->FbBase + state_base_offset); - /* Set up our pointers to state structures in framebuffer. It would probably - * be a good idea to fill these structures out in system memory and then dump - * them there, instead. - */ - vs_state = (void *)(state_base + vs_offset); - sf_state = (void *)(state_base + sf_offset); - wm_state = (void *)(state_base + wm_offset); - cc_state = (void *)(state_base + cc_offset); - sf_kernel = (void *)(state_base + sf_kernel_offset); - ps_kernel = (void *)(state_base + ps_kernel_offset); - sip_kernel = (void *)(state_base + sip_kernel_offset); - - cc_viewport = (void *)(state_base + cc_viewport_offset); - dest_surf_state = (void *)(state_base + dest_surf_offset); - src_surf_state = (void *)(state_base + src_surf_offset); - src_sampler_state = (void *)(state_base + src_sampler_offset); - binding_table = (void *)(state_base + binding_table_offset); - vb = (void *)(state_base + vb_offset); + state_base = (char *)(pI830->FbBase + state_base_offset); + /* Set up our pointers to state structures in framebuffer. It would + * probably be a good idea to fill these structures out in system memory + * and then dump them there, instead. + */ + vs_state = (void *)(state_base + vs_offset); + sf_state = (void *)(state_base + sf_offset); + wm_state = (void *)(state_base + wm_offset); + cc_state = (void *)(state_base + cc_offset); + sf_kernel = (void *)(state_base + sf_kernel_offset); + ps_kernel = (void *)(state_base + ps_kernel_offset); + sip_kernel = (void *)(state_base + sip_kernel_offset); - /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it. - * A VUE consists of a 256-bit vertex header followed by the vertex data, - * which in our case is 4 floats (128 bits), thus a single 512-bit URB - * entry. - */ + cc_viewport = (void *)(state_base + cc_viewport_offset); + dest_surf_state = (void *)(state_base + dest_surf_offset); + src_surf_state = (void *)(state_base + src_surf_offset); + src_sampler_state = (void *)(state_base + src_sampler_offset); + binding_table = (void *)(state_base + binding_table_offset); + vb = (void *)(state_base + vb_offset); + + /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it. + * A VUE consists of a 256-bit vertex header followed by the vertex data, + * which in our case is 4 floats (128 bits), thus a single 512-bit URB + * entry. + */ #define URB_VS_ENTRIES 8 #define URB_VS_ENTRY_SIZE 1 - + #define URB_GS_ENTRIES 0 #define URB_GS_ENTRY_SIZE 0 - + #define URB_CLIP_ENTRIES 0 #define URB_CLIP_ENTRY_SIZE 0 - - /* The SF kernel we use outputs only 4 256-bit registers, leading to an - * entry size of 2 512-bit URBs. We don't need to have many entries to - * output as we're generally working on large rectangles and don't care - * about having WM threads running on different rectangles simultaneously. - */ + + /* The SF kernel we use outputs only 4 256-bit registers, leading to an + * entry size of 2 512-bit URBs. We don't need to have many entries to + * output as we're generally working on large rectangles and don't care + * about having WM threads running on different rectangles simultaneously. + */ #define URB_SF_ENTRIES 1 #define URB_SF_ENTRY_SIZE 2 #define URB_CS_ENTRIES 0 #define URB_CS_ENTRY_SIZE 0 - - urb_vs_start = 0; - urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; - urb_gs_start = urb_vs_start + urb_vs_size; - urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; - urb_clip_start = urb_gs_start + urb_gs_size; - urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; - urb_sf_start = urb_clip_start + urb_clip_size; - urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; - urb_cs_start = urb_sf_start + urb_sf_size; - urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; - /* We'll be poking the state buffers that could be in use by the 3d hardware - * here, but we should have synced the 3D engine already in I830PutImage. - */ + urb_vs_start = 0; + urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; + urb_gs_start = urb_vs_start + urb_vs_size; + urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; + urb_clip_start = urb_gs_start + urb_gs_size; + urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; + urb_sf_start = urb_clip_start + urb_clip_size; + urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; + urb_cs_start = urb_sf_start + urb_sf_size; + urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; - memset (cc_viewport, 0, sizeof (*cc_viewport)); - cc_viewport->min_depth = -1.e35; - cc_viewport->max_depth = 1.e35; + /* We'll be poking the state buffers that could be in use by the 3d + * hardware here, but we should have synced the 3D engine already in + * I830PutImage. + */ - /* Color calculator state */ - memset(cc_state, 0, sizeof(*cc_state)); - cc_state->cc0.stencil_enable = 0; /* disable stencil */ - cc_state->cc2.depth_test = 0; /* disable depth test */ - cc_state->cc2.logicop_enable = 1; /* enable logic op */ - cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */ - cc_state->cc3.blend_enable = 0; /* disable color blend */ - cc_state->cc3.alpha_test = 0; /* disable alpha test */ - cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5; - cc_state->cc5.dither_enable = 0; /* disable dither */ - cc_state->cc5.logicop_func = 0xc; /* WHITE */ - cc_state->cc5.statistics_enable = 1; - cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; - cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE; - cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE; + memset (cc_viewport, 0, sizeof (*cc_viewport)); + cc_viewport->min_depth = -1.e35; + cc_viewport->max_depth = 1.e35; - /* Upload system kernel */ - memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static)); - - /* Set up the state buffer for the destination surface */ - memset(dest_surf_state, 0, sizeof(*dest_surf_state)); - dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; - dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; - if (pI830->cpp == 2) { - dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; - } else { - dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - } - dest_surf_state->ss0.writedisable_alpha = 0; - dest_surf_state->ss0.writedisable_red = 0; - dest_surf_state->ss0.writedisable_green = 0; - dest_surf_state->ss0.writedisable_blue = 0; - dest_surf_state->ss0.color_blend = 1; - dest_surf_state->ss0.vert_line_stride = 0; - dest_surf_state->ss0.vert_line_stride_ofs = 0; - dest_surf_state->ss0.mipmap_layout_mode = 0; - dest_surf_state->ss0.render_cache_read_mode = 0; - - dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start; - dest_surf_state->ss2.height = pScrn->virtualY - 1; - dest_surf_state->ss2.width = pScrn->virtualX - 1; - dest_surf_state->ss2.mip_count = 0; - dest_surf_state->ss2.render_target_rotation = 0; - dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1; + /* Color calculator state */ + memset(cc_state, 0, sizeof(*cc_state)); + cc_state->cc0.stencil_enable = 0; /* disable stencil */ + cc_state->cc2.depth_test = 0; /* disable depth test */ + cc_state->cc2.logicop_enable = 1; /* enable logic op */ + cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */ + cc_state->cc3.blend_enable = 0; /* disable color blend */ + cc_state->cc3.alpha_test = 0; /* disable alpha test */ + cc_state->cc4.cc_viewport_state_offset = (state_base_offset + + cc_viewport_offset) >> 5; + cc_state->cc5.dither_enable = 0; /* disable dither */ + cc_state->cc5.logicop_func = 0xc; /* WHITE */ + cc_state->cc5.statistics_enable = 1; + cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; + cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE; + cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE; - /* Set up the source surface state buffer */ - memset(src_surf_state, 0, sizeof(*src_surf_state)); - src_surf_state->ss0.surface_type = BRW_SURFACE_2D; -/* src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; */ - switch (id) { - case FOURCC_YUY2: - src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL; - break; - case FOURCC_UYVY: - src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY; - break; - } - src_surf_state->ss0.writedisable_alpha = 0; - src_surf_state->ss0.writedisable_red = 0; - src_surf_state->ss0.writedisable_green = 0; - src_surf_state->ss0.writedisable_blue = 0; - src_surf_state->ss0.color_blend = 1; - src_surf_state->ss0.vert_line_stride = 0; - src_surf_state->ss0.vert_line_stride_ofs = 0; - src_surf_state->ss0.mipmap_layout_mode = 0; - src_surf_state->ss0.render_cache_read_mode = 0; - - src_surf_state->ss1.base_addr = pPriv->YBuf0offset; - src_surf_state->ss2.width = width - 1; - src_surf_state->ss2.height = height - 1; - src_surf_state->ss2.mip_count = 0; - src_surf_state->ss2.render_target_rotation = 0; - src_surf_state->ss3.pitch = video_pitch - 1; + /* Upload system kernel */ + memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static)); - /* Set up a binding table for our two surfaces. Only the PS will use it */ - /* XXX: are these offset from the right place? */ - binding_table[0] = state_base_offset + dest_surf_offset; - binding_table[1] = state_base_offset + src_surf_offset; + /* Set up the state buffer for the destination surface */ + memset(dest_surf_state, 0, sizeof(*dest_surf_state)); + dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; + dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; + if (pI830->cpp == 2) { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; + } else { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + } + dest_surf_state->ss0.writedisable_alpha = 0; + dest_surf_state->ss0.writedisable_red = 0; + dest_surf_state->ss0.writedisable_green = 0; + dest_surf_state->ss0.writedisable_blue = 0; + dest_surf_state->ss0.color_blend = 1; + dest_surf_state->ss0.vert_line_stride = 0; + dest_surf_state->ss0.vert_line_stride_ofs = 0; + dest_surf_state->ss0.mipmap_layout_mode = 0; + dest_surf_state->ss0.render_cache_read_mode = 0; - /* Set up the packed YUV source sampler. Doesn't do colorspace conversion. - */ - memset(src_sampler_state, 0, sizeof(*src_sampler_state)); - src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; - src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; - src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; - src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; - src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start; + dest_surf_state->ss2.height = pScrn->virtualY - 1; + dest_surf_state->ss2.width = pScrn->virtualX - 1; + dest_surf_state->ss2.mip_count = 0; + dest_surf_state->ss2.render_target_rotation = 0; + dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1; - /* Set up the vertex shader to be disabled (passthrough) */ - memset(vs_state, 0, sizeof(*vs_state)); - vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES; - vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; - vs_state->vs6.vs_enable = 0; - vs_state->vs6.vert_cache_disable = 1; + /* Set up the source surface state buffer */ + memset(src_surf_state, 0, sizeof(*src_surf_state)); + src_surf_state->ss0.surface_type = BRW_SURFACE_2D; + /* src_surf_state->ss0.data_return_format = + BRW_SURFACERETURNFORMAT_FLOAT32; */ + switch (id) { + case FOURCC_YUY2: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL; + break; + case FOURCC_UYVY: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY; + break; + } + src_surf_state->ss0.writedisable_alpha = 0; + src_surf_state->ss0.writedisable_red = 0; + src_surf_state->ss0.writedisable_green = 0; + src_surf_state->ss0.writedisable_blue = 0; + src_surf_state->ss0.color_blend = 1; + src_surf_state->ss0.vert_line_stride = 0; + src_surf_state->ss0.vert_line_stride_ofs = 0; + src_surf_state->ss0.mipmap_layout_mode = 0; + src_surf_state->ss0.render_cache_read_mode = 0; - /* Set up the SF kernel to do coord interp: for each attribute, - * calculate dA/dx and dA/dy. Hand these interpolation coefficients - * back to SF which then hands pixels off to WM. - */ + src_surf_state->ss1.base_addr = pPriv->YBuf0offset; + src_surf_state->ss2.width = width - 1; + src_surf_state->ss2.height = height - 1; + src_surf_state->ss2.mip_count = 0; + src_surf_state->ss2.render_target_rotation = 0; + src_surf_state->ss3.pitch = video_pitch - 1; - memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); - memset(sf_state, 0, sizeof(*sf_state)); + /* Set up a binding table for our two surfaces. Only the PS will use it */ + /* XXX: are these offset from the right place? */ + binding_table[0] = state_base_offset + dest_surf_offset; + binding_table[1] = state_base_offset + src_surf_offset; + + /* Set up the packed YUV source sampler. Doesn't do colorspace conversion. + */ + memset(src_sampler_state, 0, sizeof(*src_sampler_state)); + src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + + /* Set up the vertex shader to be disabled (passthrough) */ + memset(vs_state, 0, sizeof(*vs_state)); + vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES; + vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; + vs_state->vs6.vs_enable = 0; + vs_state->vs6.vert_cache_disable = 1; + + /* Set up the SF kernel to do coord interp: for each attribute, + * calculate dA/dx and dA/dy. Hand these interpolation coefficients + * back to SF which then hands pixels off to WM. + */ + + memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); + memset(sf_state, 0, sizeof(*sf_state)); #if 0 - ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); + ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); #endif - sf_state->thread0.kernel_start_pointer = - (state_base_offset + sf_kernel_offset) >> 6; - sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); - sf_state->sf1.single_program_flow = 1; /* XXX */ - sf_state->sf1.binding_table_entry_count = 0; - sf_state->sf1.thread_priority = 0; - sf_state->sf1.floating_point_mode = 0; /* Mesa does this */ - sf_state->sf1.illegal_op_exception_enable = 1; - sf_state->sf1.mask_stack_exception_enable = 1; - sf_state->sf1.sw_exception_enable = 1; - sf_state->thread2.per_thread_scratch_space = 0; - sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */ - sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */ - sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */ - sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ - sf_state->thread3.urb_entry_read_offset = 0; - sf_state->thread3.dispatch_grf_start_reg = 3; - sf_state->thread4.max_threads = SF_MAX_THREADS - 1; - sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; - sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES; - sf_state->thread4.stats_enable = 1; - sf_state->sf5.viewport_transform = FALSE; /* skip viewport */ - sf_state->sf6.cull_mode = BRW_CULLMODE_NONE; - sf_state->sf6.scissor = 0; - sf_state->sf7.trifan_pv = 2; - sf_state->sf6.dest_org_vbias = 0x8; - sf_state->sf6.dest_org_hbias = 0x8; + sf_state->thread0.kernel_start_pointer = + (state_base_offset + sf_kernel_offset) >> 6; + sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); + sf_state->sf1.single_program_flow = 1; /* XXX */ + sf_state->sf1.binding_table_entry_count = 0; + sf_state->sf1.thread_priority = 0; + sf_state->sf1.floating_point_mode = 0; /* Mesa does this */ + sf_state->sf1.illegal_op_exception_enable = 1; + sf_state->sf1.mask_stack_exception_enable = 1; + sf_state->sf1.sw_exception_enable = 1; + sf_state->thread2.per_thread_scratch_space = 0; + /* scratch space is not used in our kernel */ + sf_state->thread2.scratch_space_base_pointer = 0; + sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */ + sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */ + sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ + sf_state->thread3.urb_entry_read_offset = 0; + sf_state->thread3.dispatch_grf_start_reg = 3; + sf_state->thread4.max_threads = SF_MAX_THREADS - 1; + sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; + sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES; + sf_state->thread4.stats_enable = 1; + sf_state->sf5.viewport_transform = FALSE; /* skip viewport */ + sf_state->sf6.cull_mode = BRW_CULLMODE_NONE; + sf_state->sf6.scissor = 0; + sf_state->sf7.trifan_pv = 2; + sf_state->sf6.dest_org_vbias = 0x8; + sf_state->sf6.dest_org_hbias = 0x8; - memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static)); + memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static)); #if 0 - ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); + ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); #endif - memset (wm_state, 0, sizeof (*wm_state)); - wm_state->thread0.kernel_start_pointer = - (state_base_offset + ps_kernel_offset) >> 6; - wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF); - wm_state->thread1.single_program_flow = 1; /* XXX */ - wm_state->thread1.binding_table_entry_count = 2; - /* Though we never use the scratch space in our WM kernel, it has to be - * set, and the minimum allocation is 1024 bytes. - */ - wm_state->thread2.scratch_space_base_pointer = (state_base_offset + - wm_scratch_offset) >> 10; - wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */ - wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */ - wm_state->thread3.const_urb_entry_read_length = 0; - wm_state->thread3.const_urb_entry_read_offset = 0; - wm_state->thread3.urb_entry_read_length = 1; /* XXX */ - wm_state->thread3.urb_entry_read_offset = 0; /* XXX */ - wm_state->wm4.stats_enable = 1; - wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; - wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */ - wm_state->wm5.max_threads = PS_MAX_THREADS - 1; - wm_state->wm5.thread_dispatch_enable = 1; - wm_state->wm5.enable_16_pix = 1; - wm_state->wm5.enable_8_pix = 0; - wm_state->wm5.early_depth_test = 1; + memset (wm_state, 0, sizeof (*wm_state)); + wm_state->thread0.kernel_start_pointer = + (state_base_offset + ps_kernel_offset) >> 6; + wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF); + wm_state->thread1.single_program_flow = 1; /* XXX */ + wm_state->thread1.binding_table_entry_count = 2; + /* Though we never use the scratch space in our WM kernel, it has to be + * set, and the minimum allocation is 1024 bytes. + */ + wm_state->thread2.scratch_space_base_pointer = (state_base_offset + + wm_scratch_offset) >> 10; + wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */ + wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */ + wm_state->thread3.const_urb_entry_read_length = 0; + wm_state->thread3.const_urb_entry_read_offset = 0; + wm_state->thread3.urb_entry_read_length = 1; /* XXX */ + wm_state->thread3.urb_entry_read_offset = 0; /* XXX */ + wm_state->wm4.stats_enable = 1; + wm_state->wm4.sampler_state_pointer = (state_base_offset + + src_sampler_offset) >> 5; + wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */ + wm_state->wm5.max_threads = PS_MAX_THREADS - 1; + wm_state->wm5.thread_dispatch_enable = 1; + wm_state->wm5.enable_16_pix = 1; + wm_state->wm5.enable_8_pix = 0; + wm_state->wm5.early_depth_test = 1; - { - BEGIN_LP_RING(2); - OUT_RING(MI_FLUSH | - MI_STATE_INSTRUCTION_CACHE_FLUSH | - BRW_MI_GLOBAL_SNAPSHOT_RESET); - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); - } - -/* brw_debug (pScrn, "before base address modify"); */ - { BEGIN_LP_RING(12); - /* Match Mesa driver setup */ - OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); + { + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | + MI_STATE_INSTRUCTION_CACHE_FLUSH | + BRW_MI_GLOBAL_SNAPSHOT_RESET); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } - /* Mesa does this. Who knows... */ - OUT_RING(BRW_CS_URB_STATE | 0); - OUT_RING((0 << 4) | /* URB Entry Allocation Size */ - (0 << 0)); /* Number of URB Entries */ - - /* Zero out the two base address registers so all offsets are absolute */ - OUT_RING(BRW_STATE_BASE_ADDRESS | 4); - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */ - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */ - OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */ - OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* general state max addr, disabled */ - OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* media object state max addr, disabled */ + /* brw_debug (pScrn, "before base address modify"); */ + { + BEGIN_LP_RING(12); + /* Match Mesa driver setup */ + OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); - /* Set system instruction pointer */ - OUT_RING(BRW_STATE_SIP | 0); - OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */ - - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); } - -/* brw_debug (pScrn, "after base address modify"); */ + /* Mesa does this. Who knows... */ + OUT_RING(BRW_CS_URB_STATE | 0); + OUT_RING((0 << 4) | /* URB Entry Allocation Size */ + (0 << 0)); /* Number of URB Entries */ - { BEGIN_LP_RING(42); - /* Enable VF statistics */ - OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1); - - /* Pipe control */ - OUT_RING(BRW_PIPE_CONTROL | - BRW_PIPE_CONTROL_NOWRITE | - BRW_PIPE_CONTROL_IS_FLUSH | - 2); - OUT_RING(0); /* Destination address */ - OUT_RING(0); /* Immediate data low DW */ - OUT_RING(0); /* Immediate data high DW */ + /* Zero out the two base address registers so all offsets are + * absolute + */ + OUT_RING(BRW_STATE_BASE_ADDRESS | 4); + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */ + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */ + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */ + /* general state max addr, disabled */ + OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); + /* media object state max addr, disabled */ + OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); - /* Binding table pointers */ - OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); - OUT_RING(0); /* vs */ - OUT_RING(0); /* gs */ - OUT_RING(0); /* clip */ - OUT_RING(0); /* sf */ - /* Only the PS uses the binding table */ - OUT_RING(state_base_offset + binding_table_offset); /* ps */ - - /* Blend constant color (magenta is fun) */ - OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3); - OUT_RING(float_to_uint (1.0)); - OUT_RING(float_to_uint (0.0)); - OUT_RING(float_to_uint (1.0)); - OUT_RING(float_to_uint (1.0)); - - /* The drawing rectangle clipping is always on. Set it to values that - * shouldn't do any clipping. - */ - OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */ - OUT_RING(0x00000000); /* ymin, xmin */ - OUT_RING((pScrn->virtualX - 1) | - (pScrn->virtualY - 1) << 16); /* ymax, xmax */ - OUT_RING(0x00000000); /* yorigin, xorigin */ + /* Set system instruction pointer */ + OUT_RING(BRW_STATE_SIP | 0); + /* system instruction pointer */ + OUT_RING(state_base_offset + sip_kernel_offset); - /* skip the depth buffer */ - /* skip the polygon stipple */ - /* skip the polygon stipple offset */ - /* skip the line stipple */ - - /* Set the pointers to the 3d pipeline state */ - OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5); - OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */ - OUT_RING(BRW_GS_DISABLE); /* disable GS, resulting in passthrough */ - OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */ - OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */ - OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */ - OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */ + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } - /* URB fence */ - OUT_RING(BRW_URB_FENCE | - UF0_CS_REALLOC | - UF0_SF_REALLOC | - UF0_CLIP_REALLOC | - UF0_GS_REALLOC | - UF0_VS_REALLOC | - 1); - OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | - ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | - ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); - OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | - ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); + /* brw_debug (pScrn, "after base address modify"); */ - /* Constant buffer state */ - OUT_RING(BRW_CS_URB_STATE | 0); - OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */ - (URB_CS_ENTRIES << 0)); /* Number of URB Entries */ - - /* Set up the pointer to our vertex buffer */ - OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2); - OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) | - VB0_VERTEXDATA | - ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */ - OUT_RING(state_base_offset + vb_offset); - OUT_RING(3); /* four corners to our rectangle */ + { + BEGIN_LP_RING(42); + /* Enable VF statistics */ + OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1); - /* Set up our vertex elements, sourced from the single vertex buffer. */ - OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3); - /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */ - OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | - (0 << VE0_OFFSET_SHIFT)); - OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | - (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); - /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */ - OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | - (8 << VE0_OFFSET_SHIFT)); - OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | - (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + /* Pipe control */ + OUT_RING(BRW_PIPE_CONTROL | + BRW_PIPE_CONTROL_NOWRITE | + BRW_PIPE_CONTROL_IS_FLUSH | + 2); + OUT_RING(0); /* Destination address */ + OUT_RING(0); /* Immediate data low DW */ + OUT_RING(0); /* Immediate data high DW */ - OUT_RING(MI_NOOP); /* pad to quadword */ - ADVANCE_LP_RING(); } + /* Binding table pointers */ + OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); + OUT_RING(0); /* vs */ + OUT_RING(0); /* gs */ + OUT_RING(0); /* clip */ + OUT_RING(0); /* sf */ + /* Only the PS uses the binding table */ + OUT_RING(state_base_offset + binding_table_offset); /* ps */ - dxo = dstRegion->extents.x1; - dyo = dstRegion->extents.y1; + /* Blend constant color (magenta is fun) */ + OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3); + OUT_RING(float_to_uint (1.0)); + OUT_RING(float_to_uint (0.0)); + OUT_RING(float_to_uint (1.0)); + OUT_RING(float_to_uint (1.0)); - pbox = REGION_RECTS(dstRegion); - nbox = REGION_NUM_RECTS(dstRegion); - while (nbox--) - { - int box_x1 = pbox->x1; - int box_y1 = pbox->y1; - int box_x2 = pbox->x2; - int box_y2 = pbox->y2; - int i; - float src_scale_x, src_scale_y; + /* The drawing rectangle clipping is always on. Set it to values that + * shouldn't do any clipping. + */ + OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */ + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING((pScrn->virtualX - 1) | + (pScrn->virtualY - 1) << 16); /* ymax, xmax */ + OUT_RING(0x00000000); /* yorigin, xorigin */ - if (!first_output) { - /* Since we use the same little vertex buffer over and over, sync for - * subsequent rectangles. - */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } - } + /* skip the depth buffer */ + /* skip the polygon stipple */ + /* skip the polygon stipple offset */ + /* skip the line stipple */ - pbox++; + /* Set the pointers to the 3d pipeline state */ + OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5); + OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */ + /* disable GS, resulting in passthrough */ + OUT_RING(BRW_GS_DISABLE); + /* disable CLIP, resulting in passthrough */ + OUT_RING(BRW_CLIP_DISABLE); + OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */ + OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */ + OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */ - /* Use normalized texture coordinates */ - src_scale_x = (float)1.0 / (float)drw_w; - src_scale_y = (float)1.0 / (float)drw_h; + /* URB fence */ + OUT_RING(BRW_URB_FENCE | + UF0_CS_REALLOC | + UF0_SF_REALLOC | + UF0_CLIP_REALLOC | + UF0_GS_REALLOC | + UF0_VS_REALLOC | + 1); + OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | + ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | + ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); + OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | + ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); - i = 0; - vb[i++] = (box_x2 - dxo) * src_scale_x; - vb[i++] = (box_y2 - dyo) * src_scale_y; - vb[i++] = (float) box_x2; - vb[i++] = (float) box_y2; + /* Constant buffer state */ + OUT_RING(BRW_CS_URB_STATE | 0); + OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | + (URB_CS_ENTRIES << 0)); - vb[i++] = (box_x1 - dxo) * src_scale_x; - vb[i++] = (box_y2 - dyo) * src_scale_y; - vb[i++] = (float) box_x1; - vb[i++] = (float) box_y2; + /* Set up the pointer to our vertex buffer */ + OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2); + /* four 32-bit floats per vertex */ + OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) | + VB0_VERTEXDATA | + ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); + OUT_RING(state_base_offset + vb_offset); + OUT_RING(3); /* four corners to our rectangle */ - vb[i++] = (box_x1 - dxo) * src_scale_x; - vb[i++] = (box_y1 - dyo) * src_scale_y; - vb[i++] = (float) box_x1; - vb[i++] = (float) box_y1; + /* Set up our vertex elements, sourced from the single vertex buffer. */ + OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3); + /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */ + OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | + VE0_VALID | + (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | + (0 << VE0_OFFSET_SHIFT)); + OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | + (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | + (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */ + OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | + VE0_VALID | + (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | + (8 << VE0_OFFSET_SHIFT)); + OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | + (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | + (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + + OUT_RING(MI_NOOP); /* pad to quadword */ + ADVANCE_LP_RING(); + } + + dxo = dstRegion->extents.x1; + dyo = dstRegion->extents.y1; + + pbox = REGION_RECTS(dstRegion); + nbox = REGION_NUM_RECTS(dstRegion); + while (nbox--) { + int box_x1 = pbox->x1; + int box_y1 = pbox->y1; + int box_x2 = pbox->x2; + int box_y2 = pbox->y2; + int i; + float src_scale_x, src_scale_y; + + if (!first_output) { + /* Since we use the same little vertex buffer over and over, sync + * for subsequent rectangles. + */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + } + + pbox++; + + /* Use normalized texture coordinates */ + src_scale_x = (float)1.0 / (float)drw_w; + src_scale_y = (float)1.0 / (float)drw_h; + + i = 0; + vb[i++] = (box_x2 - dxo) * src_scale_x; + vb[i++] = (box_y2 - dyo) * src_scale_y; + vb[i++] = (float) box_x2; + vb[i++] = (float) box_y2; + + vb[i++] = (box_x1 - dxo) * src_scale_x; + vb[i++] = (box_y2 - dyo) * src_scale_y; + vb[i++] = (float) box_x1; + vb[i++] = (float) box_y2; + + vb[i++] = (box_x1 - dxo) * src_scale_x; + vb[i++] = (box_y1 - dyo) * src_scale_y; + vb[i++] = (float) box_x1; + vb[i++] = (float) box_y1; #if 0 - ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", - INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), - INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); + ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", + INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), + INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); - OUTREG(BRW_VF_CTL, - BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID | - BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX | - BRW_VF_CTL_SNAPSHOT_ENABLE); - OUTREG(BRW_VF_STRG_VAL, 0); -#endif - -#if 0 - OUTREG(BRW_VS_CTL, - BRW_VS_CTL_SNAPSHOT_ALL_THREADS | - BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT | - BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE); - - OUTREG(BRW_VS_STRG_VAL, 0); -#endif - -#if WATCH_SF - OUTREG(BRW_SF_CTL, - BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT | - BRW_SF_CTL_SNAPSHOT_ALL_THREADS | - BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE); - OUTREG(BRW_SF_STRG_VAL, 0); -#endif - -#if WATCH_WIZ - OUTREG(BRW_WIZ_CTL, - BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE | - BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS | - BRW_WIZ_CTL_SNAPSHOT_ENABLE); - OUTREG(BRW_WIZ_STRG_VAL, - (box_x1) | (box_y1 << 16)); -#endif - -#if 0 - OUTREG(BRW_TS_CTL, - BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR | - BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS | - BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS | - BRW_TS_CTL_SNAPSHOT_ENABLE); -#endif - - BEGIN_LP_RING(6); - OUT_RING(BRW_3DPRIMITIVE | - BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | - (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | - (0 << 9) | /* CTG - indirect vertex count */ - 4); - OUT_RING(3); /* vertex count per instance */ - OUT_RING(0); /* start vertex offset */ - OUT_RING(1); /* single instance */ - OUT_RING(0); /* start instance location */ - OUT_RING(0); /* index buffer offset, ignored */ - ADVANCE_LP_RING(); - -#if 0 - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_VF_CTL); - if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_VF_RDATA); - OUTREG(BRW_VF_CTL, 0); - ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata); + OUTREG(BRW_VF_CTL, + BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID | + BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX | + BRW_VF_CTL_SNAPSHOT_ENABLE); + OUTREG(BRW_VF_STRG_VAL, 0); #endif #if 0 - for (j = 0; j < 1000000; j++) { - ctl = INREG(BRW_VS_CTL); - if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE) - break; - } + OUTREG(BRW_VS_CTL, + BRW_VS_CTL_SNAPSHOT_ALL_THREADS | + BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT | + BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE); - rdata = INREG(BRW_VS_RDATA); - for (k = 0; k <= 3; k++) { - OUTREG(BRW_VS_CTL, - BRW_VS_CTL_SNAPSHOT_COMPLETE | - (k << 8)); - rdata = INREG(BRW_VS_RDATA); - ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata); - } - - OUTREG(BRW_VS_CTL, 0); + OUTREG(BRW_VS_STRG_VAL, 0); #endif #if WATCH_SF - for (j = 0; j < 1000000; j++) { - ctl = INREG(BRW_SF_CTL); - if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE) - break; - } - - for (k = 0; k <= 7; k++) { - OUTREG(BRW_SF_CTL, - BRW_SF_CTL_SNAPSHOT_COMPLETE | - (k << 8)); - rdata = INREG(BRW_SF_RDATA); - ErrorF ("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata); - } - - OUTREG(BRW_SF_CTL, 0); + OUTREG(BRW_SF_CTL, + BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT | + BRW_SF_CTL_SNAPSHOT_ALL_THREADS | + BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE); + OUTREG(BRW_SF_STRG_VAL, 0); #endif #if WATCH_WIZ - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_WIZ_CTL); - if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_WIZ_RDATA); - OUTREG(BRW_WIZ_CTL, 0); - ErrorF ("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata); -#endif - -#if 0 - for (j = 0; j < 100000; j++) { - ctl = INREG(BRW_TS_CTL); - if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE) - break; - } - - rdata = INREG(BRW_TS_RDATA); - OUTREG(BRW_TS_CTL, 0); - ErrorF ("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata); - - ErrorF ("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", - INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), - INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); + OUTREG(BRW_WIZ_CTL, + BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE | + BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS | + BRW_WIZ_CTL_SNAPSHOT_ENABLE); + OUTREG(BRW_WIZ_STRG_VAL, + (box_x1) | (box_y1 << 16)); #endif #if 0 - for (j = 0; j < 256; j++) { - OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT); - rdata = INREG(BRW_TD_RDATA); - ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata); - } + OUTREG(BRW_TS_CTL, + BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR | + BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS | + BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS | + BRW_TS_CTL_SNAPSHOT_ENABLE); #endif - first_output = FALSE; - if (pI830->AccelInfoRec) - pI830->AccelInfoRec->NeedToSync = TRUE; - } - if (pI830->AccelInfoRec) - (*pI830->AccelInfoRec->Sync)(pScrn); + BEGIN_LP_RING(6); + OUT_RING(BRW_3DPRIMITIVE | + BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | + (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | + (0 << 9) | /* CTG - indirect vertex count */ + 4); + OUT_RING(3); /* vertex count per instance */ + OUT_RING(0); /* start vertex offset */ + OUT_RING(1); /* single instance */ + OUT_RING(0); /* start instance location */ + OUT_RING(0); /* index buffer offset, ignored */ + ADVANCE_LP_RING(); + +#if 0 + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_VF_CTL); + if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_VF_RDATA); + OUTREG(BRW_VF_CTL, 0); + ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata); +#endif + +#if 0 + for (j = 0; j < 1000000; j++) { + ctl = INREG(BRW_VS_CTL); + if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_VS_RDATA); + for (k = 0; k <= 3; k++) { + OUTREG(BRW_VS_CTL, + BRW_VS_CTL_SNAPSHOT_COMPLETE | + (k << 8)); + rdata = INREG(BRW_VS_RDATA); + ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata); + } + + OUTREG(BRW_VS_CTL, 0); +#endif + +#if WATCH_SF + for (j = 0; j < 1000000; j++) { + ctl = INREG(BRW_SF_CTL); + if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE) + break; + } + + for (k = 0; k <= 7; k++) { + OUTREG(BRW_SF_CTL, + BRW_SF_CTL_SNAPSHOT_COMPLETE | + (k << 8)); + rdata = INREG(BRW_SF_RDATA); + ErrorF("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata); + } + + OUTREG(BRW_SF_CTL, 0); +#endif + +#if WATCH_WIZ + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_WIZ_CTL); + if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_WIZ_RDATA); + OUTREG(BRW_WIZ_CTL, 0); + ErrorF("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata); +#endif + +#if 0 + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_TS_CTL); + if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_TS_RDATA); + OUTREG(BRW_TS_CTL, 0); + ErrorF("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata); + + ErrorF("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", + INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), + INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); +#endif + +#if 0 + for (j = 0; j < 256; j++) { + OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT); + rdata = INREG(BRW_TD_RDATA); + ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata); + } +#endif + first_output = FALSE; + if (pI830->AccelInfoRec) + pI830->AccelInfoRec->NeedToSync = TRUE; + } + + if (pI830->AccelInfoRec) + (*pI830->AccelInfoRec->Sync)(pScrn); #if WATCH_STATS - i830_dump_error_state (pScrn); + i830_dump_error_state(pScrn); #endif } From a75b416c91085df1db4027a25eafcd04fef1e57c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 17:58:57 -0800 Subject: [PATCH 04/37] Replace XAA mark/waitsyncs with the XAA/EXA wrappers. --- src/i965_video.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/i965_video.c b/src/i965_video.c index 07ee3605..96ba8f14 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -659,10 +659,7 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, /* Since we use the same little vertex buffer over and over, sync * for subsequent rectangles. */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } + i830WaitSync(pScrn); } pbox++; @@ -831,12 +828,10 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, } #endif first_output = FALSE; - if (pI830->AccelInfoRec) - pI830->AccelInfoRec->NeedToSync = TRUE; + i830MarkSync(pScrn); } - if (pI830->AccelInfoRec) - (*pI830->AccelInfoRec->Sync)(pScrn); + i830WaitSync(pScrn); #if WATCH_STATS i830_dump_error_state(pScrn); #endif From f830c55e5f4efc97451240f8f18b49f46e8bce0f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 18:14:59 -0800 Subject: [PATCH 05/37] Make the assert() in i965_video.c actually work and expose an error. --- src/i830_video.c | 5 ----- src/i830_video.h | 5 +++++ src/i965_video.c | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 2e4a85bd..3153041b 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -131,11 +131,6 @@ static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; #define IMAGE_MAX_WIDTH_LEGACY 1024 #define IMAGE_MAX_HEIGHT_LEGACY 1088 -/* - * Broadwater requires a bit of extra video memory for state information - */ -#define BRW_LINEAR_EXTRA (32*1024) - #if !VIDEO_DEBUG #define ErrorF Edummy static void diff --git a/src/i830_video.h b/src/i830_video.h index a00cd508..356a8f7f 100644 --- a/src/i830_video.h +++ b/src/i830_video.h @@ -81,6 +81,11 @@ typedef struct { #define GET_PORT_PRIVATE(pScrn) \ (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr) +/* + * Broadwater requires a bit of extra video memory for state information + */ +#define BRW_LINEAR_EXTRA (32*1024) + void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, RegionPtr dstRegion, short width, short height, int video_pitch, diff --git a/src/i965_video.c b/src/i965_video.c index 96ba8f14..d4403df5 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -40,6 +40,10 @@ #include "brw_defines.h" #include "brw_structs.h" +/* Make assert() work. */ +#undef NDEBUG +#include + static const CARD32 sip_kernel_static[][4] = { /* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */ { 0x00000030, 0x20000108, 0x00001220, 0x00000000 }, From 8165e043670f6a7fee5e7e8f33644adda5757591 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 18:17:37 -0800 Subject: [PATCH 06/37] Bump the size of the extra space for 965 so it actually fits. --- src/i830_video.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_video.h b/src/i830_video.h index 356a8f7f..90c58b76 100644 --- a/src/i830_video.h +++ b/src/i830_video.h @@ -84,7 +84,7 @@ typedef struct { /* * Broadwater requires a bit of extra video memory for state information */ -#define BRW_LINEAR_EXTRA (32*1024) +#define BRW_LINEAR_EXTRA (36*1024) void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, RegionPtr dstRegion, short width, From 82738e60769a4798d7425ffc67882d1f74043b76 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 18:35:35 -0800 Subject: [PATCH 07/37] Fix discrepancy between XAA/EXA linear allocations that broke EXA XV. The XAA allocator returned an offset from the beginning of the frontbuffer allocation (where the linear allocations come from), while EXA returned one from the start of framebuffer. Now, both of them use the start of framebuffer as the reference. --- src/i830_video.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 3153041b..a0ab932c 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -2018,7 +2018,8 @@ I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) * \param pPriv adaptor the memory is being allocated for. * \param size size of the allocation, in bytes. * \param alignment offset alignment of the allocation, in bytes. - * \return offset of the allocated memory. + * + * \return byte offset of the allocated memory from the start of framebuffer. */ static void I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, @@ -2048,6 +2049,11 @@ I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, if (!pI830->useEXA) { int max_size; + /* Converts an offset from XAA's linear allocator to an offset from the + * start of fb. + */ +#define XAA_OFFSET_TO_OFFSET(x) (pI830->FrontBuffer.Start + (x * pI830->cpp)) + /* The XFree86 linear allocator operates in units of screen pixels, * sadly. */ @@ -2056,12 +2062,12 @@ I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, if (linear->xaa != NULL) { if (linear->xaa->size >= size) { - linear->offset = linear->xaa->offset * pI830->cpp; + linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); return; } if (xf86ResizeOffscreenLinear(linear->xaa, size)) { - linear->offset = linear->xaa->offset * pI830->cpp; + linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); return; } @@ -2071,7 +2077,7 @@ I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align, NULL, NULL, NULL); if (linear->xaa != NULL) { - linear->offset = linear->xaa->offset * pI830->cpp; + linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); return; } @@ -2087,7 +2093,7 @@ I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, xf86PurgeUnlockedOffscreenAreas(pScreen); linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL); - linear->offset = linear->xaa->offset * pI830->cpp; + linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); } #endif /* I830_USE_XAA */ } @@ -2270,11 +2276,7 @@ I830PutImage(ScrnInfoPtr pScrn, pPriv->doubleBuffer ? size * 2 : size; /* fixup pointers */ -#if 0 - pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear.offset; -#else - pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear.offset; -#endif + pPriv->YBuf0offset = pPriv->linear.offset; if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2); @@ -2592,11 +2594,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn, surface->offsets[0] = pPriv->linear.offset; surface->devPrivate.ptr = (pointer) pPriv; -#if 0 - memset(pI830->FbBase + pScrn->fbOffset + surface->offsets[0], 0, size); -#else - memset(pI830->FbBase + pI830->FrontBuffer.Start + surface->offsets[0], 0, size); -#endif + memset(pI830->FbBase + surface->offsets[0], 0, size); return Success; } From 210f30bd75529d0064bc46af15464a2a47f9d4c6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 18:57:50 -0800 Subject: [PATCH 08/37] debugging for location of various 965 textured-video state. --- src/i965_video.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/i965_video.c b/src/i965_video.c index d4403df5..af22cb24 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -281,6 +281,22 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, binding_table = (void *)(state_base + binding_table_offset); vb = (void *)(state_base + vb_offset); +#if 0 + ErrorF("vs: 0x%08x\n", state_base_offset + vs_offset); + ErrorF("wm: 0x%08x\n", state_base_offset + wm_offset); + ErrorF("sf: 0x%08x\n", state_base_offset + sf_offset); + ErrorF("cc: 0x%08x\n", state_base_offset + cc_offset); + ErrorF("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); + ErrorF("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); + ErrorF("sip kernel: 0x%08x\n", state_base_offset + sip_kernel_offset); + ErrorF("cc_vp: 0x%08x\n", state_base_offset + cc_viewport_offset); + ErrorF("src sampler: 0x%08x\n", state_base_offset + src_sampler_offset); + ErrorF("vb: 0x%08x\n", state_base_offset + vb_offset); + ErrorF("dst surf: 0x%08x\n", state_base_offset + dest_surf_offset); + ErrorF("src surf: 0x%08x\n", state_base_offset + src_surf_offset); + ErrorF("binding table: 0x%08x\n", state_base_offset + binding_table_offset); +#endif + /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it. * A VUE consists of a 256-bit vertex header followed by the vertex data, * which in our case is 4 floats (128 bits), thus a single 512-bit URB @@ -430,9 +446,6 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); memset(sf_state, 0, sizeof(*sf_state)); -#if 0 - ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); -#endif sf_state->thread0.kernel_start_pointer = (state_base_offset + sf_kernel_offset) >> 6; sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); @@ -463,9 +476,6 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, sf_state->sf6.dest_org_hbias = 0x8; memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static)); -#if 0 - ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); -#endif memset (wm_state, 0, sizeof (*wm_state)); wm_state->thread0.kernel_start_pointer = (state_base_offset + ps_kernel_offset) >> 6; From 6dc3387219b2b31e0c7dbaa88b568fbd54d72878 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 18:58:40 -0800 Subject: [PATCH 09/37] Fix operator precedence issue that stuck 965 t-v state into the front buffer. --- src/i830_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_video.c b/src/i830_video.c index a0ab932c..0ffa1894 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -2273,7 +2273,7 @@ I830PutImage(ScrnInfoPtr pScrn, return BadAlloc; pPriv->extra_offset = pPriv->linear.offset + - pPriv->doubleBuffer ? size * 2 : size; + (pPriv->doubleBuffer ? size * 2 : size); /* fixup pointers */ pPriv->YBuf0offset = pPriv->linear.offset; From c87462ded20904dbc6c6cbdb9547523b75fe5471 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 27 Dec 2006 19:14:14 -0800 Subject: [PATCH 10/37] Remove the nasty #define away of ErrorF in i830_video.c. Every new person touching this file hits this trap, so it's now removed. --- src/i830_video.c | 150 +++++++++++++++++++++++++++-------------------- 1 file changed, 85 insertions(+), 65 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 0ffa1894..76d4f9c8 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -131,12 +131,11 @@ static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; #define IMAGE_MAX_WIDTH_LEGACY 1024 #define IMAGE_MAX_HEIGHT_LEGACY 1088 -#if !VIDEO_DEBUG -#define ErrorF Edummy -static void -Edummy(const char *dummy, ...) -{ -} +/* overlay debugging printf function */ +#if 0 +#define OVERLAY_DEBUG ErrorF +#else +#define OVERLAY_DEBUG if (0) ErrorF #endif /* @@ -157,7 +156,7 @@ Edummy(const char *dummy, ...) OUT_RING(MI_NOOP); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON); \ - ErrorF("Overlay goes from off to on\n"); \ + OVERLAY_DEBUG("Overlay goes from off to on\n"); \ *pI830->overlayOn = TRUE; \ } else { \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ @@ -171,7 +170,7 @@ Edummy(const char *dummy, ...) OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ - ErrorF("OVERLAY_UPDATE\n"); \ + OVERLAY_DEBUG("OVERLAY_UPDATE\n"); \ } while(0) #define OVERLAY_OFF \ @@ -190,13 +189,14 @@ Edummy(const char *dummy, ...) OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ *pI830->overlayOn = FALSE; \ - ErrorF("Overlay goes from on to off\n"); \ + OVERLAY_DEBUG("Overlay goes from on to off\n"); \ while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){ \ - ErrorF("SPIN %d\n",spin); \ + OVERLAY_DEBUG("SPIN %d\n",spin); \ spin--; \ } \ - if (spin == 0) ErrorF("OVERLAY FAILED TO GO OFF\n"); \ - ErrorF("OVERLAY_OFF\n"); \ + if (spin == 0) \ + OVERLAY_DEBUG("OVERLAY FAILED TO GO OFF\n"); \ + OVERLAY_DEBUG("OVERLAY_OFF\n"); \ } \ } while(0) @@ -387,13 +387,13 @@ CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size) for (i = 0; i < size; i += 4) { val = INREG(0x30100 + i); if (val != overlay[i / 4]) { - ErrorF("0x%05x value doesn't match (0x%lx != 0x%lx)\n", + OVERLAY_DEBUG("0x%05x value doesn't match (0x%lx != 0x%lx)\n", 0x30100 + i, val, overlay[i / 4]); bad++; } } if (!bad) - ErrorF("CompareOverlay: no differences\n"); + OVERLAY_DEBUG("CompareOverlay: no differences\n"); } #endif @@ -406,8 +406,6 @@ I830InitVideo(ScreenPtr pScreen) XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; int num_adaptors; - ErrorF("I830InitVideo\n"); - #if 0 { I830OverlayRegRec tmp; @@ -480,7 +478,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); - ErrorF("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n", + OVERLAY_DEBUG("I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n", pI830->FbBase, pI830->OverlayMem->Start, overlay); /* * Default to maximum image size in YV12 @@ -622,15 +620,19 @@ I830UpdateGamma(ScrnInfoPtr pScrn) CARD32 gamma4 = pPriv->gamma4; CARD32 gamma5 = pPriv->gamma5; +#if 0 ErrorF ("Original gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", gamma0, gamma1, gamma2, gamma3, gamma4, gamma5); +#endif gamma1 = I830BoundGamma (gamma1, gamma0); gamma2 = I830BoundGamma (gamma2, gamma1); gamma3 = I830BoundGamma (gamma3, gamma2); gamma4 = I830BoundGamma (gamma4, gamma3); gamma5 = I830BoundGamma (gamma5, gamma4); +#if 0 ErrorF ("Bounded gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", gamma0, gamma1, gamma2, gamma3, gamma4, gamma5); +#endif OUTREG(OGAMC5, gamma5); OUTREG(OGAMC4, gamma4); @@ -649,7 +651,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) I830PortPrivPtr pPriv; XF86AttributePtr att; - ErrorF("I830SetupImageVideoOverlay\n"); + OVERLAY_DEBUG("I830SetupImageVideoOverlay\n"); if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(I830PortPrivRec) + sizeof(DevUnion)))) @@ -775,7 +777,7 @@ I830SetupImageVideoTextured(ScreenPtr pScreen) int nports = 16, i; int nAttributes; - ErrorF("I830SetupImageVideoOverlay\n"); + OVERLAY_DEBUG("I830SetupImageVideoOverlay\n"); nAttributes = NUM_TEXTURED_ATTRIBUTES; @@ -881,7 +883,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) if (pPriv->textured) return; - ErrorF("I830StopVideo\n"); + OVERLAY_DEBUG("I830StopVideo\n"); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); @@ -928,14 +930,14 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, return BadValue; pPriv->brightness = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - ErrorF("BRIGHTNESS\n"); + OVERLAY_DEBUG("BRIGHTNESS\n"); OVERLAY_UPDATE; } else if (attribute == xvContrast) { if ((value < 0) || (value > 255)) return BadValue; pPriv->contrast = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - ErrorF("CONTRAST\n"); + OVERLAY_DEBUG("CONTRAST\n"); OVERLAY_UPDATE; } else if (attribute == xvSaturation) { if ((value < 0) || (value > 1023)) @@ -956,7 +958,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->OCONFIG |= OVERLAY_PIPE_A; else overlay->OCONFIG |= OVERLAY_PIPE_B; - ErrorF("PIPE CHANGE\n"); + OVERLAY_DEBUG("PIPE CHANGE\n"); OVERLAY_UPDATE; } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { pPriv->gamma0 = value; @@ -983,7 +985,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->DCLRKV = pPriv->colorKey; break; } - ErrorF("COLORKEY\n"); + OVERLAY_DEBUG("COLORKEY\n"); OVERLAY_UPDATE; REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } else if(attribute == xvDoubleBuffer) { @@ -1003,7 +1005,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, attribute == xvGamma4 || attribute == xvGamma5) && (IS_I9XX(pI830))) { CARD32 r = overlay->OCMD & OVERLAY_ENABLE; - ErrorF("GAMMA\n"); + OVERLAY_DEBUG("GAMMA\n"); overlay->OCMD &= ~OVERLAY_ENABLE; OVERLAY_UPDATE; I830UpdateGamma(pScrn); @@ -1078,8 +1080,11 @@ I830CopyPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int i,j; unsigned char *s; +#if 0 ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n" - "srcPitch: %d, dstPitch: %d\n", top, left, h, w, srcPitch, dstPitch); + "srcPitch: %d, dstPitch: %d\n", top, left, h, w, + srcPitch, dstPitch); +#endif src = buf + (top * srcPitch) + (left << 1); @@ -1232,14 +1237,19 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, unsigned char *s; int dstPitch2 = dstPitch << 1; +#if 0 ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n" - "nlines %d, npixels %d, top %d, left %d\n", srcPitch, srcPitch2, dstPitch, - h, w, top, left); + "nlines %d, npixels %d, top %d, left %d\n", + srcPitch, srcPitch2, dstPitch, + h, w, top, left); +#endif /* Copy Y data */ src1 = buf + (top * srcPitch) + left; +#if 0 ErrorF("src1 is %p, offset is %ld\n", src1, (unsigned long)src1 - (unsigned long)buf); +#endif if (pPriv->currentBuf == 0) dst1 = pI830->FbBase + pPriv->YBuf0offset; else @@ -1284,8 +1294,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, /* Copy V data for YV12, or U data for I420 */ src2 = buf + (srcH * srcPitch) + ((top * srcPitch) >> 2) + (left >> 1); +#if 0 ErrorF("src2 is %p, offset is %ld\n", src2, (unsigned long)src2 - (unsigned long)buf); +#endif if (pPriv->currentBuf == 0) { if (id == FOURCC_I420) dst2 = pI830->FbBase + pPriv->UBuf0offset; @@ -1338,8 +1350,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, /* Copy U data for YV12, or V data for I420 */ src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) + ((top * srcPitch) >> 2) + (left >> 1); +#if 0 ErrorF("src3 is %p, offset is %ld\n", src3, (unsigned long)src3 - (unsigned long)buf); +#endif if (pPriv->currentBuf == 0) { if (id == FOURCC_I420) dst3 = pI830->FbBase + pPriv->VBuf0offset; @@ -1533,8 +1547,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, unsigned int mask, shift, offsety, offsetu; int tmp; - ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, - dstPitch); + OVERLAY_DEBUG("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, + dstPitch); if (!pPriv->overlayOK) return; @@ -1590,7 +1604,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */ if (!*pI830->overlayOn) { - ErrorF("TURNING ON OVERLAY BEFORE UPDATE\n"); + OVERLAY_DEBUG("TURNING ON OVERLAY BEFORE UPDATE\n"); I830ResetVideo(pScrn); OVERLAY_UPDATE; } @@ -1673,22 +1687,22 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, /* nothing do to */ if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) { - ErrorF("NOTHING TO DO\n"); + OVERLAY_DEBUG("NOTHING TO DO\n"); return; } if ((dstBox->x1 == (pScrn->currentMode->HDisplay - 1) && dstBox->x2 == (pScrn->currentMode->HDisplay - 1)) || (dstBox->y1 == vactive && dstBox->y2 == vactive)) { - ErrorF("NOTHING TO DO\n"); + OVERLAY_DEBUG("NOTHING TO DO\n"); return; } if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) { - ErrorF("NOTHING TO DO\n"); + OVERLAY_DEBUG("NOTHING TO DO\n"); return; } if ((dstBox->x2 - dstBox->x1) <= 2) { - ErrorF("NOTHING TO DO\n"); + OVERLAY_DEBUG("NOTHING TO DO\n"); return; } } @@ -1726,7 +1740,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth -= 1; - ErrorF("Y width is %d, swidth is %d\n", width, swidth); + OVERLAY_DEBUG("Y width is %d, swidth is %d\n", width, swidth); overlay->SWIDTHSW = swidth << 2; @@ -1738,11 +1752,11 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth -= 1; - ErrorF("UV width is %d, swidthsw is %d\n", width / 2, swidth); + OVERLAY_DEBUG("UV width is %d, swidthsw is %d\n", width / 2, swidth); overlay->SWIDTHSW |= swidth << 18; - ErrorF("HEIGHT is %d\n",height); + OVERLAY_DEBUG("HEIGHT is %d\n",height); overlay->SHEIGHT = height | ((height / 2) << 16); break; @@ -1752,7 +1766,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth = width; overlay->SWIDTH = swidth; - ErrorF("Y width is %d\n", swidth); + OVERLAY_DEBUG("Y width is %d\n", swidth); swidth = ((offsety + (width << 1) + mask) >> shift) - (offsety >> shift); @@ -1762,11 +1776,11 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth -= 1; - ErrorF("swidthsw is %d\n", swidth); + OVERLAY_DEBUG("swidthsw is %d\n", swidth); overlay->SWIDTHSW = swidth << 2; - ErrorF("HEIGHT is %d\n",height); + OVERLAY_DEBUG("HEIGHT is %d\n",height); overlay->SHEIGHT = height; break; @@ -1779,8 +1793,8 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1); - ErrorF("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n", dstBox->x1, dstBox->y1, - dstBox->x2, dstBox->y2); + OVERLAY_DEBUG("dstBox: x1: %d, y1: %d, x2: %d, y2: %d\n", + dstBox->x1, dstBox->y1, dstBox->x2, dstBox->y2); /* buffer locations */ if (IS_I965G(pI830)) @@ -1810,10 +1824,10 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, } } - ErrorF("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n", overlay->OBUF_0Y, - overlay->OBUF_0U, overlay->OBUF_0V); - ErrorF("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n", overlay->OBUF_1Y, - overlay->OBUF_1U, overlay->OBUF_1V); + OVERLAY_DEBUG("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n", + overlay->OBUF_0Y, overlay->OBUF_0U, overlay->OBUF_0V); + OVERLAY_DEBUG("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n", + overlay->OBUF_1Y, overlay->OBUF_1U, overlay->OBUF_1V); #if 0 { @@ -1837,8 +1851,9 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, } #endif - ErrorF("pos: 0x%lx, size: 0x%lx\n", overlay->DWINPOS, overlay->DWINSZ); - ErrorF("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h); + OVERLAY_DEBUG("pos: 0x%lx, size: 0x%lx\n", + overlay->DWINPOS, overlay->DWINSZ); + OVERLAY_DEBUG("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h); /* * Calculate horizontal and vertical scaling factors and polyphase @@ -1881,20 +1896,20 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, xscaleIntUV = xscaleFractUV >> 12; yscaleIntUV = yscaleFractUV >> 12; - ErrorF("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt, - xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF); - ErrorF("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV, - xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF); + OVERLAY_DEBUG("xscale: %x.%03x, yscale: %x.%03x\n", xscaleInt, + xscaleFract & 0xFFF, yscaleInt, yscaleFract & 0xFFF); + OVERLAY_DEBUG("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV, + xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF); /* shouldn't get here */ - if (xscaleInt > 7) { - ErrorF("xscale: bad scale\n"); + if (xscaleInt > 7) { + OVERLAY_DEBUG("xscale: bad scale\n"); return; } /* shouldn't get here */ - if (xscaleIntUV > 7) { - ErrorF("xscaleUV: bad scale\n"); + if (xscaleIntUV > 7) { + OVERLAY_DEBUG("xscaleUV: bad scale\n"); return; } @@ -1965,12 +1980,13 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, switch (id) { case FOURCC_YV12: case FOURCC_I420: - ErrorF("YUV420\n"); + OVERLAY_DEBUG("YUV420\n"); #if 0 /* set UV vertical phase to -0.25 */ overlay->UV_VPH = 0x30003000; #endif - ErrorF("UV stride is %d, Y stride is %d\n", dstPitch, dstPitch * 2); + OVERLAY_DEBUG("UV stride is %d, Y stride is %d\n", + dstPitch, dstPitch * 2); overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16); overlay->OCMD &= ~SOURCE_FORMAT; overlay->OCMD &= ~OV_BYTE_ORDER; @@ -1979,7 +1995,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, case FOURCC_UYVY: case FOURCC_YUY2: default: - ErrorF("YUV422\n"); + OVERLAY_DEBUG("YUV422\n"); overlay->OSTRIDE = dstPitch; overlay->OCMD &= ~SOURCE_FORMAT; overlay->OCMD |= YUV_422; @@ -1995,7 +2011,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, else overlay->OCMD |= BUFFER1; - ErrorF("OCMD is 0x%lx\n", overlay->OCMD); + OVERLAY_DEBUG("OCMD is 0x%lx\n", overlay->OCMD); OVERLAY_UPDATE; } @@ -2158,9 +2174,11 @@ I830PutImage(ScrnInfoPtr pScrn, int pitchAlignMask; int extraLinear; +#if 0 ErrorF("I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n" "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, width, height); +#endif if (pI830->entityPrivate) { if (pI830->entityPrivate->XvInUse != -1 && @@ -2441,6 +2459,7 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, if (offsets) offsets[2] = size; size += tmp; +#if 0 if (pitches) ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", pitches[0], pitches[1], pitches[2]); @@ -2448,6 +2467,7 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], offsets[2]); if (offsets) ErrorF("size is %d\n", size); +#endif break; case FOURCC_UYVY: case FOURCC_YUY2: @@ -2504,7 +2524,7 @@ I830BlockHandler(int i, if (pPriv->videoStatus & OFF_TIMER) { if (pPriv->offTime < now) { /* Turn off the overlay */ - ErrorF("BLOCKHANDLER\n"); + OVERLAY_DEBUG("BLOCKHANDLER\n"); I830ResetVideo(pScrn); OVERLAY_UPDATE; @@ -2544,7 +2564,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn, OffscreenPrivPtr pPriv; I830Ptr pI830 = I830PTR(pScrn); - ErrorF("I830AllocateSurface\n"); + OVERLAY_DEBUG("I830AllocateSurface\n"); if (IS_845G(pI830) || IS_I830(pI830)) { if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY)) @@ -2608,7 +2628,7 @@ I830StopSurface(XF86SurfacePtr surface) if (pPriv->isOn) { I830Ptr pI830 = I830PTR(pScrn); - ErrorF("StopSurface\n"); + OVERLAY_DEBUG("StopSurface\n"); I830ResetVideo(pScrn); OVERLAY_UPDATE; @@ -2669,7 +2689,7 @@ I830DisplaySurface(XF86SurfacePtr surface, INT32 loops = 0; BoxRec dstBox; - ErrorF("I830DisplaySurface\n"); + OVERLAY_DEBUG("I830DisplaySurface\n"); if (pI830->entityPrivate) { if (pI830->entityPrivate->XvInUse != -1 && From b928cef9cd5b3f88dc0880f406300d246a59e0fe Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 21 Dec 2006 16:21:28 -0800 Subject: [PATCH 11/37] Move dvo driver detection into i830_dvo_init(), and use GPIOB for LVDS drivers. The documentation states that GPIOB is (generally) used for devices on DVOA on the motherboard, which appears to be the case on the laptop we have with LVDS on the motherboard. This patch is probably not entirely accurate, as there was apparently an LVDS DVO card sold that could be put in desktop machines, which would likely be on GPIOE like other ADD cards. Given that we couldn't find one of these cards for purchase, I'm not worrying about it. --- src/i830_dvo.c | 109 +++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 97453ded..283e975b 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -183,37 +183,6 @@ i830_dvo_detect(xf86OutputPtr output) return intel_output->i2c_drv->vid_rec->detect(dev_priv); } -static Bool -I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, - struct _I830DVODriver **retdrv) -{ - int i; - void *ret_ptr; - struct _I830DVODriver *drv; - - for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) { - drv = &i830_dvo_drivers[i]; - drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename); - if (drv->modhandle == NULL) - continue; - - xf86LoaderReqSymLists(drv->symbols, NULL); - - ret_ptr = NULL; - drv->vid_rec = LoaderSymbol(drv->fntablename); - if (drv->vid_rec != NULL) - ret_ptr = drv->vid_rec->init(pI2CBus, drv->address); - - if (ret_ptr != NULL) { - drv->dev_priv = ret_ptr; - *retdrv = drv; - return TRUE; - } - xf86UnloadSubModule(drv->modhandle); - } - return FALSE; -} - static void i830_dvo_destroy (xf86OutputPtr output) { @@ -245,9 +214,14 @@ static const xf86OutputFuncsRec i830_dvo_output_funcs = { void i830_dvo_init(ScrnInfoPtr pScrn) { - xf86OutputPtr output; - I830OutputPrivatePtr intel_output; - int ret; + xf86OutputPtr output; + I830OutputPrivatePtr intel_output; + int ret; + int i; + void *ret_ptr; + struct _I830DVODriver *drv; + int gpio_inited = 0; + I2CBusPtr pI2CBus = NULL; output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs, "TMDS"); @@ -263,14 +237,7 @@ i830_dvo_init(ScrnInfoPtr pScrn) output->driver_private = intel_output; output->subpixel_order = SubPixelHorizontalRGB; - /* Set up the I2C and DDC buses */ - ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E"); - if (!ret) - { - xf86OutputDestroy (output); - return; - } - + /* Set up the DDC bus */ ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D"); if (!ret) { @@ -279,17 +246,51 @@ i830_dvo_init(ScrnInfoPtr pScrn) } /* Now, try to find a controller */ - ret = I830I2CDetectDVOControllers(pScrn, intel_output->pI2CBus, - &intel_output->i2c_drv); - if (ret) - { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", - intel_output->i2c_drv->modulename, - intel_output->pI2CBus->DriverPrivate.uval); - } - else - { - xf86OutputDestroy (output); - return; + for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) { + int gpio; + + drv = &i830_dvo_drivers[i]; + drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename); + if (drv->modhandle == NULL) + continue; + + xf86LoaderReqSymLists(drv->symbols, NULL); + + ret_ptr = NULL; + drv->vid_rec = LoaderSymbol(drv->fntablename); + + if (drv->type & I830_DVO_CHIP_LVDS) + gpio = GPIOB; + else + gpio = GPIOE; + + /* Set up the I2C bus necessary for the chip we're probing. It appears + * that everything is on GPIOE except for panels on i830 laptops, which + * are on GPIOB (DVOA). + */ + if (gpio_inited != gpio) { + if (pI2CBus != NULL) + xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); + if (!I830I2CInit(pScrn, &intel_output->pI2CBus, gpio, + gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E")) { + continue; + } + } + + if (drv->vid_rec != NULL) + ret_ptr = drv->vid_rec->init(pI2CBus, drv->address); + + if (ret_ptr != NULL) { + drv->dev_priv = ret_ptr; + intel_output->i2c_drv = drv; + intel_output->pI2CBus = pI2CBus; + return; + } + xf86UnloadSubModule(drv->modhandle); } + + /* Didn't find a chip, so tear down. */ + if (pI2CBus != NULL) + xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); + xf86OutputDestroy (output); } From 5806f670eb3a5171ffb0b75701640d5311b34c80 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 21 Dec 2006 16:22:14 -0800 Subject: [PATCH 12/37] Reformat the DVO drivers table to be a bit more normal style. --- src/i830_dvo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 283e975b..6d119721 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -48,10 +48,10 @@ static const char *CH7xxxSymbols[] = { /* driver list */ struct _I830DVODriver i830_dvo_drivers[] = { - { I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", - (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL}, - { I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", - (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL} + {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", + (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL}, + {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", + (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL} }; #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver)) From 778db49616b233f5a2f4f007ceb62a1a878a6e25 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 28 Dec 2006 11:36:15 -0800 Subject: [PATCH 13/37] Add WIP IVCH (i82807aa) driver. It is not currently hooked up as it hasn't been tested. The hardware that this was written for decided to stop working. --- configure.ac | 1 + src/Makefile.am | 3 +- src/i830_dvo.c | 13 ++- src/ivch/Makefile.am | 15 +++ src/ivch/ivch.c | 234 +++++++++++++++++++++++++++++++++++++++++ src/ivch/ivch_module.c | 64 +++++++++++ src/ivch/ivch_reg.h | 97 +++++++++++++++++ 7 files changed, 425 insertions(+), 2 deletions(-) create mode 100644 src/ivch/Makefile.am create mode 100644 src/ivch/ivch.c create mode 100644 src/ivch/ivch_module.c create mode 100644 src/ivch/ivch_reg.h diff --git a/configure.ac b/configure.ac index b1dd287f..30a69bc6 100644 --- a/configure.ac +++ b/configure.ac @@ -149,6 +149,7 @@ AC_OUTPUT([ src/xvmc/Makefile src/bios_reader/Makefile src/ch7xxx/Makefile + src/ivch/Makefile src/sil164/Makefile man/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index d843ecff..77a19175 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,8 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = xvmc bios_reader ch7xxx sil164 +SUBDIRS = xvmc bios_reader ch7xxx ivch sil164 + # this is obnoxious: # -module lets us name the module exactly how we want # -avoid-version prevents gratuitous .0.0.0 version numbers on the end diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 6d119721..6d4039a5 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -45,13 +45,24 @@ static const char *CH7xxxSymbols[] = { NULL }; +#if 0 +static const char *ivch_symbols[] = { + "ivch_methods", + NULL +}; +#endif + /* driver list */ struct _I830DVODriver i830_dvo_drivers[] = { {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL}, {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", - (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL} + (CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}, + /* + {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods", + (0x2 << 1), ivch_symbols, NULL, NULL, NULL}, + */ }; #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver)) diff --git a/src/ivch/Makefile.am b/src/ivch/Makefile.am new file mode 100644 index 00000000..fac074db --- /dev/null +++ b/src/ivch/Makefile.am @@ -0,0 +1,15 @@ +# this is obnoxious: +# -module lets us name the module exactly how we want +# -avoid-version prevents gratuitous .0.0.0 version numbers on the end +# _ladir passes a dummy rpath to libtool so the thing will actually link +# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. +AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ + +ivch_la_LTLIBRARIES = ivch.la +ivch_la_LDFLAGS = -module -avoid-version +ivch_ladir = @moduledir@/drivers + +ivch_la_SOURCES = \ + ivch.c \ + ivch_module.c \ + ivch_reg.h diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c new file mode 100644 index 00000000..6c5db6c9 --- /dev/null +++ b/src/ivch/ivch.c @@ -0,0 +1,234 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "compiler.h" +#include "miscstruct.h" +#include "xf86i2c.h" +#include "../i830_xf86Crtc.h" +#define DPMS_SERVER +#include + +#include "../i2c_vid.h" +#include "ivch_reg.h" + +struct ivch_priv { + I2CDevRec d; + + CARD16 save_VR01; + CARD16 save_VR40; +}; + +static void +ivch_dump_regs(I2CDevPtr d); + +/** + * Reads a register on the ivch. + * + * Each of the 256 registers are 16 bits long. + */ +static Bool +ivch_read(struct ivch_priv *priv, int addr, CARD16 *data) +{ + if (!xf86I2CReadWord(&priv->d, addr, data)) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to read register 0x%02x from %s:%d.\n", + addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +/** Writes a 16-bit register on the ivch */ +static Bool +ivch_write(struct ivch_priv *priv, int addr, CARD16 data) +{ + if (!xf86I2CWriteWord(&priv->d, addr, data)) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to write register 0x%02x to %s:%d.\n", + addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +/** Probes the given bus and slave address for an ivch */ +static void * +ivch_init(I2CBusPtr b, I2CSlaveAddr addr) +{ + struct ivch_priv *priv; + CARD16 temp; + + xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ivch\n"); + + priv = xcalloc(1, sizeof(struct ivch_priv)); + if (priv = NULL) + return NULL; + + priv->d.DevName = "i82807aa \"ivch\" LVDS/CMOS panel controller"; + priv->d.SlaveAddr = addr; + priv->d.pI2CBus = b; + priv->d.StartTimeout = b->StartTimeout; + priv->d.BitTimeout = b->BitTimeout; + priv->d.AcknTimeout = b->AcknTimeout; + priv->d.ByteTimeout = b->ByteTimeout; + priv->d.DriverPrivate.ptr = priv; + + if (!xf86I2CReadWord(&priv->d, VR00, &temp)) + goto out; + + /* Since the identification bits are probably zeroes, which doesn't seem + * very unique, check that the value in the base address field matches + * the address it's responding on. + */ + if ((temp & VR00_BASE_ADDRESS_MASK) != priv->d.SlaveAddr) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "ivch detect failed due to address mismatch " + "(%d vs %d)\n", + (temp & VR00_BASE_ADDRESS_MASK), priv->d.SlaveAddr); + } + + if (!xf86I2CDevInit(&priv->d)) { + goto out; + } + + return priv; + +out: + xfree(priv); + return NULL; +} + +static xf86OutputStatus +ivch_detect(I2CDevPtr d) +{ + return XF86OutputStatusUnknown; +} + +static ModeStatus +ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode) +{ + if (mode->Clock > 112000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +/** Sets the power state of the panel connected to the ivch */ +static void +ivch_dpms(I2CDevPtr d, int mode) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + int i; + CARD16 temp; + + /* Set the new power state of the panel. */ + if (!ivch_read(priv, VR01, &temp)) + return; + + if (mode == DPMSModeOn) + temp |= VR01_LCD_ENABLE | VR01_DVO_ENABLE; + else + temp &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE); + + ivch_write(priv, VR01, temp); + + /* Wait for the panel to make its state transition */ + for (i = 0; i < 1000; i++) { + if (!ivch_read(priv, VR30, &temp)) + break; + + if (((temp & VR30_PANEL_ON) != 0) == (mode == DPMSModeOn)) + break; + } +} + +static void +ivch_mode_set(I2CDevPtr d, DisplayModePtr mode) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + + /* Disable panel fitting for now, until we can test. */ + ivch_write(priv, VR40, 0); + + ivch_dpms(d, DPMSModeOn); + + ivch_dump_regs(d); +} + +static void +ivch_dump_regs(I2CDevPtr d) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + CARD16 val; + + ivch_read(priv, VR00, &val); + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR00: 0x%04x\n", val); + ivch_read(priv, VR01, &val); + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR01: 0x%04x\n", val); + ivch_read(priv, VR30, &val); + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR30: 0x%04x\n", val); + ivch_read(priv, VR40, &val); + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, "VR40: 0x%04x\n", val); + +} + +static void +ivch_save(I2CDevPtr d) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + + ivch_read(priv, VR01, &priv->save_VR01); + ivch_read(priv, VR40, &priv->save_VR40); +} + +static void +ivch_restore(I2CDevPtr d) +{ + struct ivch_priv *priv = d->DriverPrivate.ptr; + + ivch_write(priv, VR01, priv->save_VR01); + ivch_write(priv, VR40, priv->save_VR40); +} + + +I830I2CVidOutputRec ivch_methods = { + .init = ivch_init, + .detect = ivch_detect, + .mode_valid = ivch_mode_valid, + .mode_set = ivch_mode_set, + .dpms = ivch_dpms, + .dump_regs = ivch_dump_regs, + .save = ivch_save, + .restore = ivch_restore, +}; diff --git a/src/ivch/ivch_module.c b/src/ivch/ivch_module.c new file mode 100644 index 00000000..1ed483b1 --- /dev/null +++ b/src/ivch/ivch_module.c @@ -0,0 +1,64 @@ +/* -*- c-basic-offset: 4 -*- */ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86Module.h" + +static MODULESETUPPROTO(ivch_setup); + +static XF86ModuleVersionInfo ivch_version = { + "ivch", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + { 0,0,0,0 } +}; + +_X_EXPORT XF86ModuleData ivchModuleData = { + &ivch_version, + ivch_setup, + NULL +}; + +static pointer +ivch_setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + return (pointer)1; +} diff --git a/src/ivch/ivch_reg.h b/src/ivch/ivch_reg.h new file mode 100644 index 00000000..112c97d6 --- /dev/null +++ b/src/ivch/ivch_reg.h @@ -0,0 +1,97 @@ +/* -*- c-basic-offset: 4 -*- */ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +/** @file + * This file contains the register definitions for the i82807aa. + * + * Documentation on this chipset can be found in datasheet #29069001 at + * intel.com. + */ +#ifndef I82807AA_REG_H +#define I82807AA_REG_H + +/** @defgroup VR00 + * @{ + */ +#define VR00 0x00 +# define VR00_BASE_ADDRESS_MASK 0x007f +/** @} */ + +/** @defgroup VR01 + * @{ + */ +#define VR01 0x01 +# define VR01_PANEL_FIT_ENABLE (1 << 3) +/** + * Enables the LCD display. + * + * This must not be set while VR01_DVO_BYPASS_ENABLE is set. + */ +# define VR01_LCD_ENABLE (1 << 2) +/** Enables the DVO repeater. */ +# define VR01_DVO_BYPASS_ENABLE (1 << 1) +/** Enables the DVO clock */ +# define VR01_DVO_ENABLE (1 << 0) +/** @} */ + +/** @defgroup VR10 + * @{ + */ +#define VR10 0x10 +/** Enables LVDS output instead of CMOS */ +# define VR10_LVDS_ENABLE (1 << 4) +/** Enables 18-bit LVDS output. */ +# define VR10_INTERFACE_1X18 (0 << 2) +/** Enables 24-bit LVDS or CMOS output */ +# define VR10_INTERFACE_1X24 (1 << 2) +/** Enables 2x18-bit LVDS or CMOS output. */ +# define VR10_INTERFACE_2X18 (2 << 2) +/** Enables 2x24-bit LVDS output */ +# define VR10_INTERFACE_2X24 (3 << 2) +/** @} */ + +/** @defgroup VR30 + * @{ + */ +#define VR30 0x30 +/** Read only bit indicating that the panel is not in a safe poweroff state. */ +# define VR30_PANEL_ON (1 << 15) +/** @} */ + +/** @defgroup VR40 + * @{ + */ +#define VR40 0x40 +# define VR40_STALL_ENABLE (1 << 13) +# define VR40_VERTICAL_INTERP_ENABLE (1 << 11) +# define VR40_HORIZONTAL_INTERP_ENABLE (1 << 10) +# define VR40_RATIO_ENABLE (1 << 9) +# define VR40_PANEL_FIT_ENABLE (1 << 8) +/** @} */ + +#endif /* I82807AA_REG_H */ From c7083a6f30fdf1859f60beba4c352bd790af4773 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 28 Dec 2006 11:53:33 -0800 Subject: [PATCH 14/37] Add WIP CH7017 LVDS driver. This is disconnected because it's untested. --- configure.ac | 1 + src/Makefile.am | 2 +- src/ch7017/Makefile.am | 15 ++ src/ch7017/ch7017.c | 302 +++++++++++++++++++++++++++++++++++++ src/ch7017/ch7017_module.c | 36 +++++ src/ch7017/ch7017_reg.h | 150 ++++++++++++++++++ src/i830_dvo.c | 10 ++ 7 files changed, 515 insertions(+), 1 deletion(-) create mode 100644 src/ch7017/Makefile.am create mode 100644 src/ch7017/ch7017.c create mode 100644 src/ch7017/ch7017_module.c create mode 100644 src/ch7017/ch7017_reg.h diff --git a/configure.ac b/configure.ac index 30a69bc6..be80a872 100644 --- a/configure.ac +++ b/configure.ac @@ -148,6 +148,7 @@ AC_OUTPUT([ src/Makefile src/xvmc/Makefile src/bios_reader/Makefile + src/ch7017/Makefile src/ch7xxx/Makefile src/ivch/Makefile src/sil164/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 77a19175..5309eea9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = xvmc bios_reader ch7xxx ivch sil164 +SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 # this is obnoxious: # -module lets us name the module exactly how we want diff --git a/src/ch7017/Makefile.am b/src/ch7017/Makefile.am new file mode 100644 index 00000000..9cf2fa49 --- /dev/null +++ b/src/ch7017/Makefile.am @@ -0,0 +1,15 @@ +# this is obnoxious: +# -module lets us name the module exactly how we want +# -avoid-version prevents gratuitous .0.0.0 version numbers on the end +# _ladir passes a dummy rpath to libtool so the thing will actually link +# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. +AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ + +ch7017_la_LTLIBRARIES = ch7017.la +ch7017_la_LDFLAGS = -module -avoid-version +ch7017_ladir = @moduledir@/drivers + +ch7017_la_SOURCES = \ + ch7017.c \ + ch7017_module.c \ + ch7017_reg.h diff --git a/src/ch7017/ch7017.c b/src/ch7017/ch7017.c new file mode 100644 index 00000000..28bce0d2 --- /dev/null +++ b/src/ch7017/ch7017.c @@ -0,0 +1,302 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "compiler.h" +#include "miscstruct.h" +#include "xf86i2c.h" +#include "../i830_xf86Crtc.h" +#define DPMS_SERVER +#include + +#include "../i2c_vid.h" +#include "ch7017_reg.h" + +struct ch7017_priv { + I2CDevRec d; + + CARD8 save_hapi; + CARD8 save_vali; + CARD8 save_valo; + CARD8 save_lvds_pll_vco; + CARD8 save_feedback_div; + CARD8 save_lvds_control_2; + CARD8 save_outputs_enable; + CARD8 save_lvds_power_down; +}; + +static void +ch7017_dump_regs(I2CDevPtr d); + +static Bool +ch7017_read(struct ch7017_priv *priv, int addr, CARD8 *val) +{ + if (!xf86I2CReadByte(&priv->d, addr, val)) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to read from %s Slave %d.\n", + priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +static Bool +ch7017_write(struct ch7017_priv *priv, int addr, CARD8 val) +{ + if (!xf86I2CWriteByte(&priv->d, addr, val)) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to write to %s Slave %d.\n", + priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +/** Probes for a CH7017 on the given bus and slave address. */ +static void * +ch7017_init(I2CBusPtr b, I2CSlaveAddr addr) +{ + struct ch7017_priv *priv; + CARD8 val; + + xf86DrvMsg(b->scrnIndex, X_INFO, "detecting ch7017\n"); + + priv = xcalloc(1, sizeof(struct ch7017_priv)); + if (priv == NULL) + return NULL; + + priv->d.DevName = "CH7017/7018 TMDS Controller"; + priv->d.SlaveAddr = addr; + priv->d.pI2CBus = b; + priv->d.StartTimeout = b->StartTimeout; + priv->d.BitTimeout = b->BitTimeout; + priv->d.AcknTimeout = b->AcknTimeout; + priv->d.ByteTimeout = b->ByteTimeout; + priv->d.DriverPrivate.ptr = priv; + + if (!xf86I2CReadByte(&priv->d, CH7017_DEVICE_ID, &val)) + goto fail; + + if (val != CH7017_DEVICE_ID_VALUE && val != CH7018_DEVICE_ID_VALUE) { + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR, + "ch7017 not detected, got %d: from %s Slave %d.\n", + val, priv->d.pI2CBus->BusName, priv->d.SlaveAddr); + goto fail; + } + + if (!xf86I2CDevInit(&(priv->d))) + goto fail; + + return priv; + +fail: + xfree(priv); + return NULL; +} + +static xf86OutputStatus +ch7017_detect(I2CDevPtr d) +{ + return XF86OutputStatusUnknown; +} + +static ModeStatus +ch7017_mode_valid(I2CDevPtr d, DisplayModePtr mode) +{ + if (mode->Clock > 160000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static void +ch7017_mode_set(I2CDevPtr d, DisplayModePtr mode) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + CARD8 lvds_pll_feedback_div, lvds_pll_vco_control; + CARD8 outputs_enable, lvds_control_2, lvds_power_down; + CARD8 horizontal_active_pixel_input; + CARD8 horizontal_active_pixel_output, vertical_active_line_output; + CARD8 active_input_line_output; + + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, + "Registers before mode setting\n"); + ch7017_dump_regs(d); + + /* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/ + if (mode->Clock < 50000) { + lvds_pll_feedback_div = 45; + lvds_pll_vco_control = (2 << 4) | (3 << 0); + outputs_enable = (0 << 0); /* XXX: enables */ + lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) | + (0 << CH7017_PHASE_DETECTOR_SHIFT); + } else if (mode->Clock < 100000) { + lvds_pll_feedback_div = 45; + lvds_pll_vco_control = (2 << 4) | (3 << 0); + outputs_enable = (0 << 0); /* XXX: enables */ + lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) | + (0 << CH7017_PHASE_DETECTOR_SHIFT); + } else if (mode->Clock < 160000) { + lvds_pll_feedback_div = 35; + outputs_enable = (3 << 0); /* XXX: enables */ + lvds_control_2 = (3 << CH7017_LOOP_FILTER_SHIFT) | + (0 << CH7017_PHASE_DETECTOR_SHIFT); + if (1) { /* XXX: dual panel */ + lvds_pll_vco_control = (2 << 4) | (13 << 0); + } else { + lvds_pll_vco_control = (1 << 4) | (13 << 0); + } + } else { + FatalError("Invalid mode clock (%.1fMHz)\n", + (float)mode->Clock / 1000.0); + } + + horizontal_active_pixel_input = mode->HDisplay & 0x00ff; + + vertical_active_line_output = mode->VDisplay & 0x00ff; + horizontal_active_pixel_output = mode->HDisplay & 0x00ff; + + active_input_line_output = ((mode->HDisplay & 0x0700) >> 9) | + ((mode->VDisplay & 0x0700) >> 8); + + lvds_power_down = (mode->HDisplay & 0x0f00) >> 8; + + ch7017Power(d, FALSE); + ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, + horizontal_active_pixel_input); + ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT, + horizontal_active_pixel_output); + ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, + vertical_active_line_output); + ch7017_write(priv, CH7017_LVDS_PLL_VCO_CONTROL, lvds_pll_vco_control); + ch7017_write(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, lvds_pll_feedback_div); + ch7017_write(priv, CH7017_LVDS_CONTROL_2, lvds_control_2); + ch7017_write(priv, CH7017_OUTPUTS_ENABLE, outputs_enable); + + /* Turn the LVDS back on with new settings. */ + ch7017_write(priv, CH7017_LVDS_POWER_DOWN, lvds_power_down); + + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, + "Registers after mode setting\n"); + ch7017PrintRegs(d); +} + +/* set the CH7017 power state */ +static void +ch7017_dpms(I2CDevPtr d, int mode) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + CARD8 val; + + ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &val); + + if (mode == DPMSModeOn) { + /* Turn on the LVDS */ + ch7017_write(priv, CH7017_LVDS_POWER_DOWN, + val & ~CH7017_LVDS_POWER_DOWN_EN); + } else { + /* Turn on the LVDS */ + ch7017_write(priv, CH7017_LVDS_POWER_DOWN, + val | CH7017_LVDS_POWER_DOWN_EN); + } + + /* XXX: Should actually wait for update power status somehow */ + usleep(50000); +} + +static void +ch7017_dump_regs(I2CDevPtr d) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + CARD8 val; + +#define DUMP(reg) \ +do { \ + ch7017_read(priv, reg, &val); \ + xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_INFO, \ + #reg ": %02x\n", val); \ +} while (0) + + DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT); + DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT); + DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT); + DUMP(CH7017_LVDS_PLL_VCO_CONTROL); + DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV); + DUMP(CH7017_LVDS_CONTROL_2); + DUMP(CH7017_OUTPUTS_ENABLE); + DUMP(CH7017_LVDS_POWER_DOWN); +} + +static void +ch7017_save(I2CDevPtr d) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + + ch7017_read(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, &priv->save_hapi); + ch7017_read(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, &priv->save_valo); + ch7017_read(priv, CH7017_LVDS_PLL_VCO_CONTROL, &priv->save_lvds_pll_vco); + ch7017_read(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, &priv->save_feedback_div); + ch7017_read(priv, CH7017_LVDS_CONTROL_2, &priv->save_lvds_control_2); + ch7017_read(priv, CH7017_OUTPUTS_ENABLE, &priv->save_outputs_enable); + ch7017_read(priv, CH7017_LVDS_POWER_DOWN, &priv->save_lvds_power_down); +} + +static void +ch7017_restore(I2CDevPtr d) +{ + struct ch7017_priv *priv = d->DriverPrivate.ptr; + + /* Power down before changing mode */ + ch7017Power(d, FALSE); + + ch7017_write(priv, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, priv->save_hapi); + ch7017_write(priv, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, priv->save_valo); + ch7017_write(priv, CH7017_LVDS_PLL_VCO_CONTROL, priv->save_lvds_pll_vco); + ch7017_write(priv, CH7017_LVDS_PLL_FEEDBACK_DIV, priv->save_feedback_div); + ch7017_write(priv, CH7017_LVDS_CONTROL_2, priv->save_lvds_control_2); + ch7017_write(priv, CH7017_OUTPUTS_ENABLE, priv->save_outputs_enable); + ch7017_write(priv, CH7017_LVDS_POWER_DOWN, priv->save_lvds_power_down); +} + +I830I2CVidOutputRec ch7017_methods = { + .init = ch7017_init, + .detect = ch7017_detect, + .mode_valid = ch7017_mode_valid, + .mode_set = ch7017_mode_set, + .dpms = ch7017_dpms, + .dump_regs = ch7017_dump_regs, + .save = ch7017_save, + .restore = ch7017_restore, +}; diff --git a/src/ch7017/ch7017_module.c b/src/ch7017/ch7017_module.c new file mode 100644 index 00000000..135f3c65 --- /dev/null +++ b/src/ch7017/ch7017_module.c @@ -0,0 +1,36 @@ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86Module.h" + +static MODULESETUPPROTO(ch7017Setup); + +static XF86ModuleVersionInfo ch7017VersRec = + { + "ch7017", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + { 0,0,0,0 } + }; + +_X_EXPORT XF86ModuleData ch7017ModuleData = { + &ch7017VersRec, + ch7017Setup, + NULL +}; + +static pointer +ch7017Setup(pointer module, pointer opts, int *errmaj, int *errmin) { + return (pointer)1; +} diff --git a/src/ch7017/ch7017_reg.h b/src/ch7017/ch7017_reg.h new file mode 100644 index 00000000..89f81cc3 --- /dev/null +++ b/src/ch7017/ch7017_reg.h @@ -0,0 +1,150 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifndef CH7017_REG_H +#define CH7017_REG_H + +#define CH7017_TV_DISPLAY_MODE 0x00 +#define CH7017_FLICKER_FILTER 0x01 +#define CH7017_VIDEO_BANDWIDTH 0x02 +#define CH7017_TEXT_ENHANCEMENT 0x03 +#define CH7017_START_ACTIVE_VIDEO 0x04 +#define CH7017_HORIZONTAL_POSITION 0x05 +#define CH7017_VERTICAL_POSITION 0x06 +#define CH7017_BLACK_LEVEL 0x07 +#define CH7017_CONTRAST_ENHANCEMENT 0x08 +#define CH7017_TV_PLL 0x09 +#define CH7017_TV_PLL_M 0x0a +#define CH7017_TV_PLL_N 0x0b +#define CH7017_SUB_CARRIER_0 0x0c +#define CH7017_CIV_CONTROL 0x10 +#define CH7017_CIV_0 0x11 +#define CH7017_CHROMA_BOOST 0x14 +#define CH7017_CLOCK_MODE 0x1c +#define CH7017_INPUT_CLOCK 0x1d +#define CH7017_GPIO_CONTROL 0x1e +#define CH7017_INPUT_DATA_FORMAT 0x1f +#define CH7017_CONNECTION_DETECT 0x20 +#define CH7017_DAC_CONTROL 0x21 +#define CH7017_BUFFERED_CLOCK_OUTPUT 0x22 +#define CH7017_DEFEAT_VSYNC 0x47 +#define CH7017_TEST_PATTERN 0x48 + +#define CH7017_POWER_MANAGEMENT 0x49 +/** Enables the TV output path. */ +#define CH7017_TV_EN (1 << 0) +#define CH7017_DAC0_POWER_DOWN (1 << 1) +#define CH7017_DAC1_POWER_DOWN (1 << 2) +#define CH7017_DAC2_POWER_DOWN (1 << 3) +#define CH7017_DAC3_POWER_DOWN (1 << 4) +/** Powers down the TV out block, and DAC0-3 */ +#define CH7017_TV_POWER_DOWN_EN (1 << 5) + +#define CH7017_VERSION_ID 0x4a + +#define CH7017_DEVICE_ID 0x4b +#define CH7017_DEVICE_ID_VALUE 0x1b +#define CH7018_DEVICE_ID_VALUE 0x1a + +#define CH7017_XCLK_D2_ADJUST 0x53 +#define CH7017_UP_SCALER_COEFF_0 0x55 +#define CH7017_UP_SCALER_COEFF_1 0x56 +#define CH7017_UP_SCALER_COEFF_2 0x57 +#define CH7017_UP_SCALER_COEFF_3 0x58 +#define CH7017_UP_SCALER_COEFF_4 0x59 +#define CH7017_UP_SCALER_VERTICAL_INC_0 0x5a +#define CH7017_UP_SCALER_VERTICAL_INC_1 0x5b +#define CH7017_GPIO_INVERT 0x5c +#define CH7017_UP_SCALER_HORIZONTAL_INC_0 0x5d +#define CH7017_UP_SCALER_HORIZONTAL_INC_1 0x5e + +#define CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT 0x5f +/**< Low bits of horizontal active pixel input */ + +#define CH7017_ACTIVE_INPUT_LINE_OUTPUT 0x60 +/** High bits of horizontal active pixel input */ +#define CH7017_LVDS_HAP_INPUT_MASK (0x7 << 0) +/** High bits of vertical active line output */ +#define CH7017_LVDS_VAL_HIGH_MASK (0x7 << 3) + +#define CH7017_VERTICAL_ACTIVE_LINE_OUTPUT 0x61 +/**< Low bits of vertical active line output */ + +#define CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT 0x62 +/**< Low bits of horizontal active pixel output */ + +#define CH7017_LVDS_POWER_DOWN 0x63 +/** High bits of horizontal active pixel output */ +#define CH7017_LVDS_HAP_HIGH_MASK (0xf << 0) +/** Enables the LVDS power down state transition */ +#define CH7017_LVDS_POWER_DOWN_EN (1 << 6) +/** Enables the LVDS upscaler */ +#define CH7017_LVDS_UPSCALER_EN (1 << 7) + +#define CH7017_LVDS_ENCODING 0x64 +#define CH7017_LVDS_DITHER_2D (1 << 2) +#define CH7017_LVDS_DITHER_DIS (1 << 3) +#define CH7017_LVDS_DUAL_CHANNEL_EN (1 << 4) +#define CH7017_LVDS_24_BIT (1 << 5) + +#define CH7017_LVDS_ENCODING_2 0x65 + +#define CH7017_LVDS_PLL_CONTROL 0x66 +/** Enables the LVDS panel output path */ +#define CH7017_LVDS_PANEN (1 << 0) +/** Enables the LVDS panel backlight */ +#define CH7017_LVDS_BKLEN (1 << 3) + +#define CH7017_POWER_SEQUENCING_T1 0x67 +#define CH7017_POWER_SEQUENCING_T2 0x68 +#define CH7017_POWER_SEQUENCING_T3 0x69 +#define CH7017_POWER_SEQUENCING_T4 0x6a +#define CH7017_POWER_SEQUENCING_T5 0x6b +#define CH7017_GPIO_DRIVER_TYPE 0x6c +#define CH7017_GPIO_DATA 0x6d +#define CH7017_GPIO_DIRECTION_CONTROL 0x6e +#define CH7017_LVDS_PLL_FEEDBACK_DIV 0x71 +#define CH7017_LVDS_PLL_VCO_CONTROL 0x72 + +#define CH7017_OUTPUTS_ENABLE 0x73 +# define CH7017_LVDS_CHANNEL_A (1 << 3) +# define CH7017_LVDS_CHANNEL_B (1 << 4) +# define CH7017_TV_DAC_A (1 << 5) +# define CH7017_TV_DAC_B (1 << 6) +# define CH7017_DDC_SELECT_DC2 (1 << 7) + +#define CH7017_LVDS_OUTPUT_AMPLITUDE 0x74 +#define CH7017_LVDS_PLL_EMI_REDUCTION 0x75 +#define CH7017_LVDS_POWER_DOWN_FLICKER 0x76 + +#define CH7017_LVDS_CONTROL_2 0x78 +# define CH7017_LOOP_FILTER_SHIFT 5 +# define CH7017_PHASE_DETECTOR_SHIFT 0 + +#define CH7017_BANG_LIMIT_CONTROL 0x7f + +#endif /* CH7017_REG_H */ diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 6d4039a5..d1010545 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -51,6 +51,12 @@ static const char *ivch_symbols[] = { NULL }; #endif +#if 0 +static const char *ch7017_symbols[] = { + "ch7017_methods", + NULL +}; +#endif /* driver list */ struct _I830DVODriver i830_dvo_drivers[] = @@ -63,6 +69,10 @@ struct _I830DVODriver i830_dvo_drivers[] = {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods", (0x2 << 1), ivch_symbols, NULL, NULL, NULL}, */ + /* + { I830_DVO_CHIP_LVDS, "ch7017", "ch7017_methods", + (CH7017_ADDR_1 << 1), ch7017_symbols, NULL, NULL, NULL } + */ }; #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver)) From e889bde13dcc2438181a03319e204ae7b9235a78 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 28 Dec 2006 12:49:24 -0800 Subject: [PATCH 15/37] Draw textured video to the backing pixmap in the composited case. Currently, when the backing pixmap is not in framebuffer, we just BadAlloc rather than drawing garbage to the front buffer. This can be fixed with EXA. --- src/i830_video.c | 27 ++++++++++++++++++++++++--- src/i830_video.h | 4 ++-- src/i915_video.c | 34 +++++++++++++++++++++++----------- src/i965_video.c | 32 ++++++++++++++++++++++---------- 4 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/i830_video.c b/src/i830_video.c index 76d4f9c8..b50b21b9 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -76,6 +76,8 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86fbman.h" #include "regionstr.h" #include "randrstr.h" +#include "windowstr.h" +#include "damage.h" #include "i830.h" #include "i830_video.h" #include "xf86xv.h" @@ -2016,7 +2018,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, OVERLAY_UPDATE; } - #ifdef I830_USE_EXA static void I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) @@ -2167,6 +2168,7 @@ I830PutImage(ScrnInfoPtr pScrn, ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + PixmapPtr pPixmap; INT32 x1, x2, y1, y2; int srcPitch, srcPitch2 = 0, dstPitch, destId; int top, left, npixels, nlines, size, loops; @@ -2380,6 +2382,21 @@ I830PutImage(ScrnInfoPtr pScrn, break; } + if (pDraw->type == DRAWABLE_WINDOW) { + pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); + } else { + pPixmap = (PixmapPtr)pDraw; + } + + if (((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) || + ((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase + + pI830->FbMapSize)) { + /* If the pixmap wasn't in framebuffer, then we have no way in XAA to + * force it there. So, we simply refuse to draw and fail. + */ + return BadAlloc; + } + if (!pPriv->textured) { /* update cliplist */ if (!RegionsEqual(&pPriv->clip, clipBoxes)) { @@ -2392,12 +2409,16 @@ I830PutImage(ScrnInfoPtr pScrn, } else if (IS_I965G(pI830)) { I965DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, dstPitch, x1, y1, x2, y2, - src_w, src_h, drw_w, drw_h, pDraw); + src_w, src_h, drw_w, drw_h, pPixmap); } else { I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, dstPitch, x1, y1, x2, y2, - src_w, src_h, drw_w, drw_h, pDraw); + src_w, src_h, drw_w, drw_h, pPixmap); } + if (pPriv->textured) { + DamageDamageRegion(pDraw, clipBoxes); + } + pPriv->videoStatus = CLIENT_VIDEO_ON; return Success; diff --git a/src/i830_video.h b/src/i830_video.h index 90c58b76..854d0b80 100644 --- a/src/i830_video.h +++ b/src/i830_video.h @@ -92,7 +92,7 @@ void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int x1, int y1, int x2, int y2, short src_w, short src_h, short drw_w, short drw_h, - DrawablePtr pDraw); + PixmapPtr pPixmap); void I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, RegionPtr dstRegion, short width, @@ -100,4 +100,4 @@ void I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int x1, int y1, int x2, int y2, short src_w, short src_h, short drw_w, short drw_h, - DrawablePtr pDraw); + PixmapPtr pPixmap); diff --git a/src/i915_video.c b/src/i915_video.c index 636b2cbd..52fe1a51 100644 --- a/src/i915_video.c +++ b/src/i915_video.c @@ -57,12 +57,12 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, short width, short height, int video_pitch, int x1, int y1, int x2, int y2, short src_w, short src_h, short drw_w, short drw_h, - DrawablePtr pDraw) + PixmapPtr pPixmap) { I830Ptr pI830 = I830PTR(pScrn); CARD32 format, ms3, s2, s5; BoxPtr pbox; - int nbox, dxo, dyo; + int nbox, dxo, dyo, pix_xoff, pix_yoff; Bool planar; #if 0 @@ -103,7 +103,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, /* draw rect -- just clipping */ OUT_RING(_3DSTATE_DRAW_RECT_CMD); - OUT_RING(DRAW_DITHER_OFS_X(pDraw->x & 3)| DRAW_DITHER_OFS_Y(pDraw->y & 3)); /* flags */ + OUT_RING(DRAW_DITHER_OFS_X(pPixmap->drawable.x & 3) | + DRAW_DITHER_OFS_Y(pPixmap->drawable.y & 3)); OUT_RING(0x00000000); /* ymin, xmin */ OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); /* ymax, xmax */ @@ -155,8 +156,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, /* front buffer, pitch, offset */ OUT_RING(_3DSTATE_BUF_INFO_CMD); OUT_RING(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE | - (((pI830->displayWidth * pI830->cpp) / 4) << 2)); - OUT_RING(pI830->bufferOffset); + BUF_3D_PITCH(pPixmap->devKind)); + OUT_RING(BUF_3D_ADDR((long)pPixmap->devPrivate.ptr - (long)pI830->FbBase)); ADVANCE_LP_RING(); if (!planar) { @@ -340,6 +341,17 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, ADVANCE_LP_RING(); } + /* Set up the offset for translating from the given region (in screen + * coordinates) to the backing pixmap. + */ +#ifdef COMPOSITE + pix_xoff = -pPixmap->screen_x + pPixmap->drawable.x; + pix_yoff = -pPixmap->screen_y + pPixmap->drawable.y; +#else + pix_xoff = 0; + pix_yoff = 0; +#endif + dxo = dstRegion->extents.x1; dyo = dstRegion->extents.y1; @@ -380,8 +392,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, (vert_data_count - 1)); /* bottom right */ - OUT_RING_F(box_x2); - OUT_RING_F(box_y2); + OUT_RING_F(box_x2 + pix_xoff); + OUT_RING_F(box_y2 + pix_yoff); if (!planar) { OUT_RING_F((box_x2 - dxo) * src_scale_x); OUT_RING_F((box_y2 - dyo) * src_scale_y); @@ -393,8 +405,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, } /* bottom left */ - OUT_RING_F(box_x1); - OUT_RING_F(box_y2); + OUT_RING_F(box_x1 + pix_xoff); + OUT_RING_F(box_y2 + pix_yoff); if (!planar) { OUT_RING_F((box_x1 - dxo) * src_scale_x); OUT_RING_F((box_y2 - dyo) * src_scale_y); @@ -406,8 +418,8 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, } /* top left */ - OUT_RING_F(box_x1); - OUT_RING_F(box_y1); + OUT_RING_F(box_x1 + pix_xoff); + OUT_RING_F(box_y1 + pix_yoff); if (!planar) { OUT_RING_F((box_x1 - dxo) * src_scale_x); OUT_RING_F((box_y1 - dyo) * src_scale_y); diff --git a/src/i965_video.c b/src/i965_video.c index af22cb24..0d1bec69 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -149,11 +149,11 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, int x1, int y1, int x2, int y2, short src_w, short src_h, short drw_w, short drw_h, - DrawablePtr pDraw) + PixmapPtr pPixmap) { I830Ptr pI830 = I830PTR(pScrn); BoxPtr pbox; - int nbox, dxo, dyo; + int nbox, dxo, dyo, pix_xoff, pix_yoff; int urb_vs_start, urb_vs_size; int urb_gs_start, urb_gs_size; int urb_clip_start, urb_clip_size; @@ -381,12 +381,13 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, dest_surf_state->ss0.mipmap_layout_mode = 0; dest_surf_state->ss0.render_cache_read_mode = 0; - dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start; + dest_surf_state->ss1.base_addr = (long)pPixmap->devPrivate.ptr - + (long)pI830->FbBase; dest_surf_state->ss2.height = pScrn->virtualY - 1; dest_surf_state->ss2.width = pScrn->virtualX - 1; dest_surf_state->ss2.mip_count = 0; dest_surf_state->ss2.render_target_rotation = 0; - dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1; + dest_surf_state->ss3.pitch = pPixmap->devKind - 1; /* Set up the source surface state buffer */ memset(src_surf_state, 0, sizeof(*src_surf_state)); @@ -656,6 +657,17 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, ADVANCE_LP_RING(); } + /* Set up the offset for translating from the given region (in screen + * coordinates) to the backing pixmap. + */ +#ifdef COMPOSITE + pix_xoff = -pPixmap->screen_x + pPixmap->drawable.x; + pix_yoff = -pPixmap->screen_y + pPixmap->drawable.y; +#else + pix_xoff = 0; + pix_yoff = 0; +#endif + dxo = dstRegion->extents.x1; dyo = dstRegion->extents.y1; @@ -685,18 +697,18 @@ I965DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, i = 0; vb[i++] = (box_x2 - dxo) * src_scale_x; vb[i++] = (box_y2 - dyo) * src_scale_y; - vb[i++] = (float) box_x2; - vb[i++] = (float) box_y2; + vb[i++] = (float) box_x2 + pix_xoff; + vb[i++] = (float) box_y2 + pix_yoff; vb[i++] = (box_x1 - dxo) * src_scale_x; vb[i++] = (box_y2 - dyo) * src_scale_y; - vb[i++] = (float) box_x1; - vb[i++] = (float) box_y2; + vb[i++] = (float) box_x1 + pix_xoff; + vb[i++] = (float) box_y2 + pix_yoff; vb[i++] = (box_x1 - dxo) * src_scale_x; vb[i++] = (box_y1 - dyo) * src_scale_y; - vb[i++] = (float) box_x1; - vb[i++] = (float) box_y1; + vb[i++] = (float) box_x1 + pix_xoff; + vb[i++] = (float) box_y1 + pix_yoff; #if 0 ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", From 9cfbf1ceda8f153438df1ba4b1712c55cc872017 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 28 Dec 2006 12:59:23 -0800 Subject: [PATCH 16/37] In EXA mode, force backing pixmaps into memory when doing XV to them. --- src/i830_video.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/i830_video.c b/src/i830_video.c index b50b21b9..f031a873 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -140,6 +140,11 @@ static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; #define OVERLAY_DEBUG if (0) ErrorF #endif +/* Oops, I never exported this function in EXA. I meant to. */ +#ifndef exaMoveInPixmap +void exaMoveInPixmap (PixmapPtr pPixmap); +#endif + /* * This is more or less the correct way to initalise, update, and shut down * the overlay. Note OVERLAY_OFF should be used only after disabling the @@ -2388,6 +2393,13 @@ I830PutImage(ScrnInfoPtr pScrn, pPixmap = (PixmapPtr)pDraw; } +#ifdef I830_USE_EXA + if (pI830->useEXA) { + /* Force the pixmap into framebuffer so we can draw to it. */ + exaMoveInPixmap(pPixmap); + } +#endif + if (((char *)pPixmap->devPrivate.ptr < (char *)pI830->FbBase) || ((char *)pPixmap->devPrivate.ptr >= (char *)pI830->FbBase + pI830->FbMapSize)) { From bb238a8fc234a8e5e86cd2f42c58c9816a15732c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Dec 2006 16:27:22 -0800 Subject: [PATCH 17/37] Configuration support: per-output mode lines, preferred mode. Add the modelines specified in the per-output monitor and all of the default modes to the list to each output. Prune the resulting list to specified sync limits and virtual sizes. Sort the resulting mode list on preferred/size/refresh. --- src/i830_crt.c | 34 +---- src/i830_display.h | 11 -- src/i830_lvds.c | 45 +++++- src/i830_modes.c | 100 ++------------ src/i830_xf86Crtc.c | 318 +++++++++++++++++++++++++++++++++++++++++-- src/i830_xf86Crtc.h | 23 ++++ src/i830_xf86Modes.c | 110 +++++++++++++++ src/i830_xf86Modes.h | 13 ++ 8 files changed, 503 insertions(+), 151 deletions(-) diff --git a/src/i830_crt.c b/src/i830_crt.c index 3be10ecc..85c25de1 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -328,38 +328,6 @@ i830_crt_detect(xf86OutputPtr output) return XF86OutputStatusUnknown; } -static DisplayModePtr -i830_crt_get_modes(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - DisplayModePtr modes; - MonRec fixed_mon; - - modes = i830_ddc_get_modes(output); - if (modes != NULL) - return modes; - - if ((*output->funcs->detect)(output) == XF86OutputStatusDisconnected) - return NULL; - - /* We've got a potentially-connected monitor that we can't DDC. Return a - * fixed set of VESA plus user modes for a presumed multisync monitor with - * some reasonable limits. - */ - fixed_mon.nHsync = 1; - fixed_mon.hsync[0].lo = 31.0; - fixed_mon.hsync[0].hi = 100.0; - fixed_mon.nVrefresh = 1; - fixed_mon.vrefresh[0].lo = 50.0; - fixed_mon.vrefresh[0].hi = 70.0; - - modes = xf86DuplicateModes(pScrn, pScrn->monitor->Modes); - i830xf86ValidateModesSync(pScrn, modes, &fixed_mon); - i830xf86PruneInvalidModes(pScrn, &modes, TRUE); - - return modes; -} - static void i830_crt_destroy (xf86OutputPtr output) { @@ -375,7 +343,7 @@ static const xf86OutputFuncsRec i830_crt_output_funcs = { .mode_fixup = i830_crt_mode_fixup, .mode_set = i830_crt_mode_set, .detect = i830_crt_detect, - .get_modes = i830_crt_get_modes, + .get_modes = i830_ddc_get_modes, .destroy = i830_crt_destroy }; diff --git a/src/i830_display.h b/src/i830_display.h index 8a982abc..5517d27c 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -42,14 +42,3 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output); void i830ReleaseLoadDetectPipe(xf86OutputPtr output); Bool i830PipeInUse(xf86CrtcPtr crtc); void i830_crtc_init(ScrnInfoPtr pScrn, int pipe); - -/** @{ - */ -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) -DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); -DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, - Bool Reduced, Bool Interlaced); -#define xf86DDCGetModes i830_xf86DDCGetModes -#define xf86CVTMode i830_xf86CVTMode -#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2) */ -/** @} */ diff --git a/src/i830_lvds.c b/src/i830_lvds.c index b682b27f..fe964136 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -127,7 +127,19 @@ i830_lvds_restore(xf86OutputPtr output) static int i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) { - return MODE_OK; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr pFixedMode = pI830->panel_fixed_mode; + + if (pFixedMode) + { + if (pMode->HDisplay > pFixedMode->HDisplay) + return MODE_PANEL; + if (pMode->VDisplay > pFixedMode->VDisplay) + return MODE_PANEL; + } + + return MODE_OK; } static Bool @@ -236,14 +248,37 @@ i830_lvds_detect(xf86OutputPtr output) static DisplayModePtr i830_lvds_get_modes(xf86OutputPtr output) { - ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr modes; + I830OutputPrivatePtr intel_output = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + xf86MonPtr edid_mon; + DisplayModePtr modes; - modes = i830_ddc_get_modes(output); + edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus); + i830_xf86OutputSetEDID (output, edid_mon); + + modes = i830_xf86OutputGetEDIDModes (output); if (modes != NULL) return modes; + if (!output->MonInfo) + { + edid_mon = xcalloc (1, sizeof (xf86Monitor)); + if (edid_mon) + { + /* Set wide sync ranges so we get all modes + * handed to valid_mode for checking + */ + edid_mon->det_mon[0].type = DS_RANGES; + edid_mon->det_mon[0].section.ranges.min_v = 0; + edid_mon->det_mon[0].section.ranges.max_v = 200; + edid_mon->det_mon[0].section.ranges.min_h = 0; + edid_mon->det_mon[0].section.ranges.max_h = 200; + + output->MonInfo = edid_mon; + } + } + if (pI830->panel_fixed_mode != NULL) return xf86DuplicateMode(pI830->panel_fixed_mode); diff --git a/src/i830_modes.c b/src/i830_modes.c index 42ee79df..b4e22c35 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -55,98 +55,16 @@ #include "i830_xf86Modes.h" #include -#define DEBUG_REPROBE 1 - -#ifdef RANDR_12_INTERFACE - -#define EDID_ATOM_NAME "EDID_DATA" - -static void -i830_ddc_set_edid_property(xf86OutputPtr output, void *data, int data_len) -{ - Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE); - - /* This may get called before the RandR resources have been created */ - if (output->randr_output == NULL) - return; - - if (data_len != 0) { - RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, - PropModeReplace, data_len, data, FALSE); - } else { - RRDeleteOutputProperty(output->randr_output, edid_atom); - } -} -#endif - -/** - * Generic get_modes function using DDC, used by many outputs. - */ DisplayModePtr -i830_ddc_get_modes(xf86OutputPtr output) +i830_ddc_get_modes (xf86OutputPtr output) { - ScrnInfoPtr pScrn = output->scrn; - I830OutputPrivatePtr intel_output = output->driver_private; - xf86MonPtr ddc_mon; - DisplayModePtr ddc_modes, mode; - int i; + I830OutputPrivatePtr intel_output = output->driver_private; + xf86MonPtr edid_mon; + DisplayModePtr modes; - ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, intel_output->pDDCBus); - if (ddc_mon == NULL) { -#ifdef RANDR_12_INTERFACE - i830_ddc_set_edid_property(output, NULL, 0); -#endif - return NULL; - } - - if (output->MonInfo != NULL) - xfree(output->MonInfo); - output->MonInfo = ddc_mon; - -#ifdef RANDR_12_INTERFACE - if (output->MonInfo->ver.version == 1) { - i830_ddc_set_edid_property(output, ddc_mon->rawData, 128); - } else if (output->MonInfo->ver.version == 2) { - i830_ddc_set_edid_property(output, ddc_mon->rawData, 256); - } else { - i830_ddc_set_edid_property(output, NULL, 0); - } -#endif - - /* Debug info for now, at least */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); - xf86PrintEDID(output->MonInfo); - - ddc_modes = xf86DDCGetModes(pScrn->scrnIndex, ddc_mon); - - /* Strip out any modes that can't be supported on this output. */ - for (mode = ddc_modes; mode != NULL; mode = mode->next) { - int status = (*output->funcs->mode_valid)(output, mode); - - if (status != MODE_OK) - mode->status = status; - } - i830xf86PruneInvalidModes(pScrn, &ddc_modes, TRUE); - - /* Pull out a phyiscal size from a detailed timing if available. */ - for (i = 0; i < 4; i++) { - if (ddc_mon->det_mon[i].type == DT && - ddc_mon->det_mon[i].section.d_timings.h_size != 0 && - ddc_mon->det_mon[i].section.d_timings.v_size != 0) - { - output->mm_width = ddc_mon->det_mon[i].section.d_timings.h_size; - output->mm_height = ddc_mon->det_mon[i].section.d_timings.v_size; - break; - } - } - - /* if no mm size is available from a detailed timing, check the max size field */ - if ((!output->mm_width || !output->mm_height) && - (ddc_mon->features.hsize && ddc_mon->features.vsize)) - { - output->mm_width = ddc_mon->features.hsize * 10; - output->mm_height = ddc_mon->features.vsize * 10; - } - - return ddc_modes; + edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus); + i830_xf86OutputSetEDID (output, edid_mon); + + modes = i830_xf86OutputGetEDIDModes (output); + return modes; } diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 0c482a2e..763df435 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -32,9 +32,14 @@ #include "xf86.h" #include "xf86DDC.h" -#include "i830.h" +/*#include "i830.h" */ #include "i830_xf86Crtc.h" +#include "i830_xf86Modes.h" +#include "i830_randr.h" #include "X11/extensions/render.h" +#define DPMS_SERVER +#include "X11/extensions/dpms.h" +#include "X11/Xatom.h" /* * Initialize xf86CrtcConfig structure @@ -121,6 +126,29 @@ xf86CrtcDestroy (xf86CrtcPtr crtc) /* * Output functions */ + +extern XF86ConfigPtr xf86configptr; + +static void +xf86OutputSetMonitor (xf86OutputPtr output) +{ + char *option_name; + static const char monitor_prefix[] = "monitor-"; + char *monitor; + + option_name = xnfalloc (strlen (monitor_prefix) + + strlen (output->name) + 1); + strcpy (option_name, monitor_prefix); + strcat (option_name, output->name); + monitor = xf86findOptionValue (output->scrn->options, option_name); + if (!monitor) + monitor = output->name; + else + xf86MarkOptionUsedByName (output->scrn->options, option_name); + free (option_name); + output->conf_monitor = xf86findMonitor (monitor, xf86configptr->conf_monitor_lst); +} + xf86OutputPtr xf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, @@ -151,8 +179,11 @@ xf86OutputCreate (ScrnInfoPtr scrn, xfree (output); return NULL; } + xf86_config->output = outputs; xf86_config->output[xf86_config->num_output++] = output; + + xf86OutputSetMonitor (output); return output; } @@ -169,6 +200,7 @@ xf86OutputRename (xf86OutputPtr output, const char *name) if (output->name != (char *) (output + 1)) xfree (output->name); output->name = newname; + xf86OutputSetMonitor (output); } void @@ -446,12 +478,61 @@ xf86PruneDuplicateMonitorModes (MonPtr Monitor) } } +/** Return - 0 + if a should be earlier, same or later than b in list + */ +static int +i830xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) +{ + int diff; + + diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); + if (diff) + return diff; + diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; + if (diff) + return diff; + diff = b->Clock - a->Clock; + return diff; +} + +/** + * Insertion sort input in-place and return the resulting head + */ +static DisplayModePtr +i830xf86SortModes (DisplayModePtr input) +{ + DisplayModePtr output = NULL, i, o, *op, prev; + + while (input) + { + i = input; + input = input->next; + for (op = &output; (o = *op); op = &o->next) + if (i830xf86ModeCompare (o, i) > 0) + break; + i->next = *op; + *op = i; + } + /* hook up backward links */ + prev = NULL; + for (o = output; o; o = o->next) + { + o->prev = prev; + prev = o; + } + return output; +} + +#define DEBUG_REPROBE 1 + void xf86ProbeOutputModes (ScrnInfoPtr pScrn) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - Bool properties_set = FALSE; int o; + int virtualX, virtualY; + + xf86RandR12GetOriginalVirtualSize (pScrn, &virtualX, &virtualY); /* Elide duplicate modes before defaulting code uses them */ xf86PruneDuplicateMonitorModes (pScrn->monitor); @@ -459,21 +540,127 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) /* Probe the list of modes for each output. */ for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode; - + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode; + XF86ConfMonitorPtr conf_monitor = output->conf_monitor; + xf86MonPtr edid_monitor = output->MonInfo; + MonRec mon_rec; + while (output->probed_modes != NULL) xf86DeleteMode(&output->probed_modes, output->probed_modes); - output->probed_modes = (*output->funcs->get_modes) (output); + if (output->status == XF86OutputStatusDisconnected) + continue; - /* Set the DDC properties to whatever first output has DDC information. - */ - if (output->MonInfo != NULL && !properties_set) { - xf86SetDDCproperties(pScrn, output->MonInfo); - properties_set = TRUE; + memset (&mon_rec, '\0', sizeof (mon_rec)); + if (conf_monitor) + { + int i; + + for (i = 0; i < conf_monitor->mon_n_hsync; i++) + { + mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; + mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; + mon_rec.nHsync++; + } + for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) + { + mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; + mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; + mon_rec.nVrefresh++; + } } + if (edid_monitor) + { + int i; + Bool set_hsync = mon_rec.nHsync == 0; + Bool set_vrefresh = mon_rec.nVrefresh == 0; + for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++) + { + if (edid_monitor->det_mon[i].type == DS_RANGES) + { + struct monitor_ranges *ranges = &edid_monitor->det_mon[i].section.ranges; + if (set_hsync && ranges->max_h) + { + mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h; + mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h; + mon_rec.nHsync++; + } + if (set_vrefresh && ranges->max_v) + { + mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v; + mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v; + mon_rec.nVrefresh++; + } + } + } + } + /* + * These limits will end up setting a 1024x768@60Hz mode by default, + * which seems like a fairly good mode to use when nothing else is + * specified + */ + if (mon_rec.nHsync == 0) + { + mon_rec.hsync[0].lo = 31.0; + mon_rec.hsync[0].hi = 55.0; + mon_rec.nHsync = 1; + } + if (mon_rec.nVrefresh == 0) + { + mon_rec.vrefresh[0].lo = 58.0; + mon_rec.vrefresh[0].hi = 62.0; + mon_rec.nVrefresh = 1; + } + + output->probed_modes = NULL; + if (conf_monitor) + output->probed_modes = xf86ModesAdd (output->probed_modes, + i830xf86GetMonitorModes (pScrn, conf_monitor)); + output->probed_modes = xf86ModesAdd (output->probed_modes, + (*output->funcs->get_modes) (output)); + output->probed_modes = xf86ModesAdd (output->probed_modes, + i830xf86GetDefaultModes ()); + + i830xf86ValidateModesSize (pScrn, output->probed_modes, virtualX, virtualY, 0); + i830xf86ValidateModesSync (pScrn, output->probed_modes, &mon_rec); + + /* Strip out any modes that can't be supported on this output. */ + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + if (mode->status == MODE_OK) + mode->status = (*output->funcs->mode_valid)(output, mode); + + i830xf86PruneInvalidModes(pScrn, &output->probed_modes, TRUE); + + output->probed_modes = i830xf86SortModes (output->probed_modes); + + /* Check for a configured preference for a particular mode */ + if (conf_monitor) + { + char *preferred_mode = xf86findOptionValue (conf_monitor->mon_option_lst, + "Preferred Mode"); + + if (preferred_mode) + { + for (mode = output->probed_modes; mode; mode = mode->next) + if (!strcmp (preferred_mode, mode->name)) + break; + if (mode && mode != output->probed_modes) + { + if (mode->prev) + mode->prev->next = mode->next; + if (mode->next) + mode->next->prev = mode->prev; + mode->next = output->probed_modes; + output->probed_modes->prev = mode; + mode->prev = NULL; + output->probed_modes = mode; + mode->type |= M_T_PREFERRED; + } + } + } + #ifdef DEBUG_REPROBE if (output->probed_modes != NULL) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -747,3 +934,112 @@ xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags) } } } + +#ifdef RANDR_12_INTERFACE + +#define EDID_ATOM_NAME "EDID_DATA" + +/** + * Set the RandR EDID property + */ +static void +xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) +{ + Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE); + + /* This may get called before the RandR resources have been created */ + if (output->randr_output == NULL) + return; + + if (data_len != 0) { + RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, + PropModeReplace, data_len, data, FALSE); + } else { + RRDeleteOutputProperty(output->randr_output, edid_atom); + } +} + +#endif + +/** + * Set the EDID information for the specified output + */ +void +i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) +{ + ScrnInfoPtr pScrn = output->scrn; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i, size; + + if (output->MonInfo != NULL) + xfree(output->MonInfo); + + output->MonInfo = edid_mon; + + /* Debug info for now, at least */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); + xf86PrintEDID(edid_mon); + + /* Set the DDC properties for the 'compat' output */ + if (output == config->output[config->compat_output]) + xf86SetDDCproperties(pScrn, edid_mon); + +#ifdef RANDR_12_INTERFACE + /* Set the RandR output properties */ + size = 0; + if (edid_mon) + { + if (edid_mon->ver.version == 1) + size = 128; + else if (edid_mon->ver.version == 2) + size = 256; + } + xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); +#endif + + if (edid_mon) + { + /* Pull out a phyiscal size from a detailed timing if available. */ + for (i = 0; i < 4; i++) { + if (edid_mon->det_mon[i].type == DT && + edid_mon->det_mon[i].section.d_timings.h_size != 0 && + edid_mon->det_mon[i].section.d_timings.v_size != 0) + { + output->mm_width = edid_mon->det_mon[i].section.d_timings.h_size; + output->mm_height = edid_mon->det_mon[i].section.d_timings.v_size; + break; + } + } + + /* if no mm size is available from a detailed timing, check the max size field */ + if ((!output->mm_width || !output->mm_height) && + (edid_mon->features.hsize && edid_mon->features.vsize)) + { + output->mm_width = edid_mon->features.hsize * 10; + output->mm_height = edid_mon->features.vsize * 10; + } + } +} + +/** + * Return the list of modes supported by the EDID information + * stored in 'output' + */ +DisplayModePtr +i830_xf86OutputGetEDIDModes (xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + xf86MonPtr edid_mon = output->MonInfo; + + if (!edid_mon) + return NULL; + return xf86DDCGetModes(pScrn->scrnIndex, edid_mon); +} + +xf86MonPtr +i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) +{ + ScrnInfoPtr pScrn = output->scrn; + + return xf86DoEDID_DDC2 (pScrn->scrnIndex, pDDCBus); +} diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 9294ccc2..168d89d8 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -25,6 +25,7 @@ #include #include "randrstr.h" #include "i830_xf86Modes.h" +#include "xf86Parser.h" typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr; typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr; @@ -288,6 +289,12 @@ struct _xf86Output { /** Output name */ char *name; + /** Configured monitor name */ + char *monitor_name; + + /** Monitor information from config file */ + XF86ConfMonitorPtr conf_monitor; + /** output-specific functions */ const xf86OutputFuncsRec *funcs; @@ -396,5 +403,21 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn); void xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); + +/** + * Set the EDID information for the specified output + */ +void +i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon); + +/** + * Return the list of modes supported by the EDID information + * stored in 'output' + */ +DisplayModePtr +i830_xf86OutputGetEDIDModes (xf86OutputPtr output); + +xf86MonPtr +i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus); #endif /* _XF86CRTC_H_ */ diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 1afda951..58a6e6f9 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -39,6 +39,9 @@ #include "xf86.h" #include "i830.h" #include "i830_xf86Modes.h" +#include "xf86Priv.h" + +extern XF86ConfigPtr xf86configptr; /** * @file this file contains symbols from xf86Mode.c and friends that are static @@ -550,3 +553,110 @@ xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new) return modes; } + +/** + * Build a mode list from a list of config file modes + */ +static DisplayModePtr +i830xf86GetConfigModes (XF86ConfModeLinePtr conf_mode) +{ + DisplayModePtr head = NULL, prev = NULL, mode; + + for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next) + { + mode = xalloc(sizeof(DisplayModeRec)); + if (!mode) + continue; + mode->name = xstrdup(conf_mode->ml_identifier); + if (!mode->name) + { + xfree (mode); + continue; + } + + memset(mode,'\0',sizeof(DisplayModeRec)); + mode->type = 0; + mode->Clock = conf_mode->ml_clock; + mode->HDisplay = conf_mode->ml_hdisplay; + mode->HSyncStart = conf_mode->ml_hsyncstart; + mode->HSyncEnd = conf_mode->ml_hsyncend; + mode->HTotal = conf_mode->ml_htotal; + mode->VDisplay = conf_mode->ml_vdisplay; + mode->VSyncStart = conf_mode->ml_vsyncstart; + mode->VSyncEnd = conf_mode->ml_vsyncend; + mode->VTotal = conf_mode->ml_vtotal; + mode->Flags = conf_mode->ml_flags; + mode->HSkew = conf_mode->ml_hskew; + mode->VScan = conf_mode->ml_vscan; + + mode->prev = prev; + mode->next = NULL; + if (prev) + prev->next = mode; + else + head = mode; + prev = mode; + } + return head; +} + +/** + * Build a mode list from a monitor configuration + */ +DisplayModePtr +i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) +{ + DisplayModePtr modes = NULL; + XF86ConfModesLinkPtr modes_link; + + /* + * first we collect the mode lines from the UseModes directive + */ + for (modes_link = conf_monitor->mon_modes_sect_lst; + modes_link; + modes_link = modes_link->list.next) + { + /* If this modes link hasn't been resolved, go look it up now */ + if (!modes_link->ml_modes) + modes_link->ml_modes = xf86findModes (modes_link->ml_modes_str, + xf86configptr->conf_modes_lst); + if (modes_link->ml_modes) + modes = xf86ModesAdd (modes, + i830xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst)); + } + + return xf86ModesAdd (modes, + i830xf86GetConfigModes (conf_monitor->mon_modeline_lst)); +} + +/** + * Build a mode list containing all of the default modes + */ +DisplayModePtr +i830xf86GetDefaultModes (void) +{ + DisplayModePtr head = NULL, prev = NULL, mode; + int i; + + for (i = 0; xf86DefaultModes[i].name != NULL; i++) + { + mode = xalloc(sizeof(DisplayModeRec)); + if (!mode) + continue; + memcpy(mode,&xf86DefaultModes[i],sizeof(DisplayModeRec)); + mode->name = xstrdup(xf86DefaultModes[i].name); + if (!mode->name) + { + xfree (mode); + continue; + } + mode->prev = prev; + mode->next = NULL; + if (prev) + prev->next = mode; + else + head = mode; + prev = mode; + } + return head; +} diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index 98300039..280743bd 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -28,6 +28,7 @@ #ifndef _I830_XF86MODES_H_ #define _I830_XF86MODES_H_ #include "xorgVersion.h" +#include "xf86Parser.h" #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) double i830_xf86ModeHSync(DisplayModePtr mode); @@ -41,6 +42,10 @@ Bool i830_xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2); void i830_xf86PrintModeline(int scrnIndex,DisplayModePtr mode); DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); +DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); +DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, + Bool Reduced, Bool Interlaced); + #define xf86ModeHSync i830_xf86ModeHSync #define xf86ModeVRefresh i830_xf86ModeVRefresh #define xf86DuplicateMode i830_xf86DuplicateMode @@ -50,6 +55,8 @@ DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); #define xf86ModesEqual i830_xf86ModesEqual #define xf86PrintModeline i830_xf86PrintModeline #define xf86ModesAdd i830_xf86ModesAdd +#define xf86DDCGetModes i830_xf86DDCGetModes +#define xf86CVTMode i830_xf86CVTMode #endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */ void @@ -79,4 +86,10 @@ i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, void i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList); +DisplayModePtr +i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor); + +DisplayModePtr +i830xf86GetDefaultModes (void); + #endif /* _I830_XF86MODES_H_ */ From 86da0d05e4e338e7f4c841577002eb1ba9f6b2ac Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Dec 2006 16:40:54 -0800 Subject: [PATCH 18/37] Add stolen xf86 header files to driver source --- src/xf86Optrec.h | 1 + src/xf86Parser.h | 1 + 2 files changed, 2 insertions(+) create mode 120000 src/xf86Optrec.h create mode 120000 src/xf86Parser.h diff --git a/src/xf86Optrec.h b/src/xf86Optrec.h new file mode 120000 index 00000000..a6ad9ce7 --- /dev/null +++ b/src/xf86Optrec.h @@ -0,0 +1 @@ +../../../xserver/hw/xfree86/parser/xf86Optrec.h \ No newline at end of file diff --git a/src/xf86Parser.h b/src/xf86Parser.h new file mode 120000 index 00000000..83b3aba0 --- /dev/null +++ b/src/xf86Parser.h @@ -0,0 +1 @@ +../../../xserver/hw/xfree86/parser/xf86Parser.h \ No newline at end of file From 4cc5dcf6d7423239f0181f246638366edcb8be87 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Dec 2006 16:43:39 -0800 Subject: [PATCH 19/37] Oops, dont use symlinks for stolen xf86 header files --- src/xf86Optrec.h | 113 ++++++++++- src/xf86Parser.h | 484 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 595 insertions(+), 2 deletions(-) mode change 120000 => 100644 src/xf86Optrec.h mode change 120000 => 100644 src/xf86Parser.h diff --git a/src/xf86Optrec.h b/src/xf86Optrec.h deleted file mode 120000 index a6ad9ce7..00000000 --- a/src/xf86Optrec.h +++ /dev/null @@ -1 +0,0 @@ -../../../xserver/hw/xfree86/parser/xf86Optrec.h \ No newline at end of file diff --git a/src/xf86Optrec.h b/src/xf86Optrec.h new file mode 100644 index 00000000..183b8572 --- /dev/null +++ b/src/xf86Optrec.h @@ -0,0 +1,112 @@ +/* + * + * Copyright (c) 1997 Metro Link Incorporated + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* + * Copyright (c) 1997-2001 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* + * This file contains the Option Record that is passed between the Parser, + * and Module setup procs. + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifndef _xf86Optrec_h_ +#define _xf86Optrec_h_ +#include + +/* + * all records that need to be linked lists should contain a GenericList as + * their first field. + */ +typedef struct generic_list_rec +{ + void *next; +} +GenericListRec, *GenericListPtr, *glp; + +/* + * All options are stored using this data type. + */ +typedef struct +{ + GenericListRec list; + char *opt_name; + char *opt_val; + int opt_used; + char *opt_comment; +} +XF86OptionRec, *XF86OptionPtr; + + +XF86OptionPtr xf86addNewOption(XF86OptionPtr head, char *name, char *val); +XF86OptionPtr xf86optionListDup(XF86OptionPtr opt); +void xf86optionListFree(XF86OptionPtr opt); +char *xf86optionName(XF86OptionPtr opt); +char *xf86optionValue(XF86OptionPtr opt); +XF86OptionPtr xf86newOption(char *name, char *value); +XF86OptionPtr xf86nextOption(XF86OptionPtr list); +XF86OptionPtr xf86findOption(XF86OptionPtr list, const char *name); +char *xf86findOptionValue(XF86OptionPtr list, const char *name); +int xf86findOptionBoolean (XF86OptionPtr, const char *, int); +XF86OptionPtr xf86optionListCreate(const char **options, int count, int used); +XF86OptionPtr xf86optionListMerge(XF86OptionPtr head, XF86OptionPtr tail); +char *xf86configStrdup (const char *s); +int xf86nameCompare (const char *s1, const char *s2); +char *xf86uLongToString(unsigned long i); +void xf86debugListOptions(XF86OptionPtr); +XF86OptionPtr xf86parseOption(XF86OptionPtr head); +void xf86printOptionList(FILE *fp, XF86OptionPtr list, int tabs); + + +#endif /* _xf86Optrec_h_ */ diff --git a/src/xf86Parser.h b/src/xf86Parser.h deleted file mode 120000 index 83b3aba0..00000000 --- a/src/xf86Parser.h +++ /dev/null @@ -1 +0,0 @@ -../../../xserver/hw/xfree86/parser/xf86Parser.h \ No newline at end of file diff --git a/src/xf86Parser.h b/src/xf86Parser.h new file mode 100644 index 00000000..a6829273 --- /dev/null +++ b/src/xf86Parser.h @@ -0,0 +1,483 @@ +/* + * + * Copyright (c) 1997 Metro Link Incorporated + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +/* + * This file contains the external interfaces for the XFree86 configuration + * file parser. + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifndef _xf86Parser_h_ +#define _xf86Parser_h_ + +#include "xf86Optrec.h" + +#define HAVE_PARSER_DECLS + +typedef struct +{ + char *file_logfile; + char *file_rgbpath; + char *file_modulepath; + char *file_inputdevs; + char *file_fontpath; + char *file_comment; +} +XF86ConfFilesRec, *XF86ConfFilesPtr; + +/* Values for load_type */ +#define XF86_LOAD_MODULE 0 +#define XF86_LOAD_DRIVER 1 + +typedef struct +{ + GenericListRec list; + int load_type; + char *load_name; + XF86OptionPtr load_opt; + char *load_comment; + int ignore; +} +XF86LoadRec, *XF86LoadPtr; + +typedef struct +{ + XF86LoadPtr mod_load_lst; + char *mod_comment; +} +XF86ConfModuleRec, *XF86ConfModulePtr; + +#define CONF_IMPLICIT_KEYBOARD "Implicit Core Keyboard" + +#define CONF_IMPLICIT_POINTER "Implicit Core Pointer" + +#define XF86CONF_PHSYNC 0x0001 +#define XF86CONF_NHSYNC 0x0002 +#define XF86CONF_PVSYNC 0x0004 +#define XF86CONF_NVSYNC 0x0008 +#define XF86CONF_INTERLACE 0x0010 +#define XF86CONF_DBLSCAN 0x0020 +#define XF86CONF_CSYNC 0x0040 +#define XF86CONF_PCSYNC 0x0080 +#define XF86CONF_NCSYNC 0x0100 +#define XF86CONF_HSKEW 0x0200 /* hskew provided */ +#define XF86CONF_BCAST 0x0400 +#define XF86CONF_CUSTOM 0x0800 /* timing numbers customized by editor */ +#define XF86CONF_VSCAN 0x1000 + +typedef struct +{ + GenericListRec list; + char *ml_identifier; + int ml_clock; + int ml_hdisplay; + int ml_hsyncstart; + int ml_hsyncend; + int ml_htotal; + int ml_vdisplay; + int ml_vsyncstart; + int ml_vsyncend; + int ml_vtotal; + int ml_vscan; + int ml_flags; + int ml_hskew; + char *ml_comment; +} +XF86ConfModeLineRec, *XF86ConfModeLinePtr; + +typedef struct +{ + GenericListRec list; + char *vp_identifier; + XF86OptionPtr vp_option_lst; + char *vp_comment; +} +XF86ConfVideoPortRec, *XF86ConfVideoPortPtr; + +typedef struct +{ + GenericListRec list; + char *va_identifier; + char *va_vendor; + char *va_board; + char *va_busid; + char *va_driver; + XF86OptionPtr va_option_lst; + XF86ConfVideoPortPtr va_port_lst; + char *va_fwdref; + char *va_comment; +} +XF86ConfVideoAdaptorRec, *XF86ConfVideoAdaptorPtr; + +#define CONF_MAX_HSYNC 8 +#define CONF_MAX_VREFRESH 8 + +typedef struct +{ + float hi, lo; +} +parser_range; + +typedef struct +{ + int red, green, blue; +} +parser_rgb; + +typedef struct +{ + GenericListRec list; + char *modes_identifier; + XF86ConfModeLinePtr mon_modeline_lst; + char *modes_comment; +} +XF86ConfModesRec, *XF86ConfModesPtr; + +typedef struct +{ + GenericListRec list; + char *ml_modes_str; + XF86ConfModesPtr ml_modes; +} +XF86ConfModesLinkRec, *XF86ConfModesLinkPtr; + +typedef struct +{ + GenericListRec list; + char *mon_identifier; + char *mon_vendor; + char *mon_modelname; + int mon_width; /* in mm */ + int mon_height; /* in mm */ + XF86ConfModeLinePtr mon_modeline_lst; + int mon_n_hsync; + parser_range mon_hsync[CONF_MAX_HSYNC]; + int mon_n_vrefresh; + parser_range mon_vrefresh[CONF_MAX_VREFRESH]; + float mon_gamma_red; + float mon_gamma_green; + float mon_gamma_blue; + XF86OptionPtr mon_option_lst; + XF86ConfModesLinkPtr mon_modes_sect_lst; + char *mon_comment; +} +XF86ConfMonitorRec, *XF86ConfMonitorPtr; + +#define CONF_MAXDACSPEEDS 4 +#define CONF_MAXCLOCKS 128 + +typedef struct +{ + GenericListRec list; + char *dev_identifier; + char *dev_vendor; + char *dev_board; + char *dev_chipset; + char *dev_busid; + char *dev_card; + char *dev_driver; + char *dev_ramdac; + int dev_dacSpeeds[CONF_MAXDACSPEEDS]; + int dev_videoram; + int dev_textclockfreq; + unsigned long dev_bios_base; + unsigned long dev_mem_base; + unsigned long dev_io_base; + char *dev_clockchip; + int dev_clocks; + int dev_clock[CONF_MAXCLOCKS]; + int dev_chipid; + int dev_chiprev; + int dev_irq; + int dev_screen; + XF86OptionPtr dev_option_lst; + char *dev_comment; +} +XF86ConfDeviceRec, *XF86ConfDevicePtr; + +typedef struct +{ + GenericListRec list; + char *mode_name; +} +XF86ModeRec, *XF86ModePtr; + +typedef struct +{ + GenericListRec list; + int disp_frameX0; + int disp_frameY0; + int disp_virtualX; + int disp_virtualY; + int disp_depth; + int disp_bpp; + char *disp_visual; + parser_rgb disp_weight; + parser_rgb disp_black; + parser_rgb disp_white; + XF86ModePtr disp_mode_lst; + XF86OptionPtr disp_option_lst; + char *disp_comment; +} +XF86ConfDisplayRec, *XF86ConfDisplayPtr; + +typedef struct +{ + XF86OptionPtr flg_option_lst; + char *flg_comment; +} +XF86ConfFlagsRec, *XF86ConfFlagsPtr; + +typedef struct +{ + GenericListRec list; + char *al_adaptor_str; + XF86ConfVideoAdaptorPtr al_adaptor; +} +XF86ConfAdaptorLinkRec, *XF86ConfAdaptorLinkPtr; + +typedef struct +{ + GenericListRec list; + char *scrn_identifier; + char *scrn_obso_driver; + int scrn_defaultdepth; + int scrn_defaultbpp; + int scrn_defaultfbbpp; + char *scrn_monitor_str; + XF86ConfMonitorPtr scrn_monitor; + char *scrn_device_str; + XF86ConfDevicePtr scrn_device; + XF86ConfAdaptorLinkPtr scrn_adaptor_lst; + XF86ConfDisplayPtr scrn_display_lst; + XF86OptionPtr scrn_option_lst; + char *scrn_comment; +} +XF86ConfScreenRec, *XF86ConfScreenPtr; + +typedef struct +{ + GenericListRec list; + char *inp_identifier; + char *inp_driver; + XF86OptionPtr inp_option_lst; + char *inp_comment; +} +XF86ConfInputRec, *XF86ConfInputPtr; + +typedef struct +{ + GenericListRec list; + XF86ConfInputPtr iref_inputdev; + char *iref_inputdev_str; + XF86OptionPtr iref_option_lst; +} +XF86ConfInputrefRec, *XF86ConfInputrefPtr; + +/* Values for adj_where */ +#define CONF_ADJ_OBSOLETE -1 +#define CONF_ADJ_ABSOLUTE 0 +#define CONF_ADJ_RIGHTOF 1 +#define CONF_ADJ_LEFTOF 2 +#define CONF_ADJ_ABOVE 3 +#define CONF_ADJ_BELOW 4 +#define CONF_ADJ_RELATIVE 5 + +typedef struct +{ + GenericListRec list; + int adj_scrnum; + XF86ConfScreenPtr adj_screen; + char *adj_screen_str; + XF86ConfScreenPtr adj_top; + char *adj_top_str; + XF86ConfScreenPtr adj_bottom; + char *adj_bottom_str; + XF86ConfScreenPtr adj_left; + char *adj_left_str; + XF86ConfScreenPtr adj_right; + char *adj_right_str; + int adj_where; + int adj_x; + int adj_y; + char *adj_refscreen; +} +XF86ConfAdjacencyRec, *XF86ConfAdjacencyPtr; + +typedef struct +{ + GenericListRec list; + char *inactive_device_str; + XF86ConfDevicePtr inactive_device; +} +XF86ConfInactiveRec, *XF86ConfInactivePtr; + +typedef struct +{ + GenericListRec list; + char *lay_identifier; + XF86ConfAdjacencyPtr lay_adjacency_lst; + XF86ConfInactivePtr lay_inactive_lst; + XF86ConfInputrefPtr lay_input_lst; + XF86OptionPtr lay_option_lst; + char *lay_comment; +} +XF86ConfLayoutRec, *XF86ConfLayoutPtr; + +typedef struct +{ + GenericListRec list; + char *vs_name; + char *vs_identifier; + XF86OptionPtr vs_option_lst; + char *vs_comment; +} +XF86ConfVendSubRec, *XF86ConfVendSubPtr; + +typedef struct +{ + GenericListRec list; + char *vnd_identifier; + XF86OptionPtr vnd_option_lst; + XF86ConfVendSubPtr vnd_sub_lst; + char *vnd_comment; +} +XF86ConfVendorRec, *XF86ConfVendorPtr; + +typedef struct +{ + GenericListRec list; + int buf_count; + int buf_size; + char *buf_flags; + char *buf_comment; +} +XF86ConfBuffersRec, *XF86ConfBuffersPtr; + +typedef struct +{ + char *dri_group_name; + int dri_group; + int dri_mode; + XF86ConfBuffersPtr dri_buffers_lst; + char *dri_comment; +} +XF86ConfDRIRec, *XF86ConfDRIPtr; + +typedef struct +{ + XF86OptionPtr ext_option_lst; + char *extensions_comment; +} +XF86ConfExtensionsRec, *XF86ConfExtensionsPtr; + +typedef struct +{ + XF86ConfFilesPtr conf_files; + XF86ConfModulePtr conf_modules; + XF86ConfFlagsPtr conf_flags; + XF86ConfVideoAdaptorPtr conf_videoadaptor_lst; + XF86ConfModesPtr conf_modes_lst; + XF86ConfMonitorPtr conf_monitor_lst; + XF86ConfDevicePtr conf_device_lst; + XF86ConfScreenPtr conf_screen_lst; + XF86ConfInputPtr conf_input_lst; + XF86ConfLayoutPtr conf_layout_lst; + XF86ConfVendorPtr conf_vendor_lst; + XF86ConfDRIPtr conf_dri; + XF86ConfExtensionsPtr conf_extensions; + char *conf_comment; +} +XF86ConfigRec, *XF86ConfigPtr; + +typedef struct +{ + int token; /* id of the token */ + char *name; /* pointer to the LOWERCASED name */ +} +xf86ConfigSymTabRec, *xf86ConfigSymTabPtr; + +/* + * prototypes for public functions + */ +extern const char *xf86openConfigFile (const char *, const char *, + const char *); +extern void xf86setBuiltinConfig(const char *config[]); +extern XF86ConfigPtr xf86readConfigFile (void); +extern void xf86closeConfigFile (void); +extern void xf86freeConfig (XF86ConfigPtr p); +extern int xf86writeConfigFile (const char *, XF86ConfigPtr); +XF86ConfDevicePtr xf86findDevice(const char *ident, XF86ConfDevicePtr p); +XF86ConfLayoutPtr xf86findLayout(const char *name, XF86ConfLayoutPtr list); +XF86ConfMonitorPtr xf86findMonitor(const char *ident, XF86ConfMonitorPtr p); +XF86ConfModesPtr xf86findModes(const char *ident, XF86ConfModesPtr p); +XF86ConfModeLinePtr xf86findModeLine(const char *ident, XF86ConfModeLinePtr p); +XF86ConfScreenPtr xf86findScreen(const char *ident, XF86ConfScreenPtr p); +XF86ConfInputPtr xf86findInput(const char *ident, XF86ConfInputPtr p); +XF86ConfInputPtr xf86findInputByDriver(const char *driver, XF86ConfInputPtr p); +XF86ConfVendorPtr xf86findVendor(const char *name, XF86ConfVendorPtr list); +XF86ConfVideoAdaptorPtr xf86findVideoAdaptor(const char *ident, + XF86ConfVideoAdaptorPtr p); + +GenericListPtr xf86addListItem(GenericListPtr head, GenericListPtr c_new); +int xf86itemNotSublist(GenericListPtr list_1, GenericListPtr list_2); + +int xf86pathIsAbsolute(const char *path); +int xf86pathIsSafe(const char *path); +char *xf86addComment(char *cur, char *add); + +#endif /* _xf86Parser_h_ */ From bedab1654e2dfcf7800bd0101e6991800a544019 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 28 Dec 2006 16:34:40 -0800 Subject: [PATCH 20/37] Remove 8MB/32MB default VideoRam limits. With modern monitors and increased XV and EXA memory requirements, these small limits were resulting in DRI and other initialization failures because we wouldn't allow them enough memory. Instead, allow each piece of the system (DRI, EXA, XAA, etc) to request as much memory as it wants, and choose the actual videoRam to be used for laying out the memory afterwards. With this change, in the absence of a VideoRam option, 32MB will be allocated for textures. --- src/i830.h | 8 ----- src/i830_driver.c | 78 +++++++++++++++++++++-------------------------- src/i830_memory.c | 9 +++++- 3 files changed, 43 insertions(+), 52 deletions(-) diff --git a/src/i830.h b/src/i830.h index fd9f9aa0..06f68384 100644 --- a/src/i830.h +++ b/src/i830.h @@ -604,14 +604,6 @@ DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output); /* i830_tv.c */ void i830_tv_init(ScrnInfoPtr pScrn); -/* - * 12288 is set as the maximum, chosen because it is enough for - * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare. - */ -#define I830_MAXIMUM_VBIOS_MEM 12288 -#define I830_DEFAULT_VIDEOMEM_2D (MB(32) / 1024) -#define I830_DEFAULT_VIDEOMEM_3D (MB(64) / 1024) - /* Flags for memory allocation function */ #define FROM_ANYWHERE 0x00000000 #define FROM_POOL_ONLY 0x00000001 diff --git a/src/i830_driver.c b/src/i830_driver.c index e2653c15..8ca79f1f 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1450,52 +1450,26 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->checkDevices = FALSE; /* - * The "VideoRam" config file parameter specifies the total amount of - * memory that will be used/allocated. When agpgart support isn't - * available (StolenOnly == TRUE), this is limited to the amount of - * pre-allocated ("stolen") memory. - */ - - /* - * Default to I830_DEFAULT_VIDEOMEM_2D (8192KB) for 2D-only, - * or I830_DEFAULT_VIDEOMEM_3D (32768KB) for 3D. If the stolen memory - * amount is higher, default to it rounded up to the nearest MB. This - * guarantees that by default there will be at least some run-time - * space for things that need a physical address. - * But, we double the amounts when dual head is enabled, and therefore - * for 2D-only we use 16384KB, and 3D we use 65536KB. The VideoRAM - * for the second head is never used, as the primary head does the - * allocation. + * The "VideoRam" config file parameter specifies the maximum amount of + * memory that will be used/allocated. When not present, we allow the + * driver to allocate as much memory as it wishes to satisfy its + * allocations, but if agpgart support isn't available (StolenOnly == TRUE), + * it gets limited to the amount of pre-allocated ("stolen") memory. */ if (!pI830->pEnt->device->videoRam) { from = X_DEFAULT; -#ifdef XF86DRI - if (!pI830->directRenderingDisabled) - pScrn->videoRam = I830_DEFAULT_VIDEOMEM_3D; - else -#endif - pScrn->videoRam = I830_DEFAULT_VIDEOMEM_2D; - - if (xf86IsEntityShared(pScrn->entityList[0])) { - if (I830IsPrimary(pScrn)) - pScrn->videoRam += I830_DEFAULT_VIDEOMEM_2D; - else - pScrn->videoRam = I830_MAXIMUM_VBIOS_MEM; - } - - if (pI830->StolenMemory.Size / 1024 > pScrn->videoRam) - pScrn->videoRam = ROUND_TO(pI830->StolenMemory.Size / 1024, 1024); + pScrn->videoRam = pI830->FbMapSize / KB(1); } else { from = X_CONFIG; pScrn->videoRam = pI830->pEnt->device->videoRam; } /* Make sure it's on a page boundary */ - if (pScrn->videoRam & (GTT_PAGE_SIZE - 1)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "VideoRAM reduced to %d kByte " - "(page aligned - was %d)\n", pScrn->videoRam & ~(GTT_PAGE_SIZE - 1), pScrn->videoRam); - pScrn->videoRam &= ~(GTT_PAGE_SIZE - 1); + if (pScrn->videoRam & 3) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB " + "(page aligned - was %d KB)\n", + pScrn->videoRam & ~3, pScrn->videoRam); + pScrn->videoRam &= ~3; } DPRINTF(PFX, @@ -1523,9 +1497,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Pre-allocated VideoRAM: %ld kByte\n", + "Pre-allocated VideoRam: %ld kByte\n", pI830->StolenMemory.Size / 1024); - xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", + xf86DrvMsg(pScrn->scrnIndex, from, "Potential VideoRam: %d kByte\n", pScrn->videoRam); pI830->TotalVideoRam = KB(pScrn->videoRam); @@ -1656,9 +1630,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024); } - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); - if (!xf86RandR12PreInit (pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); @@ -1771,7 +1742,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) "to make room in AGP aperture for tiling."); goto retry_dryrun; } - + /* XXX */ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Allocation with DRI tiling enabled would " "exceed the\n" @@ -1840,6 +1811,27 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) #endif pI830->disableTiling = TRUE; /* no DRI - so disableTiling */ + if (pI830->pEnt->device->videoRam == 0) { + int default_videoram; + + /* Now that we've sized the allocations, reduce our default VideoRam + * allocation from the aperture size to just what we need to cover our + * allocations. Only, put in some slop for alignment and such. + */ + default_videoram = pI830->StolenPool.Total.Size + pI830->allocatedMemory; + default_videoram += KB(512); /* slop */ + /* align to 1MB increments */ + default_videoram = (default_videoram + MB(1) - 1) / MB(1) * MB(1); + + if (default_videoram < KB(pScrn->videoRam)) { + pScrn->videoRam = default_videoram / KB(1); + pI830->TotalVideoRam = KB(pScrn->videoRam); + } + } + xf86DrvMsg(pScrn->scrnIndex, + pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT, + "VideoRam: %d KB\n", pScrn->videoRam); + if (!IS_I965G(pI830) && pScrn->displayWidth * pI830->cpp > 8192) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support DRI with frame buffer stride > 8K.\n"); diff --git a/src/i830_memory.c b/src/i830_memory.c index b41a73d2..3264a2d2 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1239,7 +1239,14 @@ I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags) if (pI830->mmModeFlags & I830_KERNEL_TEX) { - size = GetFreeSpace(pScrn); + if (dryrun && pI830->pEnt->device->videoRam == 0) { + /* If we're laying out a default-sized allocation, then don't be + * too greedy and just ask for 32MB. + */ + size = MB(32); + } else { + size = GetFreeSpace(pScrn); + } if (dryrun && (size < MB(1))) size = MB(1); i = myLog2(size / I830_NR_TEX_REGIONS); From f7b1d4c1f7d17a811e17c6a17861ff70be9fbdd7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Dec 2006 22:18:57 -0800 Subject: [PATCH 21/37] Belinea 10 15 55 monitor quirk - override preferred mode with largest @60Hz Belinea 10 15 55 model monitor reports a preferred mode of 640x350, when in fact it wants a 1024x768 mode @ 60Hz. Add an edid quirk that selects the largest size mode, preferring those closer to 60hz among equal sized modes. --- src/i830_edid_modes.c | 46 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c index 5cef46db..c1216109 100644 --- a/src/i830_edid_modes.c +++ b/src/i830_edid_modes.c @@ -48,6 +48,8 @@ typedef enum { DDC_QUIRK_NONE = 0, /* Force detailed sync polarity to -h +v */ DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0, + /* First detailed mode is bogus, prefer largest mode at 60hz */ + DDC_QUIRK_PREFER_LARGE_60 = 1 << 1, } ddc_quirk_t; static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC) @@ -64,6 +66,16 @@ static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC) return FALSE; } +static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) +{ + /* Belinea 10 15 55 */ + if (memcmp (DDC->vendor.name, "MAX", 4) == 0 && + DDC->vendor.prod_id == 1516) + return TRUE; + + return FALSE; +} + typedef struct { Bool (*detect) (int scrnIndex, xf86MonPtr DDC); ddc_quirk_t quirk; @@ -75,6 +87,10 @@ static const ddc_quirk_map_t ddc_quirks[] = { quirk_dt_sync_hm_vp, DDC_QUIRK_DT_SYNC_HM_VP, "Set detailed timing sync polarity to -h +v" }, + { + quirk_prefer_large_60, DDC_QUIRK_PREFER_LARGE_60, + "Detailed timing is not preferred, use largest mode at 60Hz" + }, { NULL, DDC_QUIRK_NONE, "No known quirks" @@ -234,8 +250,9 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) quirks |= ddc_quirks[i].quirk; } - preferred = PREFERRED_TIMING_MODE(DDC->features.msc); + if (quirks & DDC_QUIRK_PREFER_LARGE_60) + preferred = 0; for (i = 0; i < DET_TIMINGS; i++) { struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; @@ -268,6 +285,33 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks); Modes = xf86ModesAdd(Modes, Mode); + if (quirks & DDC_QUIRK_PREFER_LARGE_60) + { + DisplayModePtr best = Modes; + for (Mode = Modes; Mode; Mode = Mode->next) + { + if (Mode == best) continue; + if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay) + { + best = Mode; + continue; + } + if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay) + { + double mode_refresh = xf86ModeVRefresh (Mode); + double best_refresh = xf86ModeVRefresh (best); + double mode_dist = fabs(mode_refresh - 60.0); + double best_dist = fabs(best_refresh - 60.0); + if (mode_dist < best_dist) + { + best = Mode; + continue; + } + } + } + if (best) + best->type |= M_T_PREFERRED; + } return Modes; } From 973da654219ea43916b0b44acfa09a415bed3d7a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Dec 2006 22:22:22 -0800 Subject: [PATCH 22/37] Sync ranges from EDID/default should not limit configured modelines. Limit the effect of sync ranges so that sync ranges found via EDID will not eliminate modes explicitly added by the user. Limit default sync range to eliminating only default modes, not configured or EDID modes. --- src/i830_xf86Crtc.c | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 763df435..f2d60268 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -542,9 +542,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) { xf86OutputPtr output = config->output[o]; DisplayModePtr mode; + DisplayModePtr config_modes, output_modes, default_modes; XF86ConfMonitorPtr conf_monitor = output->conf_monitor; xf86MonPtr edid_monitor = output->MonInfo; MonRec mon_rec; + enum { sync_config, sync_edid, sync_default } sync_source = sync_default; while (output->probed_modes != NULL) xf86DeleteMode(&output->probed_modes, output->probed_modes); @@ -562,12 +564,14 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; mon_rec.nHsync++; + sync_source = sync_config; } for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) { mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; mon_rec.nVrefresh++; + sync_source = sync_config; } } if (edid_monitor) @@ -586,12 +590,16 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h; mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h; mon_rec.nHsync++; + if (sync_source == sync_default) + sync_source = sync_edid; } if (set_vrefresh && ranges->max_v) { mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v; mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v; mon_rec.nVrefresh++; + if (sync_source == sync_default) + sync_source = sync_edid; } } } @@ -614,19 +622,36 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) mon_rec.nVrefresh = 1; } + config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor); + output_modes = (*output->funcs->get_modes) (output); + default_modes = i830xf86GetDefaultModes (); + + if (sync_source == sync_config) + { + /* + * Check output and config modes against sync range from config file + */ + i830xf86ValidateModesSync (pScrn, output_modes, &mon_rec); + i830xf86ValidateModesSync (pScrn, config_modes, &mon_rec); + } + /* + * Check default modes against sync range + */ + i830xf86ValidateModesSync (pScrn, default_modes, &mon_rec); + output->probed_modes = NULL; - if (conf_monitor) - output->probed_modes = xf86ModesAdd (output->probed_modes, - i830xf86GetMonitorModes (pScrn, conf_monitor)); - output->probed_modes = xf86ModesAdd (output->probed_modes, - (*output->funcs->get_modes) (output)); - output->probed_modes = xf86ModesAdd (output->probed_modes, - i830xf86GetDefaultModes ()); - + output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); + + /* + * Check all modes against virtual size + */ i830xf86ValidateModesSize (pScrn, output->probed_modes, virtualX, virtualY, 0); - i830xf86ValidateModesSync (pScrn, output->probed_modes, &mon_rec); - /* Strip out any modes that can't be supported on this output. */ + /* + * Check all modes against output + */ for (mode = output->probed_modes; mode != NULL; mode = mode->next) if (mode->status == MODE_OK) mode->status = (*output->funcs->mode_valid)(output, mode); From b8692e646227e56c9ae4f72b9aaa75457b4c0f5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Dec 2006 22:23:16 -0800 Subject: [PATCH 23/37] Lack of configured monitor implies no configured modes. Missing check for missing monitor configuration would result in segfault. --- src/i830_xf86Modes.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 58a6e6f9..3a272cbc 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -609,6 +609,9 @@ i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) DisplayModePtr modes = NULL; XF86ConfModesLinkPtr modes_link; + if (!conf_monitor) + return NULL; + /* * first we collect the mode lines from the UseModes directive */ From 4ed79a2ba6250354ffc24fa1f7a21ca914ad157e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 29 Dec 2006 12:19:41 -0800 Subject: [PATCH 24/37] Relax tiling requirements on G965. For the 965, we can tile with the pitch at any integer multiple of a tile size (128 or 512B), up to 128KB. --- src/i830_driver.c | 48 +++++++++++++++++++++++------------------------ src/i830_memory.c | 43 +++++++++++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 40 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 8ca79f1f..7f535ac7 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1663,9 +1663,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pScrn->currentMode = pScrn->modes; -#ifndef USE_PITCHES -#define USE_PITCHES 1 -#endif pI830->disableTiling = FALSE; /* @@ -1685,18 +1682,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) { int savedDisplayWidth = pScrn->displayWidth; int memNeeded = 0; - /* Good pitches to allow tiling. Don't care about pitches < 1024. */ - static const int pitches[] = { -/* - 128 * 2, - 128 * 4, -*/ - 128 * 8, - 128 * 16, - 128 * 32, - 128 * 64, - 0 - }; + Bool tiled = FALSE; #ifdef I830_XV /* @@ -1706,16 +1692,28 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->XvEnabled = !pI830->XvDisabled; #endif - for (i = 0; pitches[i] != 0; i++) { -#if USE_PITCHES - if (pitches[i] >= pScrn->displayWidth) { - pScrn->displayWidth = pitches[i]; - break; + if (IS_I965G(pI830)) { + int tile_pixels = 512 / pI830->cpp; + pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) & + ~(tile_pixels - 1); + tiled = TRUE; + } else { + /* Good pitches to allow tiling. Don't care about pitches < 1024. */ + static const int pitches[] = { + KB(1), + KB(2), + KB(4), + KB(8), + 0 + }; + + for (i = 0; pitches[i] != 0; i++) { + if (pitches[i] >= pScrn->displayWidth) { + pScrn->displayWidth = pitches[i]; + tiled = TRUE; + break; + } } -#else - if (pitches[i] == pScrn->displayWidth) - break; -#endif } /* @@ -1723,7 +1721,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) * memory available to enable tiling. */ savedMMSize = pI830->mmSize; - if (pScrn->displayWidth == pitches[i]) { + if (tiled) { retry_dryrun: I830ResetAllocations(pScrn, 0); if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) && diff --git a/src/i830_memory.c b/src/i830_memory.c index 3264a2d2..5bbf3e30 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -438,20 +438,33 @@ AllocateOverlay(ScrnInfoPtr pScrn, int flags) #endif static Bool -IsTileable(int pitch) +IsTileable(ScrnInfoPtr pScrn, int pitch) { + I830Ptr pI830 = I830PTR(pScrn); + + if (IS_I965G(pI830)) { + if (pitch / 512 * 512 == pitch && pitch <= KB(128)) + return TRUE; + else + return FALSE; + } + /* * Allow tiling for pitches that are a power of 2 multiple of 128 bytes, * up to 64 * 128 (= 8192) bytes. */ switch (pitch) { - case 128 * 1: - case 128 * 2: - case 128 * 4: - case 128 * 8: - case 128 * 16: - case 128 * 32: - case 128 * 64: + case 128: + case 256: + if (IS_I945G(pI830) || IS_I945GM(pI830)) + return TRUE; + else + return FALSE; + case 512: + case KB(1): + case KB(2): + case KB(4): + case KB(8): return TRUE; default: return FALSE; @@ -475,7 +488,7 @@ I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, int flags) memset(&(pI830->RotatedMem), 0, sizeof(I830MemRange)); pI830->RotatedMem.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; @@ -540,7 +553,7 @@ I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, int flags) memset(&(pI830->RotatedMem2), 0, sizeof(I830MemRange)); pI830->RotatedMem2.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); + IsTileable(pScrn, pI830Ent->pScrn_2->displayWidth * pI8302->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; @@ -699,7 +712,7 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, } tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { if (IS_I9XX(pI830)) align = MB(1); @@ -886,7 +899,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) maxFb / lineSize - pScrn->virtualY); pI830->FbMemBox.y2 = maxFb / lineSize; tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { if (IS_I9XX(pI830)) align = MB(1); @@ -1113,7 +1126,7 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags) memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer)); pI830->BackBuffer.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; @@ -1176,7 +1189,7 @@ I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags) memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer)); pI830->DepthBuffer.Key = -1; tileable = !(flags & ALLOC_NO_TILING) && - IsTileable(pScrn->displayWidth * pI830->cpp); + IsTileable(pScrn, pScrn->displayWidth * pI830->cpp); if (tileable) { /* Make the height a multiple of the tile height (16) */ lines = (height + 15) / 16 * 16; @@ -1714,7 +1727,7 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) if (!pI830->directRenderingEnabled) return; - if (!IsTileable(pScrn->displayWidth * pI830->cpp)) { + if (!IsTileable(pScrn, pScrn->displayWidth * pI830->cpp)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I830SetupMemoryTiling: Not tileable 0x%x\n", pScrn->displayWidth * pI830->cpp); From 8b6c456e16c81f719bb68178e3e4d26f4108a9c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 30 Dec 2006 21:57:42 -0800 Subject: [PATCH 25/37] Detect in ProbeModes. Let get_modes set edid. Prune interlace/dblscan. Move output connection status detection from RandR code up to ProbeModes so it is done before mode sets are built. Otherwise, the mode building code will elide all modes the first time through as it ignores outputs that are disconnected. Most get_modes functions fetch EDID data; make sure that any EDID changes are used in the ProbeModes filtering of default modes. Otherwise, stale EDID data will be used. Allow outputs to advertise support for interlaced and double scan modes; prune such modes from the default mode list when outputs do not support them. --- src/i830_crt.c | 2 ++ src/i830_dvo.c | 2 ++ src/i830_lvds.c | 2 ++ src/i830_randr.c | 2 +- src/i830_sdvo.c | 2 ++ src/i830_tv.c | 2 ++ src/i830_xf86Crtc.c | 26 +++++++++++++++++++------- src/i830_xf86Crtc.h | 16 ++++++++++++++++ src/i830_xf86Modes.c | 9 ++++++++- src/i830_xf86Modes.h | 2 +- 10 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/i830_crt.c b/src/i830_crt.c index 85c25de1..4e9e3706 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -365,6 +365,8 @@ i830_crt_init(ScrnInfoPtr pScrn) i830_output->type = I830_OUTPUT_ANALOG; output->driver_private = i830_output; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; /* Set up the DDC bus. */ I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A"); diff --git a/src/i830_dvo.c b/src/i830_dvo.c index d1010545..37caf000 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -257,6 +257,8 @@ i830_dvo_init(ScrnInfoPtr pScrn) intel_output->type = I830_OUTPUT_DVO; output->driver_private = intel_output; output->subpixel_order = SubPixelHorizontalRGB; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; /* Set up the DDC bus */ ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D"); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index fe964136..18ac76bf 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -361,6 +361,8 @@ i830_lvds_init(ScrnInfoPtr pScrn) intel_output->type = I830_OUTPUT_LVDS; output->driver_private = intel_output; output->subpixel_order = SubPixelHorizontalRGB; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. diff --git a/src/i830_randr.c b/src/i830_randr.c index 3d6febc1..64d7d1fa 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -740,7 +740,7 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) output->mm_height); xf86RROutputSetModes (output->randr_output, output->probed_modes); - switch (output->status = (*output->funcs->detect)(output)) { + switch (output->status) { case XF86OutputStatusConnected: RROutputSetConnection (output->randr_output, RR_Connected); break; diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index cb68802a..b5116be0 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -1091,6 +1091,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) return; } output->driver_private = intel_output; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; dev_priv = (struct i830_sdvo_priv *) (intel_output + 1); intel_output->type = I830_OUTPUT_SDVO; diff --git a/src/i830_tv.c b/src/i830_tv.c index 62318911..f17a3532 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -1035,4 +1035,6 @@ i830_tv_init(ScrnInfoPtr pScrn) dev_priv->type = TV_TYPE_UNKNOWN; output->driver_private = intel_output; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; } diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index f2d60268..6e9e52ac 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -542,19 +542,27 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) { xf86OutputPtr output = config->output[o]; DisplayModePtr mode; - DisplayModePtr config_modes, output_modes, default_modes; - XF86ConfMonitorPtr conf_monitor = output->conf_monitor; - xf86MonPtr edid_monitor = output->MonInfo; + DisplayModePtr config_modes = NULL, output_modes, default_modes; + XF86ConfMonitorPtr conf_monitor; + xf86MonPtr edid_monitor; MonRec mon_rec; enum { sync_config, sync_edid, sync_default } sync_source = sync_default; while (output->probed_modes != NULL) xf86DeleteMode(&output->probed_modes, output->probed_modes); + /* + * Check connection status + */ + output->status = (*output->funcs->detect)(output); + if (output->status == XF86OutputStatusDisconnected) continue; memset (&mon_rec, '\0', sizeof (mon_rec)); + + conf_monitor = output->conf_monitor; + if (conf_monitor) { int i; @@ -573,7 +581,13 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) mon_rec.nVrefresh++; sync_source = sync_config; } + config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor); } + + output_modes = (*output->funcs->get_modes) (output); + + edid_monitor = output->MonInfo; + if (edid_monitor) { int i; @@ -621,10 +635,8 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) mon_rec.vrefresh[0].hi = 62.0; mon_rec.nVrefresh = 1; } - - config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor); - output_modes = (*output->funcs->get_modes) (output); - default_modes = i830xf86GetDefaultModes (); + default_modes = i830xf86GetDefaultModes (output->interlaceAllowed, + output->doubleScanAllowed); if (sync_source == sync_config) { diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 168d89d8..3e705632 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -261,6 +261,17 @@ struct _xf86Output { * Possible outputs to share the same CRTC as a mask of output indices */ CARD32 possible_clones; + + /** + * Whether this output can support interlaced modes + */ + Bool interlaceAllowed; + + /** + * Whether this output can support double scan modes + */ + Bool doubleScanAllowed; + /** * List of available modes on this output. * @@ -269,6 +280,11 @@ struct _xf86Output { */ DisplayModePtr probed_modes; + /** + * Desired initial position + */ + int initial_x, initial_y; + /** * Current connection status * diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index 3a272cbc..482a3320 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -636,13 +636,20 @@ i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) * Build a mode list containing all of the default modes */ DisplayModePtr -i830xf86GetDefaultModes (void) +i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed) { DisplayModePtr head = NULL, prev = NULL, mode; int i; for (i = 0; xf86DefaultModes[i].name != NULL; i++) { + DisplayModePtr defMode = &xf86DefaultModes[i]; + + if (!interlaceAllowed && (defMode->Flags & V_INTERLACE)) + continue; + if (!doubleScanAllowed && (defMode->Flags & V_DBLSCAN)) + continue; + mode = xalloc(sizeof(DisplayModeRec)); if (!mode) continue; diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index 280743bd..a7d0839d 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -90,6 +90,6 @@ DisplayModePtr i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor); DisplayModePtr -i830xf86GetDefaultModes (void); +i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed); #endif /* _I830_XF86MODES_H_ */ From 2330b341c925e60bc2c991b4ca8450badbc459a4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 30 Dec 2006 22:47:58 -0800 Subject: [PATCH 26/37] Prune default modes to EDID clock limit. Pick out the EDID max clock value and use that to elide default modes which are too fast. --- src/i830_xf86Crtc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 6e9e52ac..91f6071e 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -546,6 +546,8 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) XF86ConfMonitorPtr conf_monitor; xf86MonPtr edid_monitor; MonRec mon_rec; + int min_clock = 0; + int max_clock = 0; enum { sync_config, sync_edid, sync_default } sync_source = sync_default; while (output->probed_modes != NULL) @@ -615,6 +617,8 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) if (sync_source == sync_default) sync_source = sync_edid; } + if (ranges->max_clock > max_clock) + max_clock = ranges->max_clock; } } } @@ -650,6 +654,12 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) * Check default modes against sync range */ i830xf86ValidateModesSync (pScrn, default_modes, &mon_rec); + /* + * Check default modes against monitor max clock + */ + if (max_clock) + i830xf86ValidateModesClocks(pScrn, default_modes, + &min_clock, &max_clock, 1); output->probed_modes = NULL; output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); From 5e456251f0d6c8bef3241267f6c1b3bca4670c0d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 31 Dec 2006 14:21:12 -0800 Subject: [PATCH 27/37] Replace author-specific license with generic license. This file retained the old MIT license with the embedded author name. Replace that with the version that uses generic 'copyright holders' instead. --- src/i830_randr.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index 64d7d1fa..aa50254f 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -6,21 +6,21 @@ * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H From feeefc92e450e9de58da51147325300ffabd2059 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 31 Dec 2006 14:22:53 -0800 Subject: [PATCH 28/37] Replace author-specific license with generic license. This file retained the old MIT license with the embedded author name. Replace that with the version that uses generic 'copyright holders' instead. --- src/i830_xf86Crtc.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 91f6071e..3a68985c 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -1,25 +1,23 @@ /* - * $Id: $ - * * Copyright © 2006 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H From 25d5a892319b02dc6eb81390dea29cd88a1e7da4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 31 Dec 2006 15:39:20 -0800 Subject: [PATCH 29/37] Elide identical modes from reported list. Where two modes would produce precisely the same crtc settings and have the same name, remove the latter mode from the mode list. --- src/i830_xf86Crtc.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 3a68985c..33f96abc 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -499,8 +499,9 @@ i830xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) static DisplayModePtr i830xf86SortModes (DisplayModePtr input) { - DisplayModePtr output = NULL, i, o, *op, prev; + DisplayModePtr output = NULL, i, o, n, *op, prev; + /* sort by preferred status and pixel area */ while (input) { i = input; @@ -511,6 +512,17 @@ i830xf86SortModes (DisplayModePtr input) i->next = *op; *op = i; } + /* prune identical modes */ + for (o = output; o && (n = o->next); o = n) + { + if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) + { + o->next = n->next; + xfree (n->name); + xfree (n); + n = o; + } + } /* hook up backward links */ prev = NULL; for (o = output; o; o = o->next) From 237847007afb5a429a50b6aa0b1acc239326571b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Jan 2007 00:09:35 -0800 Subject: [PATCH 30/37] Make driver build and run on Xorg 7.1. Delay DSP*BASE setting until last. Autodetect libdrm version, disable new memory manager on older libraries. Move new M_T_ defines from i830.h to i830_xf86Crtc.h. Add many system headers to define functions. Use i830PipeSetBase at end of mode setting code to set DSP*BASE and flush changes. Don't duplicate PipeSetBase call from screen init function. Make initial RandR configuration code usable on older versions of extension so the server doesn't start in a panning mode. Use xfree instead of free in i830_tv.c. --- configure.ac | 6 +- src/i830.h | 8 -- src/i830_debug.c | 1 + src/i830_display.c | 8 +- src/i830_dri.c | 5 +- src/i830_driver.c | 20 ++--- src/i830_edid_modes.c | 2 + src/i830_exa.c | 1 + src/i830_randr.c | 200 +++++++++++++++++++----------------------- src/i830_tv.c | 1 + src/i830_xf86Crtc.c | 7 +- src/i830_xf86Crtc.h | 8 ++ src/i830_xf86cvt.c | 1 + src/i965_video.c | 1 + 14 files changed, 132 insertions(+), 137 deletions(-) diff --git a/configure.ac b/configure.ac index be80a872..b295c5ae 100644 --- a/configure.ac +++ b/configure.ac @@ -120,9 +120,13 @@ fi AM_CONDITIONAL(DRI, test x$DRI = xyes) if test "$DRI" = yes; then - PKG_CHECK_MODULES(DRI, [libdrm >= 2.2 xf86driproto]) + PKG_CHECK_MODULES(DRI, [libdrm xf86driproto]) AC_DEFINE(XF86DRI,1,[Enable DRI driver support]) AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support]) + PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.2],[DRI_MM=yes], [DRI_MM=no]) + if test "x$DRM_MM" = xyes; then + AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management]) + fi fi AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes) diff --git a/src/i830.h b/src/i830.h index 06f68384..c2670cda 100644 --- a/src/i830.h +++ b/src/i830.h @@ -628,14 +628,6 @@ void i830_tv_init(ScrnInfoPtr pScrn); #define _845_DRAM_RW_CONTROL 0x90 #define DRAM_WRITE 0x33330000 -/* Compat definitions for older X Servers. */ -#ifndef M_T_PREFERRED -#define M_T_PREFERRED 0x08 -#endif -#ifndef M_T_DRIVER -#define M_T_DRIVER 0x40 -#endif - /* * Xserver MM compatibility. Remove code guarded by this when the * XServer contains the libdrm mm code diff --git a/src/i830_debug.c b/src/i830_debug.c index 25245fb2..897ab926 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -32,6 +32,7 @@ #include "xf86.h" #include "i830.h" #include "i830_debug.h" +#include #define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val) diff --git a/src/i830_display.c b/src/i830_display.c index c5880d6b..9ec46a45 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -350,8 +350,8 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) } if (IS_I965G(pI830)) { - OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp)); - OUTREG(dspsurf, Start); + OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp)); + OUTREG(dspsurf, Start); } else { OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); } @@ -603,7 +603,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; @@ -828,13 +827,12 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1)); OUTREG(dsppos_reg, 0); OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1)); - i830PipeSetBase(crtc, crtc->x, crtc->y); OUTREG(pipeconf_reg, pipeconf); i830WaitForVblank(pScrn); OUTREG(dspcntr_reg, dspcntr); /* Flush the plane changes */ - OUTREG(dspbase_reg, INREG(dspbase_reg)); + i830PipeSetBase(crtc, crtc->x, crtc->y); i830WaitForVblank(pScrn); } diff --git a/src/i830_dri.c b/src/i830_dri.c index c5d7a94e..5fdacc7d 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -655,11 +655,14 @@ I830DRIScreenInit(ScreenPtr pScreen) } pI830->drmMinor = version->version_minor; if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) { +#ifdef XF86DRI_MM if ((version->version_major > 1) || ((version->version_minor >= 7) && (version->version_major == 1))) { pI830->mmModeFlags |= I830_KERNEL_MM; - } else { + } else +#endif + { pI830->mmModeFlags |= I830_KERNEL_TEX; } } else { diff --git a/src/i830_driver.c b/src/i830_driver.c index 7f535ac7..52647676 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2469,11 +2469,7 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn) } } -#ifdef XF86DRI -#ifndef DRM_BO_MEM_TT -#error "Wrong drm.h file included. You need to compile and install a recent libdrm." -#endif - +#ifdef XF86DRI_MM #ifndef XSERVER_LIBDRM_MM static int @@ -2548,7 +2544,7 @@ static int I830DrmMMUnlock(int fd, unsigned memType) } #endif -#endif +#endif /* XF86DRI_MM */ static Bool I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) @@ -3001,7 +2997,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) break; } -#ifdef XF86DRI +#ifdef XF86DRI_MM if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM)) { unsigned long aperEnd = ROUND_DOWN_TO(pI830->FbMapSize, GTT_PAGE_SIZE) / GTT_PAGE_SIZE; @@ -3040,7 +3036,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } } -#endif +#endif /* XF86DRI_MM */ return TRUE; } @@ -3101,6 +3097,7 @@ I830LeaveVT(int scrnIndex, int flags) #ifdef XF86DRI if (pI830->directRenderingOpen) { DRILock(screenInfo.screens[pScrn->scrnIndex], 0); +#ifdef XF86DRI_MM if (pI830->mmModeFlags & I830_KERNEL_MM) { #ifndef XSERVER_LIBDRM_MM I830DrmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT); @@ -3108,6 +3105,7 @@ I830LeaveVT(int scrnIndex, int flags) drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT); #endif } +#endif /* XF86DRI_MM */ I830DRISetVBlankInterrupt (pScrn, FALSE); drmCtlUninstHandler(pI830->drmSubFD); @@ -3185,8 +3183,6 @@ I830EnterVT(int scrnIndex, int flags) if (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE)) return FALSE; - - i830PipeSetBase(crtc, crtc->x, crtc->y); } i830DumpRegs (pScrn); @@ -3221,6 +3217,7 @@ I830EnterVT(int scrnIndex, int flags) for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++) sarea->texList[i].age = sarea->texAge; +#ifdef XF86DRI_MM if (pI830->mmModeFlags & I830_KERNEL_MM) { #ifndef XSERVER_LIBDRM_MM I830DrmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT); @@ -3228,6 +3225,7 @@ I830EnterVT(int scrnIndex, int flags) drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT); #endif } +#endif /* XF86DRI_MM */ DPRINTF(PFX, "calling dri unlock\n"); DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); @@ -3371,6 +3369,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) pI830->closing = TRUE; #ifdef XF86DRI if (pI830->directRenderingOpen) { +#ifdef XF86DRI_MM if (pI830->mmModeFlags & I830_KERNEL_MM) { #ifndef XSERVER_LIBDRM_MM I830DrmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT); @@ -3378,6 +3377,7 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT); #endif } +#endif /* XF86DRI_MM */ pI830->directRenderingOpen = FALSE; I830DRICloseScreen(pScreen); } diff --git a/src/i830_edid_modes.c b/src/i830_edid_modes.c index c1216109..31ce1000 100644 --- a/src/i830_edid_modes.c +++ b/src/i830_edid_modes.c @@ -37,6 +37,8 @@ #include "xf86DDC.h" #include "i830.h" #include "i830_display.h" +#include +#include #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) diff --git a/src/i830_exa.c b/src/i830_exa.c index 7de56176..9356c79c 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -36,6 +36,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i810_reg.h" #include "i830_reg.h" +#include #ifdef I830DEBUG #define DEBUG_I830FALLBACK 1 diff --git a/src/i830_randr.c b/src/i830_randr.c index aa50254f..55ff31e2 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -325,6 +325,44 @@ xf86RandR12SetConfig (ScreenPtr pScreen, return TRUE; } +static Bool +xf86RandR12ScreenSetSize (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + WindowPtr pRoot = WindowTable[pScreen->myNum]; + Bool ret = TRUE; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + if (pRoot) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); + pScrn->virtualX = width; + pScrn->virtualY = height; + + pScreen->width = pScrn->virtualX; + pScreen->height = pScrn->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + + xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); +#if RANDR_12_INTERFACE + if (WindowTable[pScreen->myNum]) + RRScreenSizeNotify (pScreen); +#endif + return ret; +} + Rotation xf86RandR12GetRotation(ScreenPtr pScreen) { @@ -336,37 +374,67 @@ xf86RandR12GetRotation(ScreenPtr pScreen) Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen) { -#if 0 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); -#endif + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int c; + int width, height; + int mmWidth, mmHeight; #ifdef PANORAMIX /* XXX disable RandR when using Xinerama */ if (!noPanoramiXExtension) return TRUE; #endif + + /* + * Compute size of screen + */ + width = 0; height = 0; + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + int crtc_width = crtc->x + crtc->curMode.HDisplay; + int crtc_height = crtc->y + crtc->curMode.VDisplay; + + if (crtc->enabled && crtc_width > width) + width = crtc_width; + if (crtc->enabled && crtc_height > height) + height = crtc_height; + } + + if (width && height) + { + /* + * Compute physical size of screen + */ + if (monitorResolution) + { + mmWidth = width * 25.4 / monitorResolution; + mmHeight = height * 25.4 / monitorResolution; + } + else + { + mmWidth = pScreen->mmWidth; + mmHeight = pScreen->mmHeight; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Setting screen physical size to %d x %d\n", + mmWidth, mmHeight); + xf86RandR12ScreenSetSize (pScreen, + width, + height, + mmWidth, + mmHeight); + } + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } #if RANDR_12_INTERFACE if (xf86RandR12CreateScreenResources12 (pScreen)) return TRUE; -#endif -#if 0 - /* XXX deal with initial rotation */ - if (pI830->rotation != RR_Rotate_0) { - RRScreenSize p; - Rotation requestedRotation = pI830->rotation; - - pI830->rotation = RR_Rotate_0; - - /* Just setup enough for an initial rotate */ - p.width = pScreen->width; - p.height = pScreen->height; - p.mmWidth = pScreen->mmWidth; - p.mmHeight = pScreen->mmHeight; - - pI830->starting = TRUE; /* abuse this for dual head & rotation */ - xf86RandR12SetConfig (pScreen, requestedRotation, 0, &p); - pI830->starting = FALSE; - } #endif return TRUE; } @@ -449,42 +517,6 @@ xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) } #if RANDR_12_INTERFACE -static Bool -xf86RandR12ScreenSetSize (ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, - CARD32 mmHeight) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); - WindowPtr pRoot = WindowTable[pScreen->myNum]; - Bool ret = TRUE; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } - if (pRoot) - (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); - pScrn->virtualX = width; - pScrn->virtualY = height; - - pScreen->width = pScrn->virtualX; - pScreen->height = pScrn->virtualY; - pScreen->mmWidth = mmWidth; - pScreen->mmHeight = mmHeight; - - xf86SetViewport (pScreen, pScreen->width, pScreen->height); - xf86SetViewport (pScreen, 0, 0); - if (pRoot) - (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); - if (WindowTable[pScreen->myNum]) - RRScreenSizeNotify (pScreen); - return ret; -} - static Bool xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) { @@ -832,62 +864,10 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen) static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - int c; - int width, height; - int mmWidth, mmHeight; - - /* - * Compute size of screen - */ - width = 0; height = 0; - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - int crtc_width = crtc->x + crtc->curMode.HDisplay; - int crtc_height = crtc->y + crtc->curMode.VDisplay; - - if (crtc->enabled && crtc_width > width) - width = crtc_width; - if (crtc->enabled && crtc_height > height) - height = crtc_height; - } - if (width && height) - { - /* - * Compute physical size of screen - */ - if (monitorResolution) - { - mmWidth = width * 25.4 / monitorResolution; - mmHeight = height * 25.4 / monitorResolution; - } - else - { - mmWidth = pScreen->mmWidth; - mmHeight = pScreen->mmHeight; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Setting screen physical size to %d x %d\n", - mmWidth, mmHeight); - xf86RandR12ScreenSetSize (pScreen, - width, - height, - mmWidth, - mmHeight); - } - for (c = 0; c < config->num_crtc; c++) xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } RRScreenSetSizeRange (pScreen, 320, 240, randrp->virtualX, randrp->virtualY); diff --git a/src/i830_tv.c b/src/i830_tv.c index f17a3532..5cf36a5a 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -36,6 +36,7 @@ #include "xf86.h" #include "i830.h" #include "i830_display.h" +#include enum tv_type { TV_TYPE_NONE, diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 33f96abc..a0f44df5 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -143,7 +143,7 @@ xf86OutputSetMonitor (xf86OutputPtr output) monitor = output->name; else xf86MarkOptionUsedByName (output->scrn->options, option_name); - free (option_name); + xfree (option_name); output->conf_monitor = xf86findMonitor (monitor, xf86configptr->conf_monitor_lst); } @@ -1026,7 +1026,10 @@ i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) { ScrnInfoPtr pScrn = output->scrn; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - int i, size; + int i; +#ifdef RANDR_12_INTERFACE + int size; +#endif if (output->MonInfo != NULL) xfree(output->MonInfo); diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 3e705632..b30003e7 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -27,6 +27,14 @@ #include "i830_xf86Modes.h" #include "xf86Parser.h" +/* Compat definitions for older X Servers. */ +#ifndef M_T_PREFERRED +#define M_T_PREFERRED 0x08 +#endif +#ifndef M_T_DRIVER +#define M_T_DRIVER 0x40 +#endif + typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr; typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr; diff --git a/src/i830_xf86cvt.c b/src/i830_xf86cvt.c index dba57c82..1a2b7869 100644 --- a/src/i830_xf86cvt.c +++ b/src/i830_xf86cvt.c @@ -39,6 +39,7 @@ #include "i830.h" #include "i830_display.h" +#include #if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) /* diff --git a/src/i965_video.c b/src/i965_video.c index 0d1bec69..9e96527d 100644 --- a/src/i965_video.c +++ b/src/i965_video.c @@ -39,6 +39,7 @@ #include "i830_video.h" #include "brw_defines.h" #include "brw_structs.h" +#include /* Make assert() work. */ #undef NDEBUG From 5080307230d534b84090bfefc13ac437d53f915d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Jan 2007 00:16:41 -0800 Subject: [PATCH 31/37] Fix driver to build on RandR 1.2 systems again. Changes to move initial config code to RandR 1.1/1.2 common path broke code required only for RandR 1.2. --- src/i830_randr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/i830_randr.c b/src/i830_randr.c index 55ff31e2..d5ccce37 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -864,7 +864,11 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen) static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) { - + int c; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + for (c = 0; c < config->num_crtc; c++) xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); From 2bb9bb951e664d704bdf7a808edbe8b2f50c4366 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Jan 2007 14:04:10 -0800 Subject: [PATCH 32/37] Typo disabled new DRI MM on all chips. Detection for new DRI MM wasn't converted to #define correctly because of a typo. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b295c5ae..70ae8078 100644 --- a/configure.ac +++ b/configure.ac @@ -124,7 +124,7 @@ if test "$DRI" = yes; then AC_DEFINE(XF86DRI,1,[Enable DRI driver support]) AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support]) PKG_CHECK_MODULES(DRI_MM, [libdrm >= 2.2],[DRI_MM=yes], [DRI_MM=no]) - if test "x$DRM_MM" = xyes; then + if test "x$DRI_MM" = xyes; then AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management]) fi fi From 5057769d3a7c1b3a94f49bbff47b9697f368d975 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 2 Jan 2007 19:25:08 -0800 Subject: [PATCH 33/37] Use correct variable to initialize DVO I2C bus. intel_output->pI2CBus isn't initialized until the output is all happy and running, so using it before that is rather unlikely to do much good. --- src/i830_dvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 37caf000..d938f466 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -294,7 +294,7 @@ i830_dvo_init(ScrnInfoPtr pScrn) if (gpio_inited != gpio) { if (pI2CBus != NULL) xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); - if (!I830I2CInit(pScrn, &intel_output->pI2CBus, gpio, + if (!I830I2CInit(pScrn, &pI2CBus, gpio, gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E")) { continue; } From d960deab39eef91fb82b9f23118323aeb4c9c63e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 2 Jan 2007 20:23:37 -0800 Subject: [PATCH 34/37] Various sparse cleanups: NULL vs. 0 remove redundant pScrn in I830DRISwapContext make I830DRISwapContext static --- src/i830_dri.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/i830_dri.c b/src/i830_dri.c index 5fdacc7d..eeef2895 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -216,9 +216,9 @@ I830InitVisualConfigs(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); int numConfigs = 0; - __GLXvisualConfig *pConfigs = 0; - I830ConfigPrivPtr pI830Configs = 0; - I830ConfigPrivPtr *pI830ConfigPtrs = 0; + __GLXvisualConfig *pConfigs = NULL; + I830ConfigPrivPtr pI830Configs = NULL; + I830ConfigPrivPtr *pI830ConfigPtrs = NULL; int accum, stencil, db, depth; int i; @@ -538,7 +538,7 @@ I830DRIScreenInit(ScreenPtr pScreen) if (!(pI830DRI = (I830DRIPtr) xcalloc(sizeof(I830DRIRec), 1))) { DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; return FALSE; } pDRIInfo->devPrivate = pI830DRI; @@ -561,9 +561,9 @@ I830DRIScreenInit(ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling DRI.\n"); xfree(pDRIInfo->devPrivate); - pDRIInfo->devPrivate = 0; + pDRIInfo->devPrivate = NULL; DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; return FALSE; } @@ -951,10 +951,10 @@ I830DRICloseScreen(ScreenPtr pScreen) if (pI830->pDRIInfo) { if (pI830->pDRIInfo->devPrivate) { xfree(pI830->pDRIInfo->devPrivate); - pI830->pDRIInfo->devPrivate = 0; + pI830->pDRIInfo->devPrivate = NULL; } DRIDestroyInfoRec(pI830->pDRIInfo); - pI830->pDRIInfo = 0; + pI830->pDRIInfo = NULL; } if (pI830->pVisualConfigs) xfree(pI830->pVisualConfigs); @@ -1025,7 +1025,7 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) } } -void +static void I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext) @@ -1035,7 +1035,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, if (syncType == DRI_3D_SYNC && oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("i830DRISwapContext (in)\n"); @@ -1128,9 +1127,9 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, BoxPtr pbox = REGION_RECTS(prgnSrc); int nbox = REGION_NUM_RECTS(prgnSrc); - BoxPtr pboxNew1 = 0; - BoxPtr pboxNew2 = 0; - DDXPointPtr pptNew1 = 0; + BoxPtr pboxNew1 = NULL; + BoxPtr pboxNew2 = NULL; + DDXPointPtr pptNew1 = NULL; DDXPointPtr pptSrc = &ptOldOrg; int dx = pParent->drawable.x - ptOldOrg.x; From 58e797b2caa6effa5455fc1f13dc4c58d0658744 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 3 Jan 2007 00:04:58 -0800 Subject: [PATCH 35/37] Sync dspbase/dspsurf registers by re-reading them. This seems to eliminate base/surf value confusion during EnterVT. --- src/i830_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/i830_display.c b/src/i830_display.c index 9ec46a45..d124ba0a 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -351,9 +351,12 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) if (IS_I965G(pI830)) { OUTREG(dspbase, ((y * pScrn->displayWidth + x) * pI830->cpp)); + (void) INREG(dspbase); OUTREG(dspsurf, Start); + (void) INREG(dspsurf); } else { OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + (void) INREG(dspbase); } crtc->x = x; From 232e2094321dbcdd6a67ef230eb50494a1c7d6df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 3 Jan 2007 00:38:34 -0800 Subject: [PATCH 36/37] Allow initial position to be set in config file. Increase 965 max size. Add relative and absolute position configuration code, using per-output monitor sections. Options include: PreferredMode selects a preferred mode for this output by name Position absolute position, x and y in a single string. Below relative positions; argument names other monitor. RightOf Above LeftOf Enable force the monitor to be disabled by setting Disable enable to no or disable to yes. MinClock Set valid clock ranges MaxClock Monitor sections can also include sync ranges, physical size and mode lines as documented in xorg.conf(5). Monitors are associated with outputs through options in the Device section: Option "monitor-VGA" "My VGA Monitor" Output named 'VGA' will use monitor section "My VGA Monitor". --- src/i830_driver.c | 25 ++- src/i830_randr.c | 4 +- src/i830_sdvo.c | 7 +- src/i830_xf86Crtc.c | 410 ++++++++++++++++++++++++++++++++++++-------- src/i830_xf86Crtc.h | 20 ++- 5 files changed, 375 insertions(+), 91 deletions(-) diff --git a/src/i830_driver.c b/src/i830_driver.c index 52647676..694c96f3 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -912,7 +912,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) Bool enable; const char *chipname; int num_pipe; - int max_width; + int max_width, max_height; #ifdef XF86DRI unsigned long savedMMSize; #endif @@ -1183,10 +1183,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); if (IS_I965G(pI830)) + { max_width = 16384; + max_height = 4096; + } else - max_width = 8192 / pI830->cpp; - xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, 2048); + { + max_width = 2048; + max_height = 2048; + } + xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, max_height); /* Some of the probing needs MMIO access, so map it here. */ I830MapMMIO(pScrn); @@ -1830,14 +1836,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT, "VideoRam: %d KB\n", pScrn->videoRam); - if (!IS_I965G(pI830) && pScrn->displayWidth * pI830->cpp > 8192) { + if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Cannot support DRI with frame buffer stride > 8K.\n"); + "Cannot support DRI with frame buffer width > 2048.\n"); pI830->disableTiling = TRUE; pI830->directRenderingDisabled = TRUE; } - if (pScrn->virtualY > 2048) { + if (!IS_I965G(pI830) && pScrn->virtualY > 2048) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support > 2048 vertical lines. disabling acceleration.\n"); pI830->noAccel = TRUE; } @@ -3047,7 +3053,8 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); - xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; + xf86OutputPtr output = config->output[config->compat_output]; + xf86CrtcPtr crtc = output->crtc; DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); @@ -3059,7 +3066,7 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) (*pI830->AccelInfoRec->Sync)(pScrn); pI830->AccelInfoRec->NeedToSync = FALSE; } - i830PipeSetBase(crtc, x, y); + i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y); } } @@ -3596,7 +3603,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) * is this. */ - xf86ProbeOutputModes (pScrn); + xf86ProbeOutputModes (pScrn, 0, 0); xf86SetScrnInfoModes (pScrn); I830DGAReInit (pScrn->pScreen); xf86SwitchMode(pScrn->pScreen, pScrn->currentMode); diff --git a/src/i830_randr.c b/src/i830_randr.c index d5ccce37..83cf0238 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -95,7 +95,7 @@ xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) } /* Re-probe the outputs for new monitors or modes */ - xf86ProbeOutputModes (scrp); + xf86ProbeOutputModes (scrp, 0, 0); xf86SetScrnInfoModes (scrp); I830DGAReInit (pScreen); @@ -818,7 +818,7 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86ProbeOutputModes (pScrn); + xf86ProbeOutputModes (pScrn, 0, 0); xf86SetScrnInfoModes (pScrn); I830DGAReInit (pScreen); return xf86RandR12SetInfo12 (pScreen); diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index b5116be0..19b4b934 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -1207,7 +1207,12 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) } strcpy (name, name_prefix); strcat (name, name_suffix); - xf86OutputRename (output, name); + if (!xf86OutputRename (output, name)) + { + xf86OutputDestroy (output); + return; + } + /* Set the input timing to the screen. Assume always input 0. */ i830_sdvo_set_target_input(output, TRUE, FALSE); diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index a0f44df5..ceb8f2ef 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -127,6 +127,33 @@ xf86CrtcDestroy (xf86CrtcPtr crtc) extern XF86ConfigPtr xf86configptr; +typedef enum { + OPTION_PREFERRED_MODE, + OPTION_POSITION, + OPTION_BELOW, + OPTION_RIGHT_OF, + OPTION_ABOVE, + OPTION_LEFT_OF, + OPTION_ENABLE, + OPTION_DISABLE, + OPTION_MIN_CLOCK, + OPTION_MAX_CLOCK, +} OutputOpts; + +static OptionInfoRec xf86OutputOptions[] = { + {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, + {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, + {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, + {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, + {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, + {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, + {-1, NULL, OPTV_NONE, {0}, FALSE }, +}; + static void xf86OutputSetMonitor (xf86OutputPtr output) { @@ -134,6 +161,12 @@ xf86OutputSetMonitor (xf86OutputPtr output) static const char monitor_prefix[] = "monitor-"; char *monitor; + if (output->options) + xfree (output->options); + + output->options = xnfalloc (sizeof (xf86OutputOptions)); + memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); + option_name = xnfalloc (strlen (monitor_prefix) + strlen (output->name) + 1); strcpy (option_name, monitor_prefix); @@ -144,7 +177,24 @@ xf86OutputSetMonitor (xf86OutputPtr output) else xf86MarkOptionUsedByName (output->scrn->options, option_name); xfree (option_name); - output->conf_monitor = xf86findMonitor (monitor, xf86configptr->conf_monitor_lst); + output->conf_monitor = xf86findMonitor (monitor, + xf86configptr->conf_monitor_lst); + if (output->conf_monitor) + xf86ProcessOptions (output->scrn->scrnIndex, + output->conf_monitor->mon_option_lst, + output->options); +} + +static Bool +xf86OutputEnabled (xf86OutputPtr output) +{ + /* Check to see if this output was disabled in the config file */ + if (xf86ReturnOptValBool (output->options, OPTION_ENABLE, TRUE) == FALSE || + xf86ReturnOptValBool (output->options, OPTION_DISABLE, FALSE) == TRUE) + { + return FALSE; + } + return TRUE; } xf86OutputPtr @@ -167,6 +217,8 @@ xf86OutputCreate (ScrnInfoPtr scrn, #ifdef RANDR_12_INTERFACE output->randr_output = NULL; #endif + xf86OutputSetMonitor (output); + if (xf86_config->output) outputs = xrealloc (xf86_config->output, (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); @@ -181,24 +233,24 @@ xf86OutputCreate (ScrnInfoPtr scrn, xf86_config->output = outputs; xf86_config->output[xf86_config->num_output++] = output; - xf86OutputSetMonitor (output); return output; } -void +Bool xf86OutputRename (xf86OutputPtr output, const char *name) { int len = strlen(name); char *newname = xalloc (len + 1); if (!newname) - return; /* so sorry... */ + return FALSE; /* so sorry... */ strcpy (newname, name); if (output->name != (char *) (output + 1)) xfree (output->name); output->name = newname; xf86OutputSetMonitor (output); + return TRUE; } void @@ -375,7 +427,9 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, * If the two outputs desire the same mode, * see if they can be cloned */ - if (xf86ModesEqual (modes[o], modes[n])) + if (xf86ModesEqual (modes[o], modes[n]) && + config->output[o]->initial_x == config->output[n]->initial_x && + config->output[o]->initial_y == config->output[n]->initial_y) { for (l = 0; l < config->num_output; l++) if (output->possible_clones & (1 << l)) @@ -403,7 +457,8 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, /* * Compute the virtual size necessary to place all of the available - * crtcs in a panorama configuration + * crtcs in the specified configuration and also large enough to + * resize any crtc to the largest available mode */ static void @@ -418,7 +473,13 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) for (c = 0; c < config->num_crtc; c++) { int crtc_width = 0, crtc_height = 0; + xf86CrtcPtr crtc = config->crtc[c]; + if (crtc->enabled) + { + crtc_width = crtc->x + crtc->desiredMode.HDisplay; + crtc_height = crtc->y + crtc->desiredMode.VDisplay; + } for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; @@ -436,7 +497,8 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) } } } - width += crtc_width; + if (crtc_width > width) + width = crtc_width; if (crtc_height > height) height = crtc_height; } @@ -448,6 +510,186 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) *heightp = height; } +#define POSITION_UNSET -100000 + +static Bool +xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int o; + int min_x, min_y; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x = output->initial_y = POSITION_UNSET; + } + + /* + * Loop until all outputs are set + */ + for (;;) + { + Bool any_set = FALSE; + Bool keep_going = FALSE; + + for (o = 0; o < config->num_output; o++) + { + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + xf86OutputPtr output = config->output[o]; + xf86OutputPtr relative; + char *relative_name; + char *position; + OutputOpts relation; + int r; + + if (output->initial_x != POSITION_UNSET) + continue; + position = xf86GetOptValString (output->options, + OPTION_POSITION); + /* + * Absolute position wins + */ + if (position) + { + int x, y; + if (sscanf (position, "%d %d", &x, &y) == 2) + { + output->initial_x = x; + output->initial_y = y; + } + else + { + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + "Output %s position not of form \"x y\"\n", + output->name); + output->initial_x = output->initial_y = 0; + } + any_set = TRUE; + continue; + } + /* + * Next comes relative positions + */ + relation = 0; + relative_name = NULL; + for (r = 0; r < 4; r++) + { + relation = relations[r]; + relative_name = xf86GetOptValString (output->options, + relation); + if (relative_name) + break; + } + if (relative_name) + { + int or; + relative = NULL; + for (or = 0; or < config->num_output; or++) + { + xf86OutputPtr out_rel = config->output[or]; + XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; + char *name; + + if (rel_mon) + name = rel_mon->mon_identifier; + else + name = out_rel->name; + if (!strcmp (relative_name, name)) + { + relative = config->output[or]; + break; + } + } + if (!relative) + { + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + "Cannot position output %s relative to unknown output %s\n", + output->name, relative_name); + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + continue; + } + if (relative->initial_x == POSITION_UNSET) + { + keep_going = TRUE; + continue; + } + output->initial_x = relative->initial_x; + output->initial_y = relative->initial_y; + switch (relation) { + case OPTION_BELOW: + output->initial_y += modes[or]->VDisplay; + break; + case OPTION_RIGHT_OF: + output->initial_x += modes[or]->HDisplay; + break; + case OPTION_ABOVE: + output->initial_y -= modes[o]->VDisplay; + break; + case OPTION_LEFT_OF: + output->initial_x -= modes[o]->HDisplay; + break; + default: + break; + } + any_set = TRUE; + continue; + } + + /* Nothing set, just stick them at 0,0 */ + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + } + if (!keep_going) + break; + if (!any_set) + { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + if (output->initial_x == POSITION_UNSET) + { + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + "Output position loop. Moving %s to 0,0\n", + output->name); + output->initial_x = output->initial_y = 0; + break; + } + } + } + } + + /* + * normalize positions + */ + min_x = 1000000; + min_y = 1000000; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->initial_x < min_x) + min_x = output->initial_x; + if (output->initial_y < min_y) + min_y = output->initial_y; + } + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x -= min_x; + output->initial_y -= min_y; + } + return TRUE; +} + /* * XXX walk the monitor mode list and prune out duplicates that * are inserted by xf86DDCMonitorSet. In an ideal world, that @@ -536,13 +778,13 @@ i830xf86SortModes (DisplayModePtr input) #define DEBUG_REPROBE 1 void -xf86ProbeOutputModes (ScrnInfoPtr pScrn) +xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); int o; - int virtualX, virtualY; - xf86RandR12GetOriginalVirtualSize (pScrn, &virtualX, &virtualY); + if (maxX == 0 || maxY == 0) + xf86RandR12GetOriginalVirtualSize (pScrn, &maxX, &maxY); /* Elide duplicate modes before defaulting code uses them */ xf86PruneDuplicateMonitorModes (pScrn->monitor); @@ -553,11 +795,13 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) xf86OutputPtr output = config->output[o]; DisplayModePtr mode; DisplayModePtr config_modes = NULL, output_modes, default_modes; - XF86ConfMonitorPtr conf_monitor; + char *preferred_mode; xf86MonPtr edid_monitor; + XF86ConfMonitorPtr conf_monitor; MonRec mon_rec; int min_clock = 0; int max_clock = 0; + double clock; enum { sync_config, sync_edid, sync_default } sync_source = sync_default; while (output->probed_modes != NULL) @@ -632,6 +876,14 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) } } } + + if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, + OPTUNITS_KHZ, &clock)) + min_clock = (int) clock; + if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, + OPTUNITS_KHZ, &clock)) + max_clock = (int) clock; + /* * These limits will end up setting a 1024x768@60Hz mode by default, * which seems like a fairly good mode to use when nothing else is @@ -677,9 +929,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); /* - * Check all modes against virtual size + * Check all modes against max size */ - i830xf86ValidateModesSize (pScrn, output->probed_modes, virtualX, virtualY, 0); + if (maxX && maxY) + i830xf86ValidateModesSize (pScrn, output->probed_modes, + maxX, maxY, 0); /* * Check all modes against output @@ -693,27 +947,28 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) output->probed_modes = i830xf86SortModes (output->probed_modes); /* Check for a configured preference for a particular mode */ - if (conf_monitor) - { - char *preferred_mode = xf86findOptionValue (conf_monitor->mon_option_lst, - "Preferred Mode"); + preferred_mode = xf86GetOptValString (output->options, + OPTION_PREFERRED_MODE); - if (preferred_mode) + if (preferred_mode) + { + for (mode = output->probed_modes; mode; mode = mode->next) { - for (mode = output->probed_modes; mode; mode = mode->next) - if (!strcmp (preferred_mode, mode->name)) - break; - if (mode && mode != output->probed_modes) + if (!strcmp (preferred_mode, mode->name)) { - if (mode->prev) - mode->prev->next = mode->next; - if (mode->next) - mode->next->prev = mode->prev; - mode->next = output->probed_modes; - output->probed_modes->prev = mode; - mode->prev = NULL; - output->probed_modes = mode; + if (mode != output->probed_modes) + { + if (mode->prev) + mode->prev->next = mode->next; + if (mode->next) + mode->next->prev = mode->prev; + mode->next = output->probed_modes; + output->probed_modes->prev = mode; + mode->prev = NULL; + output->probed_modes = mode; + } mode->type |= M_T_PREFERRED; + break; } } } @@ -760,7 +1015,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn) xf86OutputPtr output; xf86CrtcPtr crtc; DisplayModePtr last, mode; - int originalVirtualX, originalVirtualY; output = config->output[config->compat_output]; if (!output->crtc) @@ -788,18 +1042,6 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn) /* Set pScrn->modes to the mode list for the 'compat' output */ pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes); - xf86RandR12GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); - - /* Disable modes in the XFree86 DDX list that are larger than the current - * virtual size. - */ - i830xf86ValidateModesSize(pScrn, pScrn->modes, - originalVirtualX, originalVirtualY, - pScrn->displayWidth); - - /* Strip out anything that we threw out for virtualX/Y. */ - i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE); - for (mode = pScrn->modes; mode; mode = mode->next) if (xf86ModesEqual (mode, &crtc->desiredMode)) break; @@ -835,35 +1077,33 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) DisplayModePtr target_mode = NULL; xf86CrtcPtr *crtcs; DisplayModePtr *modes; - int width, height; + Bool *enabled; + int width; + int height; - xf86ProbeOutputModes (pScrn); - - if (pScrn->display->virtualX == 0) - { - /* - * Expand virtual size to cover potential mode switches - */ - xf86DefaultScreenLimits (pScrn, &width, &height); - - pScrn->display->virtualX = width; - pScrn->display->virtualY = height; - } - else - { + if (pScrn->display->virtualX) width = pScrn->display->virtualX; + else + width = config->maxWidth; + if (pScrn->display->virtualY) height = pScrn->display->virtualY; - } - if (width > pScrn->virtualX) - pScrn->virtualX = width; - if (height > pScrn->virtualY) - pScrn->virtualY = height; - + else + height = config->maxHeight; + + xf86ProbeOutputModes (pScrn, width, height); + crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); + enabled = xnfcalloc (config->num_output, sizeof (Bool)); for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + modes[o] = NULL; + enabled[o] = (xf86OutputEnabled (output) && + output->status != XF86OutputStatusDisconnected); + } /* * Let outputs with preferred modes drive screen size @@ -872,7 +1112,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) { xf86OutputPtr output = config->output[o]; - if (output->status != XF86OutputStatusDisconnected && + if (enabled[o] && xf86OutputHasPreferredMode (output, width, height)) { target_mode = xf86DefaultMode (output, width, height); @@ -889,7 +1129,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; - if (output->status != XF86OutputStatusDisconnected) + if (enabled[o]) { target_mode = xf86DefaultMode (output, width, height); if (target_mode) @@ -905,10 +1145,23 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) { xf86OutputPtr output = config->output[o]; - if (output->status != XF86OutputStatusDisconnected && !modes[o]) + if (enabled[o] && !modes[o]) modes[o] = xf86ClosestMode (output, target_mode, width, height); } + /* + * Set the position of each output + */ + if (!xf86InitialOutputPositions (pScrn, modes)) + { + xfree (crtcs); + xfree (modes); + return FALSE; + } + + /* + * Assign CRTCs to fit output configuration + */ if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height)) { xfree (crtcs); @@ -928,7 +1181,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) crtc->enabled = FALSE; memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); } - + /* * Set initial configuration */ @@ -942,13 +1195,28 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) { crtc->desiredMode = *mode; crtc->enabled = TRUE; - crtc->x = 0; - crtc->y = 0; + crtc->x = output->initial_x; + crtc->y = output->initial_y; output->crtc = crtc; - /* XXX set position; for now, we clone */ } } + if (pScrn->display->virtualX == 0) + { + /* + * Expand virtual size to cover potential mode switches + */ + xf86DefaultScreenLimits (pScrn, &width, &height); + + pScrn->display->virtualX = width; + pScrn->display->virtualY = height; + } + + if (width > pScrn->virtualX) + pScrn->virtualX = width; + if (height > pScrn->virtualY) + pScrn->virtualY = height; + /* Mirror output modes to pScrn mode list */ xf86SetScrnInfoModes (pScrn); diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index b30003e7..2555c55d 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -288,6 +288,16 @@ struct _xf86Output { */ DisplayModePtr probed_modes; + /** + * Options parsed from the related monitor section + */ + OptionInfoPtr options; + + /** + * Configured monitor section + */ + XF86ConfMonitorPtr conf_monitor; + /** * Desired initial position */ @@ -313,12 +323,6 @@ struct _xf86Output { /** Output name */ char *name; - /** Configured monitor name */ - char *monitor_name; - - /** Monitor information from config file */ - XF86ConfMonitorPtr conf_monitor; - /** output-specific functions */ const xf86OutputFuncsRec *funcs; @@ -410,14 +414,14 @@ xf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, const char *name); -void +Bool xf86OutputRename (xf86OutputPtr output, const char *name); void xf86OutputDestroy (xf86OutputPtr output); void -xf86ProbeOutputModes (ScrnInfoPtr pScrn); +xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY); void xf86SetScrnInfoModes (ScrnInfoPtr pScrn); From 394124ceaadb46d976ad5c3bdeb1b77d351c57f6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 2 Jan 2007 16:57:33 -0800 Subject: [PATCH 37/37] Add per-CRTC gamma control support for RandR. This makes the CRTCs now always run in gamma-enabled mode, rather than having flaky logic for switching modes. Also, it should clear up issues with the LUTs being uninitialized when outputs are first brought up. --- src/i830.h | 4 +- src/i830_cursor.c | 8 +-- src/i830_display.c | 60 ++++++++++++++++++--- src/i830_display.h | 1 + src/i830_driver.c | 123 +++++++++++++++----------------------------- src/i830_randr.c | 12 ++++- src/i830_xf86Crtc.h | 5 ++ 7 files changed, 116 insertions(+), 97 deletions(-) diff --git a/src/i830.h b/src/i830.h index c2670cda..d5ca5d4b 100644 --- a/src/i830.h +++ b/src/i830.h @@ -194,7 +194,8 @@ extern const char *i830_output_type_names[]; typedef struct _I830CrtcPrivateRec { int pipe; - Bool gammaEnabled; + /* Lookup table values to be set when the CRTC is enabled */ + CARD8 lut_r[256], lut_g[256], lut_b[256]; } I830CrtcPrivateRec, *I830CrtcPrivatePtr; #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private) @@ -221,7 +222,6 @@ enum last_3d { typedef struct _I830PipeRec { Bool enabled; - Bool gammaEnabled; int x; int y; Bool cursorInRange; diff --git a/src/i830_cursor.c b/src/i830_cursor.c index cb1585fb..81cb3bd8 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -130,9 +130,7 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Bool force) temp = INREG(cursor_control); temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); if (pI830->CursorIsARGB) { - temp |= CURSOR_MODE_64_ARGB_AX; - if (intel_crtc->gammaEnabled) - temp |= MCURSOR_GAMMA_ENABLE; + temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; } else temp |= CURSOR_MODE_64_4C_AX; @@ -144,9 +142,7 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Bool force) temp &= ~(CURSOR_FORMAT_MASK); temp |= CURSOR_ENABLE; if (pI830->CursorIsARGB) { - temp |= CURSOR_FORMAT_ARGB; - if (intel_crtc->gammaEnabled) - temp |= CURSOR_GAMMA_ENABLE; + temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; } else temp |= CURSOR_FORMAT_3C; OUTREG(CURSOR_CONTROL, temp); diff --git a/src/i830_display.c b/src/i830_display.c index d124ba0a..f47a9dbf 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -536,6 +536,8 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) OUTREG(dspbase_reg, INREG(dspbase_reg)); } + i830_crtc_load_lut(crtc); + /* Give the overlay scaler a chance to enable if it's on this pipe */ i830_crtc_dpms_video(crtc, TRUE); break; @@ -718,10 +720,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, dpll |= PLL_REF_INPUT_DREFCLK; /* Set up the display plane register */ - dspcntr = 0; + dspcntr = DISPPLANE_GAMMA_ENABLE; switch (pScrn->bitsPerPixel) { case 8: - dspcntr |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE; + dspcntr |= DISPPLANE_8BPP; break; case 16: if (pScrn->depth == 15) @@ -736,10 +738,6 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, FatalError("unknown display bpp\n"); } - if (intel_crtc->gammaEnabled) { - dspcntr |= DISPPLANE_GAMMA_ENABLE; - } - if (pipe == 0) dspcntr |= DISPPLANE_SEL_PIPE_A; else @@ -840,6 +838,48 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, i830WaitForVblank(pScrn); } + +/** Loads the palette/gamma unit for the CRTC with the prepared values */ +void +i830_crtc_load_lut(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B; + int i; + + /* The clocks have to be on to load the palette. */ + if (!crtc->enabled) + return; + + for (i = 0; i < 256; i++) { + OUTREG(palreg + 4 * i, + (intel_crtc->lut_r[i] << 16) | + (intel_crtc->lut_g[i] << 8) | + intel_crtc->lut_b[i]); + } +} + +/** Sets the color ramps on behalf of RandR */ +static void +i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, + int size) +{ + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int i; + + assert(size == 256); + + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = red[i] >> 8; + intel_crtc->lut_g[i] = green[i] >> 8; + intel_crtc->lut_b[i] = blue[i] >> 8; + } + + i830_crtc_load_lut(crtc); +} + /** * Sets the given video mode on the given pipe. * @@ -1147,6 +1187,7 @@ static const xf86CrtcFuncsRec i830_crtc_funcs = { .restore = NULL, /* XXX */ .mode_fixup = i830_crtc_mode_fixup, .mode_set = i830_crtc_mode_set, + .gamma_set = i830_crtc_gamma_set, .destroy = NULL, /* XXX */ }; @@ -1155,6 +1196,7 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pipe) { xf86CrtcPtr crtc; I830CrtcPrivatePtr intel_crtc; + int i; crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs); if (crtc == NULL) @@ -1163,6 +1205,12 @@ i830_crtc_init(ScrnInfoPtr pScrn, int pipe) intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1); intel_crtc->pipe = pipe; + /* Initialize the LUTs for when we turn on the CRTC. */ + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = i; + intel_crtc->lut_g[i] = i; + intel_crtc->lut_b[i] = i; + } crtc->driver_private = intel_crtc; } diff --git a/src/i830_display.h b/src/i830_display.h index 5517d27c..66ab17e8 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -42,3 +42,4 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output); void i830ReleaseLoadDetectPipe(xf86OutputPtr output); Bool i830PipeInUse(xf86CrtcPtr crtc); void i830_crtc_init(ScrnInfoPtr pScrn, int pipe); +void i830_crtc_load_lut(xf86CrtcPtr crtc); diff --git a/src/i830_driver.c b/src/i830_driver.c index 694c96f3..94cba05d 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -579,106 +579,67 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, VisualPtr pVisual) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - I830Ptr pI830; int i,j, index; - unsigned char r, g, b; - CARD32 val, temp; - int palreg; - int dspreg, dspbase, dspsurf; int p; + CARD16 lut_r[256], lut_g[256], lut_b[256]; DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); - pI830 = I830PTR(pScrn); - for(p=0; p < xf86_config->num_crtc; p++) - { + for(p = 0; p < xf86_config->num_crtc; p++) { xf86CrtcPtr crtc = xf86_config->crtc[p]; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - if (p == 0) { - palreg = PALETTE_A; - dspreg = DSPACNTR; - dspbase = DSPABASE; - dspsurf = DSPASURF; - } else { - palreg = PALETTE_B; - dspreg = DSPBCNTR; - dspbase = DSPBBASE; - dspsurf = DSPBSURF; + /* Initialize to the old lookup table values. */ + for (i = 0; i < 256; i++) { + lut_r[i] = intel_crtc->lut_r[i] << 8; + lut_g[i] = intel_crtc->lut_g[i] << 8; + lut_b[i] = intel_crtc->lut_b[i] << 8; } - if (crtc->enabled == 0) - continue; - - intel_crtc->gammaEnabled = 1; - - /* To ensure gamma is enabled we need to turn off and on the plane */ - temp = INREG(dspreg); - OUTREG(dspreg, temp & ~(1<<31)); - OUTREG(dspbase, INREG(dspbase)); - OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE); - OUTREG(dspbase, INREG(dspbase)); - if (IS_I965G(pI830)) - OUTREG(dspsurf, INREG(dspsurf)); - - /* It seems that an initial read is needed. */ - temp = INREG(palreg); - switch(pScrn->depth) { case 15: - for (i = 0; i < numColors; i++) { - index = indices[i]; - r = colors[index].red; - g = colors[index].green; - b = colors[index].blue; - val = (r << 16) | (g << 8) | b; - for (j = 0; j < 8; j++) { - OUTREG(palreg + index * 32 + (j * 4), val); + for (i = 0; i < numColors; i++) { + index = indices[i]; + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_g[index * 8 + j] = colors[index].green << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } } - } - break; + break; case 16: - for (i = 0; i < numColors; i++) { - index = indices[i]; - r = colors[index / 2].red; - g = colors[index].green; - b = colors[index / 2].blue; + for (i = 0; i < numColors; i++) { + index = indices[i]; - val = (r << 16) | (g << 8) | b; - OUTREG(palreg + index * 16, val); - OUTREG(palreg + index * 16 + 4, val); - OUTREG(palreg + index * 16 + 8, val); - OUTREG(palreg + index * 16 + 12, val); + if (i <= 31) { + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } - if (index <= 31) { - r = colors[index].red; - g = colors[(index * 2) + 1].green; - b = colors[index].blue; - - val = (r << 16) | (g << 8) | b; - OUTREG(palreg + index * 32, val); - OUTREG(palreg + index * 32 + 4, val); - OUTREG(palreg + index * 32 + 8, val); - OUTREG(palreg + index * 32 + 12, val); - } - } + for (j = 0; j < 4; j++) { + lut_g[index * 4 + j] = colors[index].green << 8; + } + } break; default: - for(i = 0; i < numColors; i++) { - index = indices[i]; - r = colors[index].red; - g = colors[index].green; - b = colors[index].blue; - val = (r << 16) | (g << 8) | b; - OUTREG(palreg + index * 4, val); - } - break; - } + for (i = 0; i < numColors; i++) { + index = indices[i]; + lut_r[index] = colors[index].red << 8; + lut_g[index] = colors[index].green << 8; + lut_b[index] = colors[index].blue << 8; + } + break; + } + + /* Make the change through RandR */ +#ifdef RANDR_12_INTERFACE + RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); +#else + crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); +#endif } - - /* Enable gamma for Cursor if ARGB */ - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) - pI830->CursorInfoRec->ShowCursor(pScrn); } int diff --git a/src/i830_randr.c b/src/i830_randr.c index 83cf0238..533322b2 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -663,9 +663,17 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, static Bool xf86RandR12CrtcSetGamma (ScreenPtr pScreen, - RRCrtcPtr crtc) + RRCrtcPtr randr_crtc) { - return FALSE; + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (crtc->funcs->gamma_set == NULL) + return FALSE; + + crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen, + randr_crtc->gammaBlue, randr_crtc->gammaSize); + + return TRUE; } /** diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 2555c55d..8fea162e 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -89,6 +89,11 @@ typedef struct _xf86CrtcFuncs { DisplayModePtr mode, DisplayModePtr adjusted_mode); + /* Set the color ramps for the CRTC to the given values. */ + void + (*gamma_set)(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, + int size); + /** * Clean up driver-specific bits of the crtc */