diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/atipreinit.c | 4 | ||||
-rw-r--r-- | src/atiprobe.c | 13 | ||||
-rw-r--r-- | src/ativga.c | 9 | ||||
-rw-r--r-- | src/r128_accel.c | 8 | ||||
-rw-r--r-- | src/r128_dri.c | 1 | ||||
-rw-r--r-- | src/r128_driver.c | 6 | ||||
-rw-r--r-- | src/r128_video.c | 6 | ||||
-rw-r--r-- | src/radeon.h | 1 | ||||
-rw-r--r-- | src/radeon_bios.c | 75 | ||||
-rw-r--r-- | src/radeon_driver.c | 92 | ||||
-rw-r--r-- | src/radeon_reg.h | 2 | ||||
-rw-r--r-- | src/radeon_render.c | 103 |
12 files changed, 272 insertions, 48 deletions
diff --git a/src/atipreinit.c b/src/atipreinit.c index ebe54ad..df11246 100644 --- a/src/atipreinit.c +++ b/src/atipreinit.c @@ -1918,11 +1918,11 @@ ATIPreInit VBlankEnd += 0x0100U; pATI->LCDHBlankWidth = HBlankEnd - HBlankStart; - pATI->LCDHSyncStart = HSyncStart - HBlankStart - 1; + pATI->LCDHSyncStart = HSyncStart - HBlankStart; pATI->LCDHSyncWidth = HSyncEnd - HSyncStart; pATI->LCDVBlankWidth = VBlankEnd - VBlankStart; - pATI->LCDVSyncStart = VSyncStart - VBlankStart - 1; + pATI->LCDVSyncStart = VSyncStart - VBlankStart; pATI->LCDVSyncWidth = VSyncEnd - VSyncStart; HDisplay = HTotal + 5 - pATI->LCDHBlankWidth; diff --git a/src/atiprobe.c b/src/atiprobe.c index 08cc56f..c7dff49 100644 --- a/src/atiprobe.c +++ b/src/atiprobe.c @@ -1243,6 +1243,10 @@ ATIProbe xf86MsgVerb(X_INFO, 2, ATI_NAME ": Unshared VGA not probed.\n"); } + /* + * Mach8/32 probing doesn't work well on some legacy free ia64 + * However if we use AVOID_CPIO we don't get here at all. + */ if (ATICheckSparseIOBases(NULL, ProbeFlags, 0x02E8U, 8, fChipsets[ATI_CHIPSET_IBM8514] || fChipsets[ATI_CHIPSET_MACH8] || @@ -1275,6 +1279,10 @@ ATIProbe ATI_NAME ": Unshared 8514/A not probed.\n"); } + /* + * Also NONPCI Mach64 probing is evil on legacy free platforms. + * However if we use AVOID_CPIO we don't get here at all. + */ for (i = 0; i < NumberOf(Mach64SparseIOBases); i++) { if (ATICheckSparseIOBases(NULL, ProbeFlags, Mach64SparseIOBases[i], @@ -1309,7 +1317,6 @@ ATIProbe ATIClaimSparseIOBases(ProbeFlags, Mach64SparseIOBases[i], 4, DetectedMach64); } - #endif /* AVOID_NON_PCI */ } @@ -1539,7 +1546,6 @@ ATIProbe ATIFindVGA(pVideo, &pVGA, &pATI, p8514, ProbeFlags); } - xf86SetPciVideo(NULL, NONE); break; } @@ -1554,6 +1560,9 @@ ATIProbe continue; pPCI = pVideo->thisCard; + if (pPCI == NULL) + continue; + PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG); j = PciReg & 0x03U; if (j == 0x03U) diff --git a/src/ativga.c b/src/ativga.c index 2ac97cd..7ecc700 100644 --- a/src/ativga.c +++ b/src/ativga.c @@ -185,7 +185,11 @@ ATIVGACalculate (pATI->Chip >= ATI_CHIP_264CT)) pMode->CrtcHBlankStart--; pMode->CrtcHSyncStart = pMode->HSyncStart >> 3; + if (pATI->LCDPanelID >= 0) + pMode->CrtcHSyncStart--; pMode->CrtcHSyncEnd = pMode->HSyncEnd >> 3; + if (pATI->LCDPanelID >= 0) + pMode->CrtcHSyncEnd--; pMode->CrtcHBlankEnd = (pMode->HTotal >> 3) - 1; pMode->CrtcHTotal = (pMode->HTotal >> 3) - 5; pMode->CrtcHSkew = pMode->HSkew; @@ -327,6 +331,11 @@ ATIVGACalculate pMode->CrtcVBlankStart++; else pMode->CrtcVBlankStart--; + if (pATI->LCDPanelID >= 0) + { + pMode->CrtcVSyncStart--; + pMode->CrtcVSyncEnd--; + } pMode->CrtcVBlankEnd--; if (pATI->Chip < ATI_CHIP_264CT) pMode->CrtcVBlankEnd--; diff --git a/src/r128_accel.c b/src/r128_accel.c index 90c5cb5..ded73d5 100644 --- a/src/r128_accel.c +++ b/src/r128_accel.c @@ -237,17 +237,23 @@ void R128CCEWaitForIdle(ScrnInfoPtr pScrn) i = 0; do { ret = drmCommandNone(info->drmFD, DRM_R128_CCE_IDLE); - } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY ); + } while ( ret && errno == EBUSY && i++ < (R128_IDLE_RETRY * R128_IDLE_RETRY) ); if (ret && ret != -EBUSY) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: CCE idle %d\n", __FUNCTION__, ret); } + if (i > R128_IDLE_RETRY) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s: (DEBUG) CCE idle took i = %d\n", __FUNCTION__, i); + } + if (ret == 0) return; xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n"); + R128CCE_STOP(pScrn, info); R128EngineReset(pScrn); /* Always restart the engine when doing CCE 2D acceleration */ diff --git a/src/r128_dri.c b/src/r128_dri.c index 2b35c33..65bb5b9 100644 --- a/src/r128_dri.c +++ b/src/r128_dri.c @@ -1297,6 +1297,7 @@ void R128DRICloseScreen(ScreenPtr pScreen) if (info->irq) { drmCtlUninstHandler(info->drmFD); info->irq = 0; + info->gen_int_cntl = 0; } /* De-allocate vertex buffers */ diff --git a/src/r128_driver.c b/src/r128_driver.c index 8167d00..c5dec60 100644 --- a/src/r128_driver.c +++ b/src/r128_driver.c @@ -1640,7 +1640,11 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn) NULL, /* linePitches */ 8 * 64, /* minPitch */ 8 * 1024, /* maxPitch */ - 8 * 64, /* pitchInc */ +/* + * ATI docs say pitchInc must be 8 * 64, but this doesn't permit a pitch of + * 800 bytes, which is known to work on the Rage128 LF on clamshell iBooks + */ + 8 * 32, /* pitchInc */ 128, /* minHeight */ 2048, /* maxHeight */ pScrn->display->virtualX, diff --git a/src/r128_video.c b/src/r128_video.c index 7ef31af..04d85e0 100644 --- a/src/r128_video.c +++ b/src/r128_video.c @@ -579,20 +579,20 @@ R128AllocateMemory( pScreen = screenInfo.screens[pScrn->scrnIndex]; - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); if(!new_linear) { int max_size; - xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME); if(max_size < size) return NULL; xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); } diff --git a/src/radeon.h b/src/radeon.h index 523d2b7..636923a 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -555,6 +555,7 @@ typedef struct { Bool RenderAccel; Bool RenderInited3D; FBLinearPtr RenderTex; + Bool RenderTexValidR100; void (*RenderCallback)(ScrnInfoPtr); Time RenderTimeout; diff --git a/src/radeon_bios.c b/src/radeon_bios.c index d54c9b9..37a3e26 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -198,13 +198,28 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) return FALSE; } } else { + /* Some laptops only have one connector (VGA) listed in the connector table, + * we need to add LVDS in as a non-DDC display. + * Note, we can't assume the listed VGA will be filled in PortInfo[0], + * when walking through connector table. connector_found has following meaning: + * 0 -- nothing found, + * 1 -- only PortInfo[0] filled, + * 2 -- only PortInfo[1] filled, + * 3 -- both are filled. + */ + int connector_found = 0; + if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x50))) { for (i = 1; i < 4; i++) { if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; /* end of table */ tmp0 = RADEON_BIOS16(tmp + i*2); - if (((tmp0 >> 12) & 0x1f) == 0) continue; /* no connector */ + if (((tmp0 >> 12) & 0x0f) == 0) continue; /* no connector */ + if (connector_found > 0) { + if (pRADEONEnt->PortInfo[tmp1].DDCType == ((tmp0 >> 8) & 0x0f)) + continue; /* same connector */ + } /* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */ tmp1 = ((((tmp0 >> 8) & 0xf) == DDC_DVI) || (tmp1 == 1)) ? 0 : 1; /* determine port info index */ @@ -222,9 +237,7 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) pRADEONEnt->PortInfo[tmp1].TMDSType == TMDS_INT) pRADEONEnt->PortInfo[tmp1].TMDSType = TMDS_UNKNOWN; - xf86DrvMsg(0, X_INFO, "Connector%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", - tmp1, pRADEONEnt->PortInfo[tmp1].DDCType, pRADEONEnt->PortInfo[tmp1].DACType, - pRADEONEnt->PortInfo[tmp1].TMDSType, pRADEONEnt->PortInfo[tmp1].ConnectorType); + connector_found += (tmp1 + 1); } } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); @@ -232,14 +245,54 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) } if (info->IsMobility) { - if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42))) { - if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) { - if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) { - pRADEONEnt->PortInfo[0].DDCType = tmp1; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); - } + /* For the cases where only one VGA connector is found, + we assume LVDS is not listed in the connector table, + add it in here as the first port. + */ + if ((connector_found < 3) && (pRADEONEnt->PortInfo[tmp1].ConnectorType == CONNECTOR_CRT)) { + if (connector_found == 1) { + memcpy (&pRADEONEnt->PortInfo[1], &pRADEONEnt->PortInfo[0], + sizeof (pRADEONEnt->PortInfo[0])); + } + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_PROPRIETARY; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS port is not in connector table, added in.\n"); + if (connector_found == 0) connector_found = 1; + else connector_found = 3; } - } + + if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42))) { + if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) { + if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) { + pRADEONEnt->PortInfo[0].DDCType = tmp1; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); + } + } + } + } else if (connector_found == 2) { + memcpy (&pRADEONEnt->PortInfo[0], &pRADEONEnt->PortInfo[1], + sizeof (pRADEONEnt->PortInfo[0])); + pRADEONEnt->PortInfo[1].DACType = DAC_UNKNOWN; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[1].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_NONE; + connector_found = 1; + } + + if (connector_found == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No connector found in Connector Info Table.\n"); + } else { + xf86DrvMsg(0, X_INFO, "Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + pRADEONEnt->PortInfo[0].DDCType, pRADEONEnt->PortInfo[0].DACType, + pRADEONEnt->PortInfo[0].TMDSType, pRADEONEnt->PortInfo[0].ConnectorType); + } + if (connector_found == 3) { + xf86DrvMsg(0, X_INFO, "Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + pRADEONEnt->PortInfo[1].DDCType, pRADEONEnt->PortInfo[1].DACType, + pRADEONEnt->PortInfo[1].TMDSType, pRADEONEnt->PortInfo[1].ConnectorType); } #if 0 diff --git a/src/radeon_driver.c b/src/radeon_driver.c index cc90627..b9a6a3a 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -365,6 +365,7 @@ static const char *int10Symbols[] = { "xf86InitInt10", "xf86FreeInt10", "xf86int10Addr", + "xf86ExecX86int10", NULL }; @@ -1311,7 +1312,7 @@ static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; } if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { - info->PanelXRes = ((fp_vert_stretch>>16) + 1) * 8; + info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; } else { info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; } @@ -1712,6 +1713,13 @@ static BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn) break; } } + for (i = 0; i < max_mt; i++) { + if (strcmp(s2, MonTypeName[i]) == 0) { + pRADEONEnt->PortInfo[1].MonType = MonTypeID[i]; + break; + } + } + if (i == max_mt) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid Monitor type specified for 2nd port \n"); @@ -1744,32 +1752,45 @@ static BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn) } - if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { - - if(((!info->HasCRTC2) || info->IsDellServer) && - (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN)) { + if(((!info->HasCRTC2) || info->IsDellServer)) { + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->PortInfo[0]))); else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->PortInfo[0]))); else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->PortInfo[0]))); else pRADEONEnt->PortInfo[0].MonType = MT_CRT; + } - if (!ignore_edid) { - if (pRADEONEnt->PortInfo[0].MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); - xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); - } + if (!ignore_edid) { + if (pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); + xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); } - - pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; - pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - info->MergeType = MT_NONE; - return TRUE; } + pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; + pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo2 = NULL; + info->MergeType = MT_NONE; + info->DisplayType = pRADEONEnt->MonType1; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: + ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], + DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], + TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], + DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); + + return TRUE; + } + + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { + /* Primary Head (DVI or Laptop Int. panel)*/ /* A ddc capable display connected on DVI port */ if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { @@ -2583,8 +2604,10 @@ static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) if (ddc->det_mon[j].type == 0) { struct detailed_timings *d_timings = &ddc->det_mon[j].section.d_timings; - if (info->PanelXRes < d_timings->h_active && - info->PanelYRes < d_timings->v_active) { + if (info->PanelXRes <= d_timings->h_active && + info->PanelYRes <= d_timings->v_active) { + + if (info->DotClock) continue; /* Timings already inited */ info->PanelXRes = d_timings->h_active; info->PanelYRes = d_timings->v_active; @@ -3157,8 +3180,9 @@ static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) new->next = NULL; new->prev = last; - last->next = new; + if (last) last->next = new; last = new; + if (!first) first = new; } } } @@ -4471,10 +4495,12 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) RADEONSave(pScrn); - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - RADEONSetDynamicClock(pScrn, 1); - } else { - RADEONSetDynamicClock(pScrn, 0); + if ((!info->IsSecondary) && info->IsMobility) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + RADEONSetDynamicClock(pScrn, 1); + } else { + RADEONSetDynamicClock(pScrn, 0); + } } if (info->FBDev) { @@ -7133,6 +7159,7 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) RADEONDoAdjustFrame(pScrn, x, y, FALSE); } + RADEONSetFBLocation (pScrn); #ifdef XF86DRI if (info->CPStarted) DRIUnlock(pScrn->pScreen); #endif @@ -7145,9 +7172,22 @@ Bool RADEONEnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; RADEONTRACE(("RADEONEnterVT\n")); + if (INREG(RADEON_CONFIG_MEMSIZE) == 0) { /* Softboot V_BIOS */ + xf86Int10InfoPtr pInt; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "zero MEMSIZE, probably at D3cold. Re-POSTing via int10.\n"); + pInt = xf86InitInt10 (info->pEnt->index); + if (pInt) { + pInt->num = 0xe6; + xf86ExecX86int10 (pInt); + xf86FreeInt10 (pInt); + } + } + if (info->FBDev) { unsigned char *RADEONMMIO = info->MMIO; if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; @@ -7158,6 +7198,8 @@ Bool RADEONEnterVT(int scrnIndex, int flags) } else if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + RADEONSetFBLocation (pScrn); + #ifdef XF86DRI if (info->directRenderingEnabled) { /* get the Radeon back into shape after resume */ diff --git a/src/radeon_reg.h b/src/radeon_reg.h index 8849cab..b56630c 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -803,7 +803,7 @@ # define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1<<12) # define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1<<13) # define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) -# define RADEON_IO_MCLK_DYN_ENABLE (1 << 14) +# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) #define RADEON_MDGPIO_A_REG 0x01ac #define RADEON_MDGPIO_EN_REG 0x01b0 #define RADEON_MDGPIO_MASK 0x0198 diff --git a/src/radeon_render.c b/src/radeon_render.c index 145b653..9a218a3 100644 --- a/src/radeon_render.c +++ b/src/radeon_render.c @@ -7,6 +7,11 @@ #ifndef RENDER_GENERIC_HELPER #define RENDER_GENERIC_HELPER +/* R100 code path constants */ +/* Minimum working values for RV200: 65x8 - your mileage may vary */ +#define MAGIC_R100_MIN_TEX_WIDTH (65) +#define MAGIC_R100_MIN_TEX_HEIGHT (8) + static void RadeonInit3DEngineMMIO(ScrnInfoPtr pScrn); #ifdef XF86DRI static void RadeonInit3DEngineCP(ScrnInfoPtr pScrn); @@ -421,6 +426,8 @@ static Bool FUNC_NAME(R100SetupTexture)( CARD8 *dst; CARD32 tex_size = 0, txformat; int dst_pitch, offset, size, i, tex_bytepp; + int offscreensize = (pScrn->bitsPerPixel >> 3) * + pScrn->displayWidth * MAGIC_R100_MIN_TEX_HEIGHT; ACCEL_PREAMBLE(); if ((width > 2048) || (height > 2048)) @@ -440,7 +447,8 @@ static Bool FUNC_NAME(R100SetupTexture)( dst_pitch = (width * tex_bytepp + 31) & ~31; size = dst_pitch * height; - if (!AllocateLinear(pScrn, size)) + /* Allocate off-screen space for texture pre-rendering as well */ + if (!AllocateLinear(pScrn, size + offscreensize)) return FALSE; if (flags & XAA_RENDER_REPEAT) { @@ -451,7 +459,7 @@ static Bool FUNC_NAME(R100SetupTexture)( txformat |= RADEON_TXFORMAT_NON_POWER2; } - offset = info->RenderTex->offset * pScrn->bitsPerPixel / 8; + offset = info->RenderTex->offset * pScrn->bitsPerPixel / 8 + offscreensize; /* Upload texture to card. Should use ImageWrite to avoid syncing. */ i = height; @@ -481,6 +489,7 @@ static Bool FUNC_NAME(R100SetupTexture)( RADEON_CLAMP_S_WRAP | RADEON_CLAMP_T_WRAP); FINISH_ACCEL(); + info->RenderTexValidR100 = FALSE; return TRUE; } @@ -608,6 +617,95 @@ FUNC_NAME(R100SubsequentCPUToScreenTexture) ( ACCEL_PREAMBLE(); + /* R100 chips seem to have cache problems and do not reload small textures + * from memory for small render areas. Thus we have to render a + * 'sufficiently large' portion of the texture (may contain uninitialized + * data as well) to off-screen memory to invalidate the cache. */ + if (!info->RenderTexValidR100 && + width*height < MAGIC_R100_MIN_TEX_WIDTH*MAGIC_R100_MIN_TEX_HEIGHT) +/* (width<MAGIC_R100_MIN_TEX_WIDTH || height<MAGIC_R100_MIN_TEX_HEIGHT))*/ + { + fboffset = info->fbLocation + pScrn->fbOffset + + info->RenderTex->offset * (pScrn->bitsPerPixel >> 3); + l = 0.0; + t = 0.0; + r = MAGIC_R100_MIN_TEX_WIDTH; + b = MAGIC_R100_MIN_TEX_HEIGHT; + +#ifdef ACCEL_CP + BEGIN_RING(23); + + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset); + + OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD, 17)); + /* RADEON_SE_VTX_FMT */ + OUT_RING(RADEON_CP_VC_FRMT_XY | + RADEON_CP_VC_FRMT_ST0); + /* SE_VF_CNTL */ + OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | + RADEON_CP_VC_CNTL_PRIM_WALK_RING | + RADEON_CP_VC_CNTL_MAOS_ENABLE | + RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | + (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + + OUT_RING(F_TO_DW(l)); + OUT_RING(F_TO_DW(t)); + OUT_RING(F_TO_DW(l)); + OUT_RING(F_TO_DW(t)); + + OUT_RING(F_TO_DW(r)); + OUT_RING(F_TO_DW(t)); + OUT_RING(F_TO_DW(r)); + OUT_RING(F_TO_DW(t)); + + OUT_RING(F_TO_DW(r)); + OUT_RING(F_TO_DW(b)); + OUT_RING(F_TO_DW(r)); + OUT_RING(F_TO_DW(b)); + + OUT_RING(F_TO_DW(l)); + OUT_RING(F_TO_DW(b)); + OUT_RING(F_TO_DW(l)); + OUT_RING(F_TO_DW(b)); + + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); + + ADVANCE_RING(); +#else + BEGIN_ACCEL(19); + + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset); + + OUT_ACCEL_REG(RADEON_SE_VF_CNTL, RADEON_VF_PRIM_TYPE_TRIANGLE_FAN | + RADEON_VF_PRIM_WALK_DATA | + RADEON_VF_RADEON_MODE | + (4 << RADEON_VF_NUM_VERTICES_SHIFT)); + + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t)); + + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t)); + + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b)); + + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l)); + OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b)); + + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); + FINISH_ACCEL(); +#endif + } + /* Note: we can't simply set up the 3D surface at the same location as the * front buffer, because the 2048x2048 limit on coordinates may be smaller * than the (MergedFB) screen. @@ -696,6 +794,7 @@ FUNC_NAME(R100SubsequentCPUToScreenTexture) ( OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); FINISH_ACCEL(); #endif + info->RenderTexValidR100 = TRUE; } |