diff options
Diffstat (limited to 'src/i830_video.c')
-rw-r--r-- | src/i830_video.c | 869 |
1 files changed, 646 insertions, 223 deletions
diff --git a/src/i830_video.c b/src/i830_video.c index 12c25e05..28e95be9 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -73,7 +73,7 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86Pci.h" #include "xf86fbman.h" #include "regionstr.h" - +#include "randrstr.h" #include "i830.h" #include "xf86xv.h" #include <X11/extensions/Xv.h> @@ -114,12 +114,13 @@ static void I830BlockHandler(int, pointer, pointer, pointer); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) -static Atom xvBrightness, xvContrast, xvColorKey, xvPipe; +static Atom xvBrightness, xvContrast, xvColorKey, xvPipe, xvDoubleBuffer; static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; -#define IMAGE_MAX_WIDTH 1440 +#define IMAGE_MAX_WIDTH 1920 #define IMAGE_MAX_HEIGHT 1080 -#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT) +#define IMAGE_MAX_WIDTH_LEGACY 1024 +#define IMAGE_MAX_HEIGHT_LEGACY 1080 #if !VIDEO_DEBUG #define ErrorF Edummy @@ -138,13 +139,13 @@ Edummy(const char *dummy, ...) * all modes of server exit. */ -#define OVERLAY_UPDATE \ +#define OVERLAY_UPDATE \ do { \ BEGIN_LP_RING(6); \ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE); \ OUT_RING(MI_NOOP); \ if (!*pI830->overlayOn) { \ - OUT_RING(MI_NOOP); \ + 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"); \ @@ -154,7 +155,7 @@ Edummy(const char *dummy, ...) OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \ } \ - OUT_RING(pI830->OverlayMem->Physical | 1); \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ ADVANCE_LP_RING(); \ ErrorF("OVERLAY_UPDATE\n"); \ } while(0) @@ -162,18 +163,28 @@ Edummy(const char *dummy, ...) #define OVERLAY_OFF \ do { \ if (*pI830->overlayOn) { \ - BEGIN_LP_RING(8); \ + int spin = 1000000; \ + BEGIN_LP_RING(12); \ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ + OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF); \ - OUT_RING(pI830->OverlayMem->Physical); \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ *pI830->overlayOn = FALSE; \ ErrorF("Overlay goes from on to off\n"); \ + while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){ \ + ErrorF("SPIN %d\n",spin); \ + spin--; \ + } \ + if (spin == 0) ErrorF("OVERLAY FAILED TO GO OFF\n"); \ ErrorF("OVERLAY_OFF\n"); \ } \ } while(0) @@ -181,6 +192,7 @@ Edummy(const char *dummy, ...) /* * OCMD - Overlay Command Register */ +#define OCMD_REGISTER 0x30168 #define MIRROR_MODE (0x3<<17) #define MIRROR_HORIZONTAL (0x1<<17) #define MIRROR_VERTICAL (0x2<<17) @@ -212,11 +224,15 @@ Edummy(const char *dummy, ...) #define FIELD1 (0x1<<1) #define OVERLAY_ENABLE 0x1 +#define OFC_UPDATE 0x1 + /* OCONFIG register */ #define CC_OUT_8BIT (0x1<<3) #define OVERLAY_PIPE_MASK (0x1<<18) #define OVERLAY_PIPE_A (0x0<<18) #define OVERLAY_PIPE_B (0x1<<18) +#define THREE_LINE_BUFFERS (0x1<<0) +#define TWO_LINE_BUFFERS (0x0<<0) /* DCLRKM register */ #define DEST_KEY_ENABLE (0x1<<31) @@ -260,11 +276,12 @@ static XF86AttributeRec CloneAttributes[CLONE_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 1, "XV_PIPE"} }; -#define NUM_ATTRIBUTES 3 +#define NUM_ATTRIBUTES 4 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, - {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, + {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"} }; #define GAMMA_ATTRIBUTES 6 @@ -355,6 +372,7 @@ typedef struct { int brightness; int contrast; int pipe; + int doubleBuffer; RegionRec clip; CARD32 colorKey; @@ -390,7 +408,7 @@ 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%08x != 0x%08x)\n", + ErrorF("0x%05x value doesn't match (0x%lx != 0x%lx)\n", 0x30100 + i, val, overlay[i / 4]); bad++; } @@ -463,7 +481,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); - DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%08x, obase: %p\n", + DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n", pI830->FbBase, pI830->OverlayMem->Start, overlay); /* * Default to maximum image size in YV12 @@ -475,10 +493,10 @@ I830ResetVideo(ScrnInfoPtr pScrn) overlay->HORZ_PH = 0; overlay->INIT_PHS = 0; overlay->DWINPOS = 0; - overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH; - overlay->SWIDTH = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 16); - overlay->SWIDTHSW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12); - overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15); + overlay->DWINSZ = 0; + overlay->SWIDTH = 0; + overlay->SWIDTHSW = 0; + overlay->SHEIGHT = 0; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); overlay->OCLRC1 = 0x00000080; /* saturation: bypass */ overlay->AWINPOS = 0; @@ -532,7 +550,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) { int i; for (i = 0x30000; i < 0x31000; i += 4) - ErrorF("0x%x 0x%08x\n", i, INREG(i)); + ErrorF("0x%x 0x%lx\n", i, INREG(i)); } #endif } @@ -602,10 +620,15 @@ I830SetupImageVideo(ScreenPtr pScreen) return NULL; adapt->type = XvWindowMask | XvInputMask | XvImageMask; - adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/; adapt->name = "Intel(R) Video Overlay"; adapt->nEncodings = 1; adapt->pEncodings = DummyEncoding; + /* update the DummyEncoding for these two chipsets */ + if (IS_845G(pI830) || IS_I830(pI830)) { + adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY; + adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY; + } adapt->nFormats = NUM_FORMATS; adapt->pFormats = Formats; adapt->nPorts = 1; @@ -617,7 +640,7 @@ I830SetupImageVideo(ScreenPtr pScreen) adapt->nAttributes = NUM_ATTRIBUTES; if (pI830->Clone) adapt->nAttributes += CLONE_ATTRIBUTES; - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) + if (IS_I9XX(pI830)) adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */ adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes); /* Now copy the attributes */ @@ -628,7 +651,7 @@ I830SetupImageVideo(ScreenPtr pScreen) memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES); att+=CLONE_ATTRIBUTES; } - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + if (IS_I9XX(pI830)) { memcpy((char*)att, (char*)GammaAttributes, sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES); att+=GAMMA_ATTRIBUTES; } @@ -658,6 +681,7 @@ I830SetupImageVideo(ScreenPtr pScreen) pPriv->gamma2 = 0x202020; pPriv->gamma1 = 0x101010; pPriv->gamma0 = 0x080808; + pPriv->doubleBuffer = 1; /* gotta uninit this someplace */ REGION_NULL(pScreen, &pPriv->clip); @@ -680,15 +704,16 @@ I830SetupImageVideo(ScreenPtr pScreen) pI830->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = I830BlockHandler; + xvColorKey = MAKE_ATOM("XV_COLORKEY"); xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvContrast = MAKE_ATOM("XV_CONTRAST"); - xvColorKey = MAKE_ATOM("XV_COLORKEY"); + xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); /* Allow the pipe to be switched from pipe A to B when in clone mode */ if (pI830->Clone) xvPipe = MAKE_ATOM("XV_PIPE"); - - if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) { + + if (IS_I9XX(pI830)) { xvGamma0 = MAKE_ATOM("XV_GAMMA0"); xvGamma1 = MAKE_ATOM("XV_GAMMA1"); xvGamma2 = MAKE_ATOM("XV_GAMMA2"); @@ -747,10 +772,12 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) if (shutdown) { if (pPriv->videoStatus & CLIENT_VIDEO_ON) { + overlay->OCMD &= ~OVERLAY_ENABLE; OVERLAY_UPDATE; - +#if 1 OVERLAY_OFF; +#endif if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; @@ -783,15 +810,23 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, return BadValue; pPriv->brightness = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - if (pPriv->overlayOK) - OVERLAY_UPDATE; + ErrorF("BRIGHTNESS\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif } else if (attribute == xvContrast) { if ((value < 0) || (value > 255)) return BadValue; pPriv->contrast = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - if (pPriv->overlayOK) - OVERLAY_UPDATE; + ErrorF("CONTRAST\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif } else if (pI830->Clone && attribute == xvPipe) { if ((value < 0) || (value > 1)) return BadValue; @@ -804,52 +839,36 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->OCONFIG |= OVERLAY_PIPE_A; else overlay->OCONFIG |= OVERLAY_PIPE_B; - if (pPriv->overlayOK) - OVERLAY_UPDATE; - } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - /* Avoid video anomalies, so set gamma registers when overlay is off */ - /* We also clamp the values if they are outside the ranges */ - if (!*pI830->overlayOn) { - pPriv->gamma0 = value; - if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) - pPriv->gamma1 = pPriv->gamma0 + 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma1 = value; - if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) - pPriv->gamma0 = pPriv->gamma1 - 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma2 = value; - if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) - pPriv->gamma3 = pPriv->gamma2 + 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma3 = value; - if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) - pPriv->gamma2 = pPriv->gamma3 - 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma4 = value; - if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) - pPriv->gamma5 = pPriv->gamma4 + 0x7d; - } else - return BadRequest; - } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { - if (!*pI830->overlayOn) { - pPriv->gamma5 = value; - if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) - pPriv->gamma4 = pPriv->gamma5 - 0x7d; - } else - return BadRequest; + ErrorF("PIPE CHANGE\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif + } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { + pPriv->gamma0 = value; + if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) + pPriv->gamma1 = pPriv->gamma0 + 0x7d; + } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) { + pPriv->gamma1 = value; + if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) + pPriv->gamma0 = pPriv->gamma1 - 0x7d; + } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) { + pPriv->gamma2 = value; + if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) + pPriv->gamma3 = pPriv->gamma2 + 0x7d; + } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) { + pPriv->gamma3 = value; + if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) + pPriv->gamma2 = pPriv->gamma3 - 0x7d; + } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) { + pPriv->gamma4 = value; + if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) + pPriv->gamma5 = pPriv->gamma4 + 0x7d; + } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) { + pPriv->gamma5 = value; + if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) + pPriv->gamma4 = pPriv->gamma5 - 0x7d; } else if (attribute == xvColorKey) { pPriv->colorKey = value; switch (pScrn->depth) { @@ -863,9 +882,19 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->DCLRKV = pPriv->colorKey; break; } - if (pPriv->overlayOK) - OVERLAY_UPDATE; + ErrorF("COLORKEY\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else if(attribute == xvDoubleBuffer) { + if ((value < 0) || (value > 1)) + return BadValue; + /* Do not allow buffer change while playing video */ + if(!*pI830->overlayOn) + pPriv->doubleBuffer = value; } else return BadMatch; @@ -875,7 +904,13 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, attribute == xvGamma2 || attribute == xvGamma3 || attribute == xvGamma4 || - attribute == xvGamma5) && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + attribute == xvGamma5) && (IS_I9XX(pI830))) { + ErrorF("GAMMA\n"); + overlay->OCMD &= ~OVERLAY_ENABLE; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif I830UpdateGamma(pScrn); } @@ -895,21 +930,23 @@ I830GetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->contrast; } else if (pI830->Clone && attribute == xvPipe) { *value = pPriv->pipe; - } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) { *value = pPriv->gamma0; - } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) { *value = pPriv->gamma1; - } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) { *value = pPriv->gamma2; - } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) { *value = pPriv->gamma3; - } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) { *value = pPriv->gamma4; - } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) { + } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) { *value = pPriv->gamma5; } else if (attribute == xvColorKey) { *value = pPriv->colorKey; - } else + } else if (attribute == xvDoubleBuffer) { + *value = pPriv->doubleBuffer; + } else return BadMatch; return Success; @@ -940,8 +977,10 @@ I830CopyPackedData(ScrnInfoPtr pScrn, I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; unsigned char *src, *dst; + int i,j; + unsigned char *s; - DPRINTF(PFX, "I830CopyPackedData: (%d,%d) (%d,%d)\n" + ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n" "srcPitch: %d, dstPitch: %d\n", top, left, h, w, srcPitch, dstPitch); src = buf + (top * srcPitch) + (left << 1); @@ -951,11 +990,76 @@ I830CopyPackedData(ScrnInfoPtr pScrn, else dst = pI830->FbBase + pPriv->YBuf1offset; - w <<= 1; - while (h--) { - memcpy(dst, src, w); - src += srcPitch; - dst += dstPitch; + switch (pI830->rotation) { + case RR_Rotate_0: + w <<= 1; + for (i = 0; i < h; i++) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } + break; + case RR_Rotate_90: + h <<= 1; + for (i = 0; i < h; i+=2) { + s = src; + for (j = 0; j < w; j++) { + /* Copy Y */ + dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++; + (void)*s++; + } + src += srcPitch; + } + h >>= 1; + src = buf + (top * srcPitch) + (left << 1); + for (i = 0; i < h; i+=2) { + for (j = 0; j < w; j+=2) { + /* Copy U */ + dst[((i*2) + 1) + ((w - j - 1) * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)]; + dst[((i*2) + 1) + ((w - j - 2) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)]; + /* Copy V */ + dst[((i*2) + 3) + ((w - j - 1) * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)]; + dst[((i*2) + 3) + ((w - j - 2) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)]; + } + } + break; + case RR_Rotate_180: + w <<= 1; + for (i = 0; i < h; i++) { + s = src; + for (j = 0; j < w; j+=4) { + dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = *s++; + dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = *s++; + dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = *s++; + dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = *s++; + } + src += srcPitch; + } + break; + case RR_Rotate_270: + h <<= 1; + for (i = 0; i < h; i+=2) { + s = src; + for (j = 0; j < w; j++) { + /* Copy Y */ + dst[(h - i - 2) + (j * dstPitch)] = *s++; + (void)*s++; + } + src += srcPitch; + } + h >>= 1; + src = buf + (top * srcPitch) + (left << 1); + for (i = 0; i < h; i+=2) { + for (j = 0; j < w; j+=2) { + /* Copy U */ + dst[(((h - i)*2) - 3) + (j * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)]; + dst[(((h - i)*2) - 3) + ((j - 1) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)]; + /* Copy V */ + dst[(((h - i)*2) - 1) + (j * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)]; + dst[(((h - i)*2) - 1) + ((j - 1) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)]; + } + } + break; } } @@ -966,8 +1070,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, { I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; - int i; + int i, j = 0; unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3; + unsigned char *s; + int dstPitch2 = dstPitch << 1; ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n" "nlines %d, npixels %d, top %d, left %d\n", srcPitch, srcPitch2, dstPitch, @@ -975,22 +1081,53 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, /* Copy Y data */ src1 = buf + (top * srcPitch) + left; - ErrorF("src1 is %p, offset is %d\n", src1, + ErrorF("src1 is %p, offset is %ld\n", src1, (unsigned long)src1 - (unsigned long)buf); if (pPriv->currentBuf == 0) dst1 = pI830->FbBase + pPriv->YBuf0offset; else dst1 = pI830->FbBase + pPriv->YBuf1offset; - for (i = 0; i < h; i++) { - memcpy(dst1, src1, w); - src1 += srcPitch; - dst1 += dstPitch << 1; + switch (pI830->rotation) { + case RR_Rotate_0: + for (i = 0; i < h; i++) { + memcpy(dst1, src1, w); + src1 += srcPitch; + dst1 += dstPitch2; + } + break; + case RR_Rotate_90: + for (i = 0; i < h; i++) { + s = src1; + for (j = 0; j < w; j++) { + dst1[(i) + ((w - j - 1) * dstPitch2)] = *s++; + } + src1 += srcPitch; + } + break; + case RR_Rotate_180: + for (i = 0; i < h; i++) { + s = src1; + for (j = 0; j < w; j++) { + dst1[(w - j - 1) + ((h - i - 1) * dstPitch2)] = *s++; + } + src1 += srcPitch; + } + break; + case RR_Rotate_270: + for (i = 0; i < h; i++) { + s = src1; + for (j = 0; j < w; j++) { + dst1[(h - i - 1) + (j * dstPitch2)] = *s++; + } + src1 += srcPitch; + } + break; } /* Copy V data for YV12, or U data for I420 */ src2 = buf + (srcH * srcPitch) + ((top * srcPitch) >> 2) + (left >> 1); - ErrorF("src2 is %p, offset is %d\n", src2, + ErrorF("src2 is %p, offset is %ld\n", src2, (unsigned long)src2 - (unsigned long)buf); if (pPriv->currentBuf == 0) { if (id == FOURCC_I420) @@ -1004,16 +1141,47 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, dst2 = pI830->FbBase + pPriv->VBuf1offset; } - for (i = 0; i < h / 2; i++) { - memcpy(dst2, src2, w / 2); - src2 += srcPitch2; - dst2 += dstPitch; + switch (pI830->rotation) { + case RR_Rotate_0: + for (i = 0; i < h / 2; i++) { + memcpy(dst2, src2, w / 2); + src2 += srcPitch2; + dst2 += dstPitch; + } + break; + case RR_Rotate_90: + for (i = 0; i < (h/2); i++) { + s = src2; + for (j = 0; j < (w/2); j++) { + dst2[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++; + } + src2 += srcPitch2; + } + break; + case RR_Rotate_180: + for (i = 0; i < (h/2); i++) { + s = src2; + for (j = 0; j < (w/2); j++) { + dst2[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++; + } + src2 += srcPitch2; + } + break; + case RR_Rotate_270: + for (i = 0; i < (h/2); i++) { + s = src2; + for (j = 0; j < (w/2); j++) { + dst2[((h/2) - i - 1) + (j * dstPitch)] = *s++; + } + src2 += srcPitch2; + } + break; } /* Copy U data for YV12, or V data for I420 */ src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) + ((top * srcPitch) >> 2) + (left >> 1); - ErrorF("src3 is %p, offset is %d\n", src3, + ErrorF("src3 is %p, offset is %ld\n", src3, (unsigned long)src3 - (unsigned long)buf); if (pPriv->currentBuf == 0) { if (id == FOURCC_I420) @@ -1027,10 +1195,41 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, dst3 = pI830->FbBase + pPriv->UBuf1offset; } - for (i = 0; i < h / 2; i++) { - memcpy(dst3, src3, w / 2); - src3 += srcPitch2; - dst3 += dstPitch; + switch (pI830->rotation) { + case RR_Rotate_0: + for (i = 0; i < h / 2; i++) { + memcpy(dst3, src3, w / 2); + src3 += srcPitch2; + dst3 += dstPitch; + } + break; + case RR_Rotate_90: + for (i = 0; i < (h/2); i++) { + s = src3; + for (j = 0; j < (w/2); j++) { + dst3[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++; + } + src3 += srcPitch2; + } + break; + case RR_Rotate_180: + for (i = 0; i < (h/2); i++) { + s = src3; + for (j = 0; j < (w/2); j++) { + dst3[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++; + } + src3 += srcPitch2; + } + break; + case RR_Rotate_270: + for (i = 0; i < (h/2); i++) { + s = src3; + for (j = 0; j < (w/2); j++) { + dst3[((h/2) - i - 1) + (j * dstPitch)] = *s++; + } + src3 += srcPitch2; + } + break; } } @@ -1175,6 +1374,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); unsigned int swidth; unsigned int mask, shift, offsety, offsetu; + int tmp; ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, dstPitch); @@ -1182,7 +1382,159 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, if (!pPriv->overlayOK) return; - if (IS_I915G(pI830) || IS_I915GM(pI830)) { +#if VIDEO_DEBUG + CompareOverlay(pI830, (CARD32 *) overlay, 0x100); +#endif + + /* When in dual head with different bpp setups we need to refresh the + * color key, so let's reset the video parameters and refresh here */ +#if 0 + if (pI830->entityPrivate) +#endif + I830ResetVideo(pScrn); + + /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */ + if (!*pI830->overlayOn) + OVERLAY_UPDATE; + + switch (pI830->rotation) { + case RR_Rotate_0: + dstBox->x1 -= pScrn->frameX0; + dstBox->x2 -= pScrn->frameX0; + dstBox->y1 -= pScrn->frameY0; + dstBox->y2 -= pScrn->frameY0; + break; + case RR_Rotate_90: + tmp = dstBox->x1; + dstBox->x1 = dstBox->y1 - pScrn->frameX0; + dstBox->y1 = pScrn->virtualY - tmp - pScrn->frameY0; + tmp = dstBox->x2; + dstBox->x2 = dstBox->y2 - pScrn->frameX0; + dstBox->y2 = pScrn->virtualY - tmp - pScrn->frameY0; + tmp = dstBox->y1; + dstBox->y1 = dstBox->y2; + dstBox->y2 = tmp; + break; + case RR_Rotate_180: + tmp = dstBox->x1; + dstBox->x1 = pScrn->virtualX - dstBox->x2 - pScrn->frameX0; + dstBox->x2 = pScrn->virtualX - tmp - pScrn->frameX0; + tmp = dstBox->y1; + dstBox->y1 = pScrn->virtualY - dstBox->y2 - pScrn->frameY0; + dstBox->y2 = pScrn->virtualY - tmp - pScrn->frameY0; + break; + case RR_Rotate_270: + tmp = dstBox->x1; + dstBox->x1 = pScrn->virtualX - dstBox->y1 - pScrn->frameX0; + dstBox->y1 = tmp - pScrn->frameY0; + tmp = dstBox->x2; + dstBox->x2 = pScrn->virtualX - dstBox->y2 - pScrn->frameX0; + dstBox->y2 = tmp - pScrn->frameY0; + tmp = dstBox->x1; + dstBox->x1 = dstBox->x2; + dstBox->x2 = tmp; + break; + } + + /* Fix up the dstBox if outside the visible screen */ + { + int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0; + int offset_y = (dstBox->y1 < 0) ? -dstBox->y1 : 0; + int offset, offset2; + + /* align */ + offset_x = (offset_x + 3) & ~3; + offset_y = (offset_y + 3) & ~3; + + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + height -= offset_x; + width -= offset_y; + } else { + height -= offset_y; + width -= offset_x; + } + + if (id == FOURCC_I420 || id == FOURCC_YV12) { + offset = ((offset_x/2) + (dstPitch * offset_y)) * 2; + offset2 = ((offset_x/2) + ((dstPitch/2) * offset_y)); + } else { + offset = ((offset_x*2) + (dstPitch * offset_y)); + offset2 = ((offset_x*2) + ((dstPitch/2) * offset_y)); + } + + /* buffer locations */ + pPriv->YBuf0offset += offset; + pPriv->UBuf0offset += offset2; + pPriv->VBuf0offset += offset2; + + if(pPriv->doubleBuffer) { + pPriv->YBuf1offset += offset; + pPriv->UBuf1offset += offset2; + pPriv->VBuf1offset += offset2; + } + } + + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + tmp = width; + width = height; + height = tmp; + tmp = drw_w; + drw_w = drw_h; + drw_h = tmp; + tmp = src_w; + src_w = src_h; + src_h = tmp; + } + + if (pPriv->oneLineMode) { + /* change the coordinates with panel fitting active */ + dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1; + dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1; + + /* Now, alter the height, so we scale to the correct size */ + drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1; + } + + { + /* Keep the engine happy and clip to the real vertical size just + * in case an LFP is in use and it's not at it's native resolution. + */ + int vactive = pI830->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF); + + vactive += 1; + + if (dstBox->y1 < 0) dstBox->y1 = 0; + if (dstBox->y2 < 0) dstBox->y2 = 0; + if (dstBox->x1 < 0) dstBox->x1 = 0; + if (dstBox->x2 < 0) dstBox->x2 = 0; + if (dstBox->y1 > vactive) dstBox->y1 = vactive; + if (dstBox->y2 > vactive) dstBox->y2 = vactive; + if (dstBox->x1 > pScrn->currentMode->HDisplay) dstBox->x1 = pScrn->currentMode->HDisplay - 1; + if (dstBox->x2 > pScrn->currentMode->HDisplay) dstBox->x2 = pScrn->currentMode->HDisplay - 1; + + /* nothing do to */ + if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) { + ErrorF("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"); + return; + } + if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) { + ErrorF("NOTHING TO DO\n"); + return; + } + if ((dstBox->x2 - dstBox->x1) <= 2) { + ErrorF("NOTHING TO DO\n"); + return; + } + } + + if (IS_I9XX(pI830)) { shift = 6; mask = 0x3f; } else { @@ -1198,17 +1550,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, offsetu = pPriv->UBuf1offset; } -#if VIDEO_DEBUG - CompareOverlay(pI830, (CARD32 *) overlay, 0x100); -#endif - - /* When in dual head with different bpp setups we need to refresh the - * color key, so let's reset the video parameters and refresh here */ -#if 0 - if (pI830->entityPrivate) -#endif - I830ResetVideo(pScrn); - switch (id) { case FOURCC_YV12: case FOURCC_I420: @@ -1221,7 +1562,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth = ((offsety + width + mask) >> shift) - (offsety >> shift); - if (IS_I915G(pI830) || IS_I915GM(pI830)) + if (IS_I9XX(pI830)) swidth <<= 1; swidth -= 1; @@ -1233,7 +1574,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth = ((offsetu + (width / 2) + mask) >> shift) - (offsetu >> shift); - if (IS_I915G(pI830) || IS_I915GM(pI830)) + if (IS_I9XX(pI830)) swidth <<= 1; swidth -= 1; @@ -1257,7 +1598,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, swidth = ((offsety + (width << 1) + mask) >> shift) - (offsety >> shift); - if (IS_I915G(pI830) || IS_I915GM(pI830)) + if (IS_I9XX(pI830)) swidth <<= 1; swidth -= 1; @@ -1272,19 +1613,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, break; } - if (pPriv->oneLineMode) { - /* change the coordinates with panel fitting active */ - dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1; - dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1; - - /* Now, alter the height, so we scale to the correct size */ - drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1; - - /* Keep the engine happy */ - if (dstBox->y1 < 0) dstBox->y1 = 0; - if (dstBox->y2 < 0) dstBox->y2 = 0; - } - + overlay->OCMD = OVERLAY_ENABLE; overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1; @@ -1299,13 +1628,15 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, overlay->OBUF_0U = pPriv->UBuf0offset; overlay->OBUF_0V = pPriv->VBuf0offset; - overlay->OBUF_1Y = pPriv->YBuf1offset; - overlay->OBUF_1U = pPriv->UBuf1offset; - overlay->OBUF_1V = pPriv->VBuf1offset; + if(pPriv->doubleBuffer) { + overlay->OBUF_1Y = pPriv->YBuf1offset; + overlay->OBUF_1U = pPriv->UBuf1offset; + overlay->OBUF_1V = pPriv->VBuf1offset; + } - ErrorF("Buffers: Y0: 0x%08x, U0: 0x%08x, V0: 0x%08x\n", overlay->OBUF_0Y, + 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%08x, U1: 0x%08x, V1: 0x%08x\n", overlay->OBUF_1Y, + ErrorF("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n", overlay->OBUF_1Y, overlay->OBUF_1U, overlay->OBUF_1V); #if 0 @@ -1330,11 +1661,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, } #endif -#if 1 - overlay->OCMD = OVERLAY_ENABLE; -#endif - - ErrorF("pos: 0x%08x, size: 0x%08x\n", overlay->DWINPOS, overlay->DWINSZ); + 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); /* @@ -1383,6 +1710,18 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, ErrorF("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"); + return; + } + + /* shouldn't get here */ + if (xscaleIntUV > 7) { + ErrorF("xscaleUV: bad scale\n"); + return; + } + newval = (xscaleInt << 16) | ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20); if (newval != overlay->YRGBSCALE) { @@ -1480,7 +1819,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, else overlay->OCMD |= BUFFER1; - ErrorF("OCMD is 0x%08x\n", overlay->OCMD); + ErrorF("OCMD is 0x%lx\n", overlay->OCMD); OVERLAY_UPDATE; } @@ -1489,7 +1828,7 @@ static FBLinearPtr I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) { ScreenPtr pScreen; - FBLinearPtr new_linear; + FBLinearPtr new_linear = NULL; DPRINTF(PFX, "I830AllocateMemory\n"); @@ -1514,8 +1853,10 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME); - if (max_size < size) + if (max_size < size) { + ErrorF("No memory available\n"); return NULL; + } xf86PurgeUnlockedOffscreenAreas(pScreen); new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, @@ -1538,6 +1879,8 @@ I830PutImage(ScrnInfoPtr pScrn, I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = (I830PortPrivPtr) data; ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + I830OverlayRegPtr overlay = + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); INT32 x1, x2, y1, y2; int srcPitch, srcPitch2 = 0, dstPitch; int top, left, npixels, nlines, size, loops; @@ -1585,68 +1928,106 @@ I830PutImage(ScrnInfoPtr pScrn, width, height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; - switch (id) { case FOURCC_YV12: case FOURCC_I420: srcPitch = (width + 3) & ~3; srcPitch2 = ((width >> 1) + 3) & ~3; - dstPitch = ((width / 2) + 63) & ~63; /* of chroma */ - size = dstPitch * height * 3; +#if 1 + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + dstPitch = ((height / 2) + 63) & ~63; + size = dstPitch * width * 3; + } else { + dstPitch = ((width / 2) + 63) & ~63; /* of chroma */ + size = dstPitch * height * 3; + } +#else + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + dstPitch = ((height / 2) + 511) & ~511; + size = dstPitch * width * 3; + } else { + dstPitch = ((width / 2) + 511) & ~511; /* of chroma */ + size = dstPitch * height * 3; + } +#endif break; case FOURCC_UYVY: case FOURCC_YUY2: default: srcPitch = width << 1; - dstPitch = (srcPitch + 63) & ~63; /* of chroma */ - size = dstPitch * height; +#if 1 + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + dstPitch = ((height << 1) + 63) & ~63; + size = dstPitch * width; + } else { + dstPitch = ((width << 1) + 63) & ~63; /* of chroma */ + size = dstPitch * height; + } +#else + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + dstPitch = ((height << 1) + 511) & ~511; + size = dstPitch * width; + } else { + dstPitch = ((width << 1) + 511) & ~511; /* of chroma */ + size = dstPitch * height; + } +#endif break; } ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size); /* size is multiplied by 2 because we have two buffers that are flipping */ - if (!(pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, size * 2 / pI830->cpp))) + pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, + (pPriv->doubleBuffer ? size * 2 : size) / pI830->cpp); + + if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY)) return BadAlloc; /* fixup pointers */ - pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp; - pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); - pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2); - - pPriv->YBuf1offset = pPriv->YBuf0offset + size; - pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); - pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2); - - /* XXX We could potentially use MI_WAIT_FOR_OVERLAY here instead - * of this code....*/ + pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp; + if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); + pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2); + if(pPriv->doubleBuffer) { + pPriv->YBuf1offset = pPriv->YBuf0offset + size; + pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * width); + pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * width / 2); + } + } else { + pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); + pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2); + if(pPriv->doubleBuffer) { + pPriv->YBuf1offset = pPriv->YBuf0offset + size; + pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); + pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2); + } + } /* Make sure this buffer isn't in use */ loops = 0; - while (loops < 1000000) { + if (*pI830->overlayOn && pPriv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) { + while (loops < 1000000) { #if USE_USLEEP_FOR_VIDEO - usleep(10); + usleep(10); #endif - if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) { - break; + if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) { + break; + } + loops++; } - loops++; - } - if (loops >= 1000000) { - ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf); + if (loops >= 1000000) { + ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf); #if 0 - pPriv->currentBuf = !pPriv->currentBuf; + pPriv->currentBuf = !pPriv->currentBuf; #endif - } + } - /* buffer swap */ - if (pPriv->currentBuf == 0) - pPriv->currentBuf = 1; - else - pPriv->currentBuf = 0; + /* buffer swap */ + if (pPriv->currentBuf == 0) + pPriv->currentBuf = 1; + else + pPriv->currentBuf = 0; + } /* copy data */ top = y1 >> 16; @@ -1690,14 +2071,22 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, unsigned short *w, unsigned short *h, int *pitches, int *offsets) { + I830Ptr pI830 = I830PTR(pScrn); int size, tmp; - DPRINTF(PFX, "I830QueryImageAttributes: w is %d, h is %d\n", *w, *h); + ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h); + if (IS_845G(pI830) || IS_I830(pI830)) { + if (*w > IMAGE_MAX_WIDTH_LEGACY) + *w = IMAGE_MAX_WIDTH_LEGACY; + if (*h > IMAGE_MAX_HEIGHT_LEGACY) + *h = IMAGE_MAX_HEIGHT_LEGACY; + } else { if (*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; if (*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; + } *w = (*w + 1) & ~1; if (offsets) @@ -1767,24 +2156,25 @@ I830BlockHandler(int i, pScreen->BlockHandler = I830BlockHandler; if (pPriv->videoStatus & TIMER_MASK) { - UpdateCurrentTime(); + Time now = currentTime.milliseconds; if (pPriv->videoStatus & OFF_TIMER) { - if (pPriv->offTime < currentTime.milliseconds) { + if (pPriv->offTime < now) { /* Turn off the overlay */ + ErrorF("BLOCKHANDLER\n"); overlay->OCMD &= ~OVERLAY_ENABLE; - - OVERLAY_UPDATE; - - OVERLAY_OFF; + OVERLAY_UPDATE; +#if 1 + OVERLAY_OFF; +#endif pPriv->videoStatus = FREE_TIMER; - pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + pPriv->freeTime = now + FREE_DELAY; if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; } } else { /* FREE_TIMER */ - if (pPriv->freeTime < currentTime.milliseconds) { + if (pPriv->freeTime < now) { if (pPriv->linear) { xf86FreeOffscreenLinear(pPriv->linear); pPriv->linear = NULL; @@ -1815,9 +2205,18 @@ I830AllocateSurface(ScrnInfoPtr pScrn, OffscreenPrivPtr pPriv; I830Ptr pI830 = I830PTR(pScrn); - DPRINTF(PFX, "I830AllocateSurface\n"); + ErrorF("I830AllocateSurface\n"); + + if (IS_845G(pI830) || IS_I830(pI830)) { + if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY)) + return BadAlloc; + } else { + if ((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT)) + return BadAlloc; + } - if ((w > 1024) || (h > 1024)) + /* What to do when rotated ?? */ + if (pI830->rotation != RR_Rotate_0) return BadAlloc; w = (w + 1) & ~1; @@ -1857,7 +2256,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn, surface->offsets[0] = linear->offset * bpp; surface->devPrivate.ptr = (pointer) pPriv; - memset(pI830->FbBase + pScrn->fbOffset + surface->offsets[0], 0, size); + memset(pI830->FbBase + pI830->FrontBuffer.Start + surface->offsets[0], 0, size); return Success; } @@ -1874,11 +2273,12 @@ I830StopSurface(XF86SurfacePtr surface) I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + ErrorF("StopSurface\n"); overlay->OCMD &= ~OVERLAY_ENABLE; - OVERLAY_UPDATE; - +#if 1 OVERLAY_OFF; +#endif if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; @@ -1929,11 +2329,13 @@ I830DisplaySurface(XF86SurfacePtr surface, ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn); + I830OverlayRegPtr overlay = + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); INT32 x1, y1, x2, y2; INT32 loops = 0; BoxRec dstBox; - DPRINTF(PFX, "I830DisplaySurface\n"); + ErrorF("I830DisplaySurface\n"); if (pI830->entityPrivate) { if (pI830->entityPrivate->XvInUse != -1 && @@ -1965,35 +2367,35 @@ I830DisplaySurface(XF86SurfacePtr surface, surface->width, surface->height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; - /* fixup pointers */ pI830Priv->YBuf0offset = surface->offsets[0]; pI830Priv->YBuf1offset = pI830Priv->YBuf0offset; - /* XXX We could potentially use MI_WAIT_FOR_OVERLAY here instead - * of this code....*/ - - /* wait for the last rendered buffer to be flipped in */ - while (((INREG(DOVSTA) & OC_BUF) >> 20) != pI830Priv->currentBuf) { + /* Make sure this buffer isn't in use */ + loops = 0; + if (*pI830->overlayOn && pI830Priv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) { + while (loops < 1000000) { #if USE_USLEEP_FOR_VIDEO - usleep(10); + usleep(10); +#endif + if (((INREG(DOVSTA) & OC_BUF) >> 20) == pI830Priv->currentBuf) { + break; + } + loops++; + } + if (loops >= 1000000) { + ErrorF("loops (1) maxed out for buffer %d\n", pI830Priv->currentBuf); +#if 0 + pI830Priv->currentBuf = !pI830Priv->currentBuf; #endif - if (loops == 200000) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n"); - break; } - loops++; - } - /* buffer swap */ - if (pI830Priv->currentBuf == 0) - pI830Priv->currentBuf = 1; - else - pI830Priv->currentBuf = 0; + /* buffer swap */ + if (pI830Priv->currentBuf == 0) + pI830Priv->currentBuf = 1; + else + pI830Priv->currentBuf = 0; + } I830DisplayVideo(pScrn, surface->id, surface->width, surface->height, surface->pitches[0], x1, y1, x2, y2, &dstBox, @@ -2018,6 +2420,8 @@ static void I830InitOffscreenImages(ScreenPtr pScreen) { XF86OffscreenImagePtr offscreenImages; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); /* need to free this someplace */ if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) { @@ -2025,15 +2429,20 @@ I830InitOffscreenImages(ScreenPtr pScreen) } offscreenImages[0].image = &Images[0]; - offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/; offscreenImages[0].alloc_surface = I830AllocateSurface; offscreenImages[0].free_surface = I830FreeSurface; offscreenImages[0].display = I830DisplaySurface; offscreenImages[0].stop = I830StopSurface; offscreenImages[0].setAttribute = I830SetSurfaceAttribute; offscreenImages[0].getAttribute = I830GetSurfaceAttribute; - offscreenImages[0].max_width = 1024; - offscreenImages[0].max_height = 1024; + if (IS_845G(pI830) || IS_I830(pI830)) { + offscreenImages[0].max_width = IMAGE_MAX_WIDTH_LEGACY; + offscreenImages[0].max_height = IMAGE_MAX_HEIGHT_LEGACY; + } else { + offscreenImages[0].max_width = IMAGE_MAX_WIDTH; + offscreenImages[0].max_height = IMAGE_MAX_HEIGHT; + } offscreenImages[0].num_attributes = 1; offscreenImages[0].attributes = Attributes; @@ -2043,9 +2452,10 @@ I830InitOffscreenImages(ScreenPtr pScreen) void I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode) { + I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv; - if (!I830PTR(pScrn)->adaptor) { + if (!pI830->adaptor) { return; } @@ -2062,6 +2472,8 @@ I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode) */ I830StopVideo(pScrn, pPriv, TRUE); + pPriv->overlayOK = FALSE; + pPriv->oneLineMode = FALSE; } @@ -2079,6 +2491,17 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) if (!pPriv) return; + pPriv->overlayOK = TRUE; + + /* ensure pipe is updated on mode switch */ + if (!pI830->Clone) { + if (pPriv->pipe != pI830->pipe) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Changing XVideo pipe (%d to %d).\n", pPriv->pipe, pI830->pipe); + pPriv->pipe = pI830->pipe; + } + } + if (pPriv->pipe == 0) { if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, |