diff options
author | Keith Packard <keithp@guitar.keithp.com> | 2006-09-20 22:38:55 -0700 |
---|---|---|
committer | Keith Packard <keithp@guitar.keithp.com> | 2006-09-20 22:38:55 -0700 |
commit | f6500e94fec0d6db8c1f1350bee1d137bf06a09e (patch) | |
tree | a26330810dec0fe897bf09dd28ed0b1f8fa2e291 /src | |
parent | cbaf3cf74bd420533d299c4113761ec536097e33 (diff) |
Update driver for RandR 1.2 X server API.
This is not entirely what I'd like to see, but it's at least functional.
Limitations:
Can't disable/enable crtcs
Can't move outputs on/off crtcs
But, it does handle monitor hot-plug, detecting changes in VGA and SDVO
status on-the fly. Which makes for good demo material.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/i830.h | 22 | ||||
-rw-r--r-- | src/i830_cursor.c | 371 | ||||
-rw-r--r-- | src/i830_display.c | 8 | ||||
-rw-r--r-- | src/i830_display.h | 1 | ||||
-rw-r--r-- | src/i830_driver.c | 25 | ||||
-rw-r--r-- | src/i830_modes.c | 5 | ||||
-rw-r--r-- | src/i830_randr.c | 450 |
8 files changed, 686 insertions, 198 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 50d0ad1a..03b5fe67 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ SUBDIRS = xvmc bios_reader ch7xxx sil164 # -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@ -DI830_XV +AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV i810_drv_la_LTLIBRARIES = i810_drv.la i810_drv_la_LDFLAGS = -module -avoid-version @@ -79,6 +79,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>. */ +#define PIPE_CRT_ID 0 +#define PIPE_TV_ID 1 +#define PIPE_DFP_ID 2 +#define PIPE_LFP_ID 3 +#define PIPE_CRT2_ID 4 +#define PIPE_TV2_ID 5 +#define PIPE_DFP2_ID 6 +#define PIPE_LFP2_ID 7 +#define PIPE_NUM_ID 8 + #define PIPE_NONE 0<<0 #define PIPE_CRT 1<<0 #define PIPE_TV 1<<1 @@ -201,10 +211,12 @@ typedef struct _I830SDVODriver { CARD32 save_SDVOX; } I830SDVORec, *I830SDVOPtr; +extern const char *i830_output_type_names[]; + struct _I830OutputRec { int type; - int pipe; - int flags; +/* int pipe; + int flags;*/ xf86MonPtr MonInfo; I2CBusPtr pI2CBus; I2CBusPtr pDDCBus; @@ -233,6 +245,10 @@ typedef struct _I830Rec { Bool gammaEnabled[MAX_DISPLAY_PIPES]; + int pipeX[MAX_DISPLAY_PIPES]; + int pipeY[MAX_DISPLAY_PIPES]; + Bool cursorInRange[MAX_DISPLAY_PIPES]; + Bool cursorShown[MAX_DISPLAY_PIPES]; Bool Clone; int CloneRefresh; int CloneHDisplay; @@ -518,6 +534,7 @@ extern void I830SetMMIOAccess(I830Ptr pI830); extern void I830PrintErrorState(ScrnInfoPtr pScrn); extern void I830Sync(ScrnInfoPtr pScrn); extern void I830InitHWCursor(ScrnInfoPtr pScrn); +extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe); extern Bool I830CursorInit(ScreenPtr pScreen); extern void I830EmitInvarientState(ScrnInfoPtr pScrn); extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer); @@ -610,6 +627,7 @@ DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq, int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time); /* i830_randr.c */ +Bool I830RandRCreateScreenResources (ScreenPtr pScreen); Bool I830RandRInit(ScreenPtr pScreen, int rotation); Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate, RRScreenSizePtr pSize); diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 2cb069cc..1e7beef2 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -80,12 +80,106 @@ static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs); #endif void +I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + Bool show; + + if (!pI830->planeEnabled[pipe]) + return; + + show = pI830->cursorOn && pI830->cursorInRange[pipe]; + if (show && !pI830->cursorShown[pipe]) + { + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { + int cursor_control, cursor_base; + if (pipe == 0) + { + cursor_control = CURSOR_A_CONTROL; + cursor_base = CURSOR_A_BASE; + } + else + { + cursor_control = CURSOR_B_CONTROL; + cursor_base = CURSOR_B_BASE; + } + temp = INREG(cursor_control); + temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); + if (pI830->CursorIsARGB) { + temp |= CURSOR_MODE_64_ARGB_AX; + if (pI830->gammaEnabled[pipe]) + temp |= MCURSOR_GAMMA_ENABLE; + } else + temp |= CURSOR_MODE_64_4C_AX; + + temp |= (pipe << 28); /* Connect to correct pipe */ + /* Need to set mode, then address. */ + OUTREG(cursor_control, temp); + if (pI830->CursorIsARGB) + OUTREG(cursor_base, pI830->CursorMemARGB->Physical); + else + OUTREG(cursor_base, pI830->CursorMem->Physical); + } else { + temp = INREG(CURSOR_CONTROL); + temp &= ~(CURSOR_FORMAT_MASK); + temp |= CURSOR_ENABLE; + if (pI830->CursorIsARGB) { + temp |= CURSOR_FORMAT_ARGB; + if (pI830->gammaEnabled[pipe]) + temp |= CURSOR_GAMMA_ENABLE; + } else + temp |= CURSOR_FORMAT_3C; + OUTREG(CURSOR_CONTROL, temp); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start); + } + pI830->cursorShown[pipe] = TRUE; + } + else if (!show && pI830->cursorShown[pipe]) + { + if (IS_MOBILE(pI830) || IS_I9XX(pI830)) + { + int cursor_control, cursor_base; + if (pipe == 0) + { + cursor_control = CURSOR_A_CONTROL; + cursor_base = CURSOR_A_BASE; + } + else + { + cursor_control = CURSOR_B_CONTROL; + cursor_base = CURSOR_B_BASE; + } + temp = INREG(cursor_control); + temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE); + temp |= CURSOR_MODE_DISABLE; + OUTREG(cursor_control, temp); + /* This is needed to flush the above change. */ + if (pI830->CursorIsARGB) + OUTREG(cursor_base, pI830->CursorMemARGB->Physical); + else + OUTREG(cursor_base, pI830->CursorMem->Physical); + } else { + temp = INREG(CURSOR_CONTROL); + temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); + OUTREG(CURSOR_CONTROL, temp); + } + pI830->cursorShown[pipe] = FALSE; + } +} + +void I830InitHWCursor(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; + int i; DPRINTF(PFX, "I830InitHWCursor\n"); + for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE; /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { temp = INREG(CURSOR_A_CONTROL); @@ -356,121 +450,109 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { - I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp = 0; - Bool hide = FALSE, show = FALSE; - int oldx = x, oldy = y; - int hotspotx = 0, hotspoty = 0; -#if 0 - static Bool outsideViewport = FALSE; -#endif - - oldx += pScrn->frameX0; /* undo what xf86HWCurs did */ - oldy += pScrn->frameY0; - - switch (pI830->rotation) { - case RR_Rotate_0: - x = oldx; - y = oldy; - break; - case RR_Rotate_90: - x = oldy; - y = pScrn->pScreen->width - oldx; - hotspoty = I810_CURSOR_X; - break; - case RR_Rotate_180: - x = pScrn->pScreen->width - oldx; - y = pScrn->pScreen->height - oldy; - hotspotx = I810_CURSOR_X; - hotspoty = I810_CURSOR_Y; - break; - case RR_Rotate_270: - x = pScrn->pScreen->height - oldy; - y = oldx; - hotspotx = I810_CURSOR_Y; - break; - } - - x -= hotspotx; - y -= hotspoty; - - /* Now, readjust */ - x -= pScrn->frameX0; - y -= pScrn->frameY0; - - /* Clamp the cursor position to the visible screen area. Ignore this if we - * are doing motion (with SilkenMouse) while the currentMode being changed. - */ - if (pScrn->currentMode != NULL) { - if (x >= pScrn->currentMode->HDisplay) - x = pScrn->currentMode->HDisplay - 1; - if (y >= pScrn->currentMode->VDisplay) - y = pScrn->currentMode->VDisplay - 1; - } - if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1; - if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1; - -#if 0 - /* - * There is a screen display problem when the cursor position is set - * wholely outside of the viewport. We trap that here, turning the - * cursor off when that happens, and back on when it comes back into - * the viewport. - */ - if (x >= pScrn->currentMode->HDisplay || - y >= pScrn->currentMode->VDisplay || - x <= -I810_CURSOR_X || y <= -I810_CURSOR_Y) { - hide = TRUE; - outsideViewport = TRUE; - } else if (outsideViewport) { - show = TRUE; - outsideViewport = FALSE; - } -#endif - - if (x < 0) { - temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); - x = -x; - } - if (y < 0) { - temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); - y = -y; - } - temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); - temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - - OUTREG(CURSOR_A_POSITION, temp); - if (pI830->Clone) - OUTREG(CURSOR_B_POSITION, temp); - - if (pI830->cursorOn) { - if (hide) - pI830->CursorInfoRec->HideCursor(pScrn); - else if (show) - pI830->CursorInfoRec->ShowCursor(pScrn); - pI830->cursorOn = TRUE; - } - - /* have to upload the base for the new position */ - if (IS_I9XX(pI830)) { - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); - } - } + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + Bool inrange; + int oldx = x, oldy = y; + int hotspotx = 0, hotspoty = 0; + int pipe; + + oldx += pScrn->frameX0; /* undo what xf86HWCurs did */ + oldy += pScrn->frameY0; + + switch (pI830->rotation) { + case RR_Rotate_0: + x = oldx; + y = oldy; + break; + case RR_Rotate_90: + x = oldy; + y = pScrn->pScreen->width - oldx; + hotspoty = I810_CURSOR_X; + break; + case RR_Rotate_180: + x = pScrn->pScreen->width - oldx; + y = pScrn->pScreen->height - oldy; + hotspotx = I810_CURSOR_X; + hotspoty = I810_CURSOR_Y; + break; + case RR_Rotate_270: + x = pScrn->pScreen->height - oldy; + y = oldx; + hotspotx = I810_CURSOR_Y; + break; + } + + x -= hotspotx; + y -= hotspoty; + + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + { + DisplayModePtr mode = &pI830->pipeCurMode[pipe]; + int thisx = x - pI830->pipeX[pipe]; + int thisy = y - pI830->pipeY[pipe]; + + if (!pI830->planeEnabled[pipe]) + continue; + + /* + * There is a screen display problem when the cursor position is set + * wholely outside of the viewport. We trap that here, turning the + * cursor off when that happens, and back on when it comes back into + * the viewport. + */ + inrange = TRUE; + if (thisx >= mode->HDisplay || + thisy >= mode->VDisplay || + thisx <= -I810_CURSOR_X || thisy <= -I810_CURSOR_Y) + { + inrange = FALSE; + thisx = 0; + thisy = 0; + } + + temp = 0; + if (thisx < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); + thisx = -thisx; + } + if (thisy < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); + thisy = -thisy; + } + temp |= ((thisx & CURSOR_POS_MASK) << CURSOR_X_SHIFT); + temp |= ((thisy & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); + + if (pipe == 0) + OUTREG(CURSOR_A_POSITION, temp); + if (pipe == 1) + OUTREG(CURSOR_B_POSITION, temp); + + pI830->cursorInRange[pipe] = inrange; + + I830SetPipeCursor (pScrn, pipe); + } + + /* have to upload the base for the new position */ + if (IS_I9XX(pI830)) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + if (pI830->Clone) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } + } } static void I830ShowCursor(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp; + int pipe; DPRINTF(PFX, "I830ShowCursor\n"); DPRINTF(PFX, @@ -482,81 +564,22 @@ I830ShowCursor(ScrnInfoPtr pScrn) " Value of CursorMemARGB->Start is %x ", pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); - pI830->cursorOn = TRUE; - if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - temp = INREG(CURSOR_A_CONTROL); - temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); - if (pI830->CursorIsARGB) { - temp |= CURSOR_MODE_64_ARGB_AX; - if (pI830->gammaEnabled[pI830->pipe]) - temp |= MCURSOR_GAMMA_ENABLE; - } else - temp |= CURSOR_MODE_64_4C_AX; - temp |= (pI830->pipe << 28); /* Connect to correct pipe */ - /* Need to set mode, then address. */ - OUTREG(CURSOR_A_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { - temp &= ~MCURSOR_PIPE_SELECT; - temp |= (!pI830->pipe << 28); - OUTREG(CURSOR_B_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); - } - } else { - temp = INREG(CURSOR_CONTROL); - temp &= ~(CURSOR_FORMAT_MASK); - temp |= CURSOR_ENABLE; - if (pI830->CursorIsARGB) { - temp |= CURSOR_FORMAT_ARGB; - if (pI830->gammaEnabled[pI830->pipe]) - temp |= CURSOR_GAMMA_ENABLE; - } else - temp |= CURSOR_FORMAT_3C; - OUTREG(CURSOR_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start); - else - OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start); - } + pI830->cursorOn = TRUE; + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + I830SetPipeCursor (pScrn, pipe); } static void I830HideCursor(ScrnInfoPtr pScrn) { - CARD32 temp; I830Ptr pI830 = I830PTR(pScrn); + int pipe; DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { - temp = INREG(CURSOR_A_CONTROL); - temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE); - temp |= CURSOR_MODE_DISABLE; - OUTREG(CURSOR_A_CONTROL, temp); - /* This is needed to flush the above change. */ - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { - OUTREG(CURSOR_B_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); - } - } else { - temp = INREG(CURSOR_CONTROL); - temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); - OUTREG(CURSOR_CONTROL, temp); - } + for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++) + I830SetPipeCursor (pScrn, pipe); } static void diff --git a/src/i830_display.c b/src/i830_display.c index 6eb2a330..52d488a4 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -245,13 +245,15 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); else OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + pI830->pipeX[pipe] = x; + pI830->pipeY[pipe] = y; } /** * Sets the given video mode on the given pipe. Assumes that plane A feeds * pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes. */ -static Bool +Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) { I830Ptr pI830 = I830PTR(pScrn); @@ -608,7 +610,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp); OUTREG(DSPASIZE, dspsize); OUTREG(DSPAPOS, 0); - i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0); + i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]); OUTREG(PIPEASRC, pipesrc); /* Then, turn the pipe on first */ @@ -656,7 +658,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe) OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp); OUTREG(DSPBSIZE, dspsize); OUTREG(DSPBPOS, 0); - i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0); + i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeY[pipe]); OUTREG(PIPEBSRC, pipesrc); if (outputs & PIPE_LCD_ACTIVE) { diff --git a/src/i830_display.h b/src/i830_display.h index 2e61afce..e5bca1c8 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -26,6 +26,7 @@ */ /* i830_display.c */ +Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe); Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb); void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on); diff --git a/src/i830_driver.c b/src/i830_driver.c index 8464b39f..dc136a3a 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -273,7 +273,7 @@ static OptionInfoRec I830BIOSOptions[] = { }; /* *INDENT-ON* */ -static const char *output_type_names[] = { +const char *i830_output_type_names[] = { "Unused", "Analog", "DVO", @@ -1133,7 +1133,7 @@ I830DetectMonitors(ScrnInfoPtr pScrn) pI830->output[i].pDDCBus); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n", - output_type_names[pI830->output[i].type], i, + i830_output_type_names[pI830->output[i].type], i, pI830->output[i].pDDCBus->DriverPrivate.uval); xf86PrintEDID(pI830->output[i].MonInfo); break; @@ -3164,22 +3164,8 @@ I830CreateScreenResources (ScreenPtr pScreen) if (!(*pScreen->CreateScreenResources)(pScreen)) return FALSE; - 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 */ - I830RandRSetConfig (pScreen, requestedRotation, 0, &p); - pI830->starting = FALSE; - } + if (!I830RandRCreateScreenResources (pScreen)) + return FALSE; return TRUE; } @@ -3507,6 +3493,9 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (!I830BIOSEnterVT(scrnIndex, 0)) return FALSE; + if (pScrn->virtualX > pScrn->displayWidth) + pScrn->displayWidth = pScrn->virtualX; + DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n"); if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, pScrn->virtualX, pScrn->virtualY, diff --git a/src/i830_modes.c b/src/i830_modes.c index 6bff1d0a..3b70d5d4 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -954,6 +954,11 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) maxY = mode->VDisplay; } } + /* let the user specify a bigger virtual size if they like */ + if (pScrn->display->virtualX > maxX) + maxX = pScrn->display->virtualX; + if (pScrn->display->virtualY > maxY) + maxY = pScrn->display->virtualY; pScrn->virtualX = maxX; pScrn->virtualY = maxY; pScrn->displayWidth = (maxX + 63) & ~63; diff --git a/src/i830_randr.c b/src/i830_randr.c index 4c7c087e..4132eb2e 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -23,6 +23,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xf86.h" #include "os.h" #include "mibank.h" @@ -33,9 +37,11 @@ #include "mipointer.h" #include "windowstr.h" #include <randrstr.h> +#include <X11/extensions/render.h> #include "i830.h" #include "i830_xf86Modes.h" +#include "i830_display.h" typedef struct _i830RandRInfo { int virtualX; @@ -46,8 +52,18 @@ typedef struct _i830RandRInfo { int maxY; Rotation rotation; /* current mode */ Rotation supported_rotations; /* driver supported */ +#ifdef RANDR_12_INTERFACE + RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; + RROutputPtr outputs[MAX_OUTPUTS]; + DisplayModePtr modes[MAX_DISPLAY_PIPES]; +#endif } XF86RandRInfoRec, *XF86RandRInfoPtr; +#ifdef RANDR_12_INTERFACE +static Bool I830RandRInit12 (ScreenPtr pScreen); +static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen); +#endif + static int i830RandRIndex; static int i830RandRGeneration; @@ -317,6 +333,40 @@ I830GetRotation(ScreenPtr pScreen) } Bool +I830RandRCreateScreenResources (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif +#if RANDR_12_INTERFACE + if (I830RandRCreateScreenResources12 (pScreen)) + return TRUE; +#endif + 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 */ + I830RandRSetConfig (pScreen, requestedRotation, 0, &p); + pI830->starting = FALSE; + } + return TRUE; +} + + +Bool I830RandRInit (ScreenPtr pScreen, int rotation) { rrScrPrivPtr rp; @@ -359,6 +409,10 @@ I830RandRInit (ScreenPtr pScreen, int rotation) pScreen->devPrivates[i830RandRIndex].ptr = randrp; +#if RANDR_12_INTERFACE + if (!I830RandRInit12 (pScreen)) + return FALSE; +#endif return TRUE; } @@ -379,3 +433,399 @@ I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) *y = randrp->virtualY; } } + +#if RANDR_12_INTERFACE +static Bool +I830RandRScreenSetSize (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 +I830RandRCrtcNotify (RRCrtcPtr crtc) +{ + ScreenPtr pScreen = crtc->pScreen; + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + RRModePtr mode = NULL; + int x; + int y; + Rotation rotation; + int numOutputs; + RROutputPtr outputs[MAX_OUTPUTS]; + struct _I830OutputRec *output; + RROutputPtr rrout; + int pipe = (int) crtc->devPrivate; + int i, j; + DisplayModePtr pipeMode = &pI830->pipeCurMode[pipe]; + int pipe_type; + + x = pI830->pipeX[pipe]; + y = pI830->pipeY[pipe]; + rotation = RR_Rotate_0; + numOutputs = 0; + for (i = 0; i < pI830->num_outputs; i++) + { + output = &pI830->output[i]; + /* + * Valid crtcs + */ + switch (output->type) { + case I830_OUTPUT_DVO: + case I830_OUTPUT_SDVO: + pipe_type = PIPE_DFP; + break; + case I830_OUTPUT_ANALOG: + pipe_type = PIPE_CRT; + break; + case I830_OUTPUT_LVDS: + pipe_type = PIPE_LFP; + break; + case I830_OUTPUT_TVOUT: + pipe_type = PIPE_TV; + break; + default: + pipe_type = PIPE_NONE; + break; + } + if (pI830->operatingDevices & (pipe_type << (pipe << 3))) + { + rrout = randrp->outputs[i]; + outputs[numOutputs++] = rrout; + for (j = 0; j < rrout->numModes; j++) + { + DisplayModePtr outMode = rrout->modes[j]->devPrivate; + if (I830ModesEqual(pipeMode, outMode)) + mode = rrout->modes[j]; + } + } + } + return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs); +} + +static Bool +I830RandRCrtcSet (ScreenPtr pScreen, + RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutputs, + RROutputPtr *outputs) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + int pipe = (int) (crtc->devPrivate); + DisplayModePtr display_mode = mode->devPrivate; + + /* Sync the engine before adjust mode */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + + if (display_mode != randrp->modes[pipe]) + { + if (!i830PipeSetMode (pScrn, display_mode, pipe)) + return FALSE; + randrp->modes[pipe] = display_mode; + } + i830PipeSetBase(pScrn, pipe, x, y); + return I830RandRCrtcNotify (crtc); +} + +static Bool +I830RandRCrtcSetGamma (ScreenPtr pScreen, + RRCrtcPtr crtc) +{ + return FALSE; +} + +/* + * Mirror the current mode configuration to RandR + */ +static Bool +I830RandRSetInfo12 (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + RROutputPtr clones[MAX_OUTPUTS]; + RRCrtcPtr crtc; + int nclone; + RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; + int ncrtc; + RRModePtr *modes; + int nmode; + struct _I830OutputRec *output; + int i; + int j; + int clone_types; + int crtc_types; + int connection; + int pipe_type; + int pipe; + int subpixel; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + RRScreenSetSizeRange (pScreen, 320, 240, + randrp->virtualX, randrp->virtualY); + for (i = 0; i < pI830->num_outputs; i++) + { + output = &pI830->output[i]; + /* + * Valid crtcs + */ + switch (output->type) { + case I830_OUTPUT_DVO: + case I830_OUTPUT_SDVO: + crtc_types = ((1 << 0)| + (1 << 1)); + clone_types = ((1 << I830_OUTPUT_ANALOG) | + (1 << I830_OUTPUT_DVO) | + (1 << I830_OUTPUT_SDVO)); + pipe_type = PIPE_DFP; + subpixel = SubPixelHorizontalRGB; + break; + case I830_OUTPUT_ANALOG: + crtc_types = (1 << 0); + clone_types = ((1 << I830_OUTPUT_ANALOG) | + (1 << I830_OUTPUT_DVO) | + (1 << I830_OUTPUT_SDVO)); + pipe_type = PIPE_CRT; + subpixel = SubPixelNone; + break; + case I830_OUTPUT_LVDS: + crtc_types = (1 << 1); + clone_types = (1 << I830_OUTPUT_LVDS); + pipe_type = PIPE_LFP; + subpixel = SubPixelHorizontalRGB; + break; + case I830_OUTPUT_TVOUT: + crtc_types = ((1 << 0) | + (1 << 1)); + clone_types = (1 << I830_OUTPUT_TVOUT); + pipe_type = PIPE_TV; + subpixel = SubPixelNone; + break; + default: + crtc_types = 0; + clone_types = 0; + pipe_type = PIPE_NONE; + subpixel = SubPixelUnknown; + break; + } + ncrtc = 0; + pipe = -1; + crtc = NULL; + for (j = 0; j < MAX_DISPLAY_PIPES; j++) + { +#if 0 + /* Can't flip outputs among crtcs yet */ + if (crtc_types & (1 << j)) + crtcs[ncrtc++] = randrp->crtcs[j]; +#endif + if (pI830->operatingDevices & (pipe_type << (j << 3))) + { + pipe = j; + crtc = randrp->crtcs[j]; + crtcs[ncrtc++] = crtc; + } + } + if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc)) + return FALSE; + + RROutputSetCrtc (randrp->outputs[i], crtc); + + if (pipe >= 0) + { + MonPtr mon = pI830->pipeMon[pipe]; + DisplayModePtr mode; + xRRModeInfo modeInfo; + RRModePtr rrmode; + + nmode = 0; + for (mode = mon->Modes; mode; mode = mode->next) + nmode++; + + if (nmode) + { + modes = xalloc (nmode * sizeof (RRModePtr)); + if (!modes) + return FALSE; + nmode = 0; + for (mode = mon->Modes; mode; mode = mode->next) + { + modeInfo.nameLength = strlen (mode->name); + modeInfo.mmWidth = mon->widthmm; + modeInfo.mmHeight = mon->heightmm; + + modeInfo.width = mode->HDisplay; + modeInfo.dotClock = mode->Clock * 1000; + modeInfo.hSyncStart = mode->HSyncStart; + modeInfo.hSyncEnd = mode->HSyncEnd; + modeInfo.hTotal = mode->HTotal; + modeInfo.hSkew = mode->HSkew; + + modeInfo.height = mode->VDisplay; + modeInfo.vSyncStart = mode->VSyncStart; + modeInfo.vSyncEnd = mode->VSyncEnd; + modeInfo.vTotal = mode->VTotal; + modeInfo.modeFlags = mode->Flags; + + rrmode = RRModeGet (pScreen, &modeInfo, mode->name); + rrmode->devPrivate = mode; + if (rrmode) + modes[nmode++] = rrmode; + } + if (!RROutputSetModes (randrp->outputs[i], modes, nmode)) + { + xfree (modes); + return FALSE; + } + + xfree (modes); + } + } + connection = RR_Disconnected; + if (pipe >= 0) + connection = RR_Connected; + + RROutputSetConnection (randrp->outputs[i], connection); + + RROutputSetSubpixelOrder (randrp->outputs[i], subpixel); + + /* + * Valid clones + */ + nclone = 0; + for (j = 0; j < pI830->num_outputs; j++) + { + if (i != j && ((1 << pI830->output[j].type) & clone_types)) + clones[nclone++] = randrp->outputs[j]; + } + if (!RROutputSetClones (randrp->outputs[i], clones, nclone)) + return FALSE; + } + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + I830RandRCrtcNotify (randrp->crtcs[i]); + return TRUE; +} + + +/* + * Query the hardware for the current state, then mirror + * that to RandR + */ +static Bool +I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + /* Re-probe the outputs for new monitors or modes */ + I830ValidateXF86ModeList(pScrn, FALSE); + return I830RandRSetInfo12 (pScreen); +} + +static Bool +I830RandRCreateScreenResources12 (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + struct _I830OutputRec *output; + const char *name; + int i; + DisplayModePtr mode; + + /* + * Create RandR resources, then probe them + */ + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + { + randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i); + RRCrtcGammaSetSize (randrp->crtcs[i], 256); + } + + for (i = 0; i < pI830->num_outputs; i++) + { + output = &pI830->output[i]; + name = i830_output_type_names[output->type]; + randrp->outputs[i] = RROutputCreate (pScreen, + name, strlen (name), + (void *) i); + } + + mode = pScrn->currentMode; + if (mode) + { + I830RandRScreenSetSize (pScreen, + mode->HDisplay, + mode->VDisplay, + pScreen->mmWidth, + pScreen->mmHeight); + + } + + for (i = 0; i < MAX_DISPLAY_PIPES; i++) + i830PipeSetBase(pScrn, i, 0, 0); + + return I830RandRSetInfo12 (pScreen); +} + +static void +I830RandRPointerMoved (int scrnIndex, int x, int y) +{ +} + +static Bool +I830RandRInit12 (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + rrScrPrivPtr rp = rrGetScrPriv(pScreen); + + rp->rrGetInfo = I830RandRGetInfo12; + rp->rrScreenSetSize = I830RandRScreenSetSize; + rp->rrCrtcSet = I830RandRCrtcSet; + rp->rrCrtcSetGamma = I830RandRCrtcSetGamma; + rp->rrSetConfig = NULL; + memset (rp->modes, '\0', sizeof (rp->modes)); + pScrn->PointerMoved = I830RandRPointerMoved; + return TRUE; +} +#endif |