diff --git a/src/i830.h b/src/i830.h index 66dad9b9..c7920730 100644 --- a/src/i830.h +++ b/src/i830.h @@ -195,8 +195,11 @@ extern const char *i830_output_type_names[]; typedef struct _I830CrtcPrivateRec { int pipe; + /* Lookup table values to be set when the CRTC is enabled */ CARD8 lut_r[256], lut_g[256], lut_b[256]; + + I830MemRange rotate_mem; } I830CrtcPrivateRec, *I830CrtcPrivatePtr; #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private) diff --git a/src/i830_display.c b/src/i830_display.c index de6c7225..08842ec9 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -342,9 +342,11 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - if (I830IsPrimary(pScrn)) + if (intel_crtc->rotate_mem.Start != 0) { + Start = intel_crtc->rotate_mem.Start; + } else if (I830IsPrimary(pScrn)) { Start = pI830->FrontBuffer.Start; - else { + } else { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); Start = pI8301->FrontBuffer2.Start; } @@ -882,6 +884,45 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, i830_crtc_load_lut(crtc); } +/** + * Creates a locked-in-framebuffer pixmap of the given width and height for + * this CRTC's rotated shadow framebuffer. + * + * The current implementation uses fixed buffers allocated at startup at the + * maximal size. + */ +static PixmapPtr +i830_crtc_shadow_create(xf86CrtcPtr crtc, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + unsigned long rotate_pitch; + PixmapPtr rotate_pixmap; + pointer rotate_offset; + + if (intel_crtc->rotate_mem.Start == 0) + return NULL; + + rotate_pitch = pI830->displayWidth * pI830->cpp; + rotate_offset = pI830->FbBase + intel_crtc->rotate_mem.Start; + + rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, + width, height, + pScrn->depth, + pScrn->bitsPerPixel, + rotate_pitch, + rotate_offset); + return rotate_pixmap; +} + +static void +i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap) +{ + FreeScratchPixmapHeader(rotate_pixmap); +} + + /** * This function configures the screens in clone mode on * all active outputs using a mode similar to the specified mode. @@ -1038,6 +1079,8 @@ static const xf86CrtcFuncsRec i830_crtc_funcs = { .mode_fixup = i830_crtc_mode_fixup, .mode_set = i830_crtc_mode_set, .gamma_set = i830_crtc_gamma_set, + .shadow_create = i830_crtc_shadow_create, + .shadow_destroy = i830_crtc_shadow_destroy, .destroy = NULL, /* XXX */ }; diff --git a/src/i830_memory.c b/src/i830_memory.c index 426242a9..ae14c06c 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -769,6 +769,63 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, return TRUE; } +/** + * Allocates memory for the rotated shadow buffers. + * + * This memory would be better allocated normally through the linear allocator, + * but it gets rotation working for now. + */ +static Bool +I830AllocateRotateBuffers(xf86CrtcPtr crtc, const int flags) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + I830Ptr pI830 = I830PTR(pScrn); + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + unsigned long avail, lineSize; + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + int align, alignflags; + long size, alloced; + int rotate_width, rotate_height; + + memset(&intel_crtc->rotate_mem, 0, sizeof(intel_crtc->rotate_mem)); + + rotate_width = pScrn->displayWidth; + if (pScrn->virtualX > pScrn->virtualY) + rotate_height = pScrn->virtualX; + else + rotate_height = pScrn->virtualY; + + lineSize = pScrn->displayWidth * pI830->cpp; + avail = pScrn->videoRam * 1024; + + align = KB(64); + alignflags = 0; + + size = lineSize * rotate_height; + size = ROUND_TO_PAGE(size); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sInitial %sshadow framebuffer allocation size: " + "%ld kByte\n", + s, (intel_crtc->pipe == 0) ? "" : "secondary ", + size / 1024); + alloced = I830AllocVidMem(pScrn, &intel_crtc->rotate_mem, + &pI830->StolenPool, size, align, + flags | alignflags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "%sshadow framebuffer. Is your VideoRAM set too low?\n", + (intel_crtc->pipe == 0) ? "" : "secondary "); + } + return FALSE; + } + + return TRUE; +} + /* * Allocate memory for 2D operation. This includes the (front) framebuffer, * ring buffer, scratch memory, HW cursor. @@ -782,7 +839,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) int verbosity = dryrun ? 4 : 1; const char *s = dryrun ? "[dryrun] " : ""; Bool tileable; - int align, alignflags; + int align, alignflags, i; DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n", BOOLTOSTRING(flags & ALLOC_INITIAL)); @@ -814,6 +871,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->StolenPool.Free.Size); if (flags & ALLOC_INITIAL) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); if (pI830->NeedRingBufferLow) AllocateRingBuffer(pScrn, flags | FORCE_LOW); @@ -839,6 +897,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) return FALSE; } + for (i = 0; i < xf86_config->num_crtc; i++) { + I830AllocateRotateBuffers(xf86_config->crtc[i], flags); + } + #ifdef I830_USE_EXA if (pI830->useEXA) { /* Default EXA to having 3 screens worth of offscreen memory space diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 504ea0b9..a926e9fb 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -190,13 +190,10 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, goto done; } -#if 0 - if (!xf86CrtcRotate (crtc, mode, rotation)) - { + if (!xf86CrtcRotate (crtc, mode, rotation)) { ret = FALSE; goto done; } -#endif /* Disable the outputs and CRTCs before setting the mode. */ for (i = 0; i < xf86_config->num_output; i++) {