diff options
author | Eric Anholt <anholt@FreeBSD.org> | 2006-05-15 17:04:27 -0700 |
---|---|---|
committer | Eric Anholt <anholt@FreeBSD.org> | 2006-05-16 10:10:32 -0700 |
commit | c9be11459bc2198b435c97c5a3432425246c4d2d (patch) | |
tree | 1176afc28e26cbe83b73c7c3db865ba7547f6994 | |
parent | f268979a0c779641c84e8d5b763acbda131474cf (diff) |
Enable overlay and/or textured video at runtime according to hardware
capabilities. Sets up 16 textured-video ports. Left in one hack (disconnected
but advertised BRIGHTNESS and CONTRAST atoms) which may actually not be
necessary.
-rw-r--r-- | src/i830_video.c | 298 |
1 files changed, 215 insertions, 83 deletions
diff --git a/src/i830_video.c b/src/i830_video.c index d23e83cb..a3cbfafd 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -84,8 +84,6 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dixstruct.h" #include "fourcc.h" -#define USE_TEXTURED_VIDEO - #ifndef USE_USLEEP_FOR_VIDEO #define USE_USLEEP_FOR_VIDEO 0 #endif @@ -101,7 +99,8 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. static void I830InitOffscreenImages(ScreenPtr); -static XF86VideoAdaptorPtr I830SetupImageVideo(ScreenPtr); +static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr); +static XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr); static void I830StopVideo(ScrnInfoPtr, pointer, Bool); static int I830SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); static int I830GetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); @@ -111,8 +110,10 @@ static void I830QueryBestSize(ScrnInfoPtr, Bool, static int I830PutImage(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char *, short, short, Bool, RegionPtr, pointer, DrawablePtr); -static int I830QueryImageAttributes(ScrnInfoPtr, int, unsigned short *, - unsigned short *, int *, int *); +static int I830QueryImageAttributesOverlay(ScrnInfoPtr, int, unsigned short *, + unsigned short *, int *, int *); +static int I830QueryImageAttributesTextured(ScrnInfoPtr, int, unsigned short *, + unsigned short *, int *, int *); static void I830BlockHandler(int, pointer, pointer, pointer); @@ -288,6 +289,12 @@ static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"} }; +#define NUM_TEXTURED_ATTRIBUTES 2 +static XF86AttributeRec TexturedAttributes[NUM_ATTRIBUTES] = { + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, +}; + #define GAMMA_ATTRIBUTES 6 static XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"}, @@ -396,6 +403,7 @@ typedef struct { Bool overlayOK; int oneLineMode; int scaleRatio; + Bool textured; } I830PortPrivRec, *I830PortPrivPtr; #define GET_PORT_PRIVATE(pScrn) \ @@ -426,8 +434,9 @@ void I830InitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; - XF86VideoAdaptorPtr newAdaptor = NULL; + XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; int num_adaptors; DPRINTF(PFX, "I830InitVideo\n"); @@ -446,35 +455,54 @@ I830InitVideo(ScreenPtr pScreen) } #endif + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + /* Give our adaptor list enough space for the overlay and/or texture video + * adaptors. + */ + newAdaptors = xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); + if (newAdaptors == NULL) + return; + + memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); + adaptors = newAdaptors; + + /* Add the adaptors supported by our hardware. First, set up the atoms + * that will be used by both output adaptors. + */ + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + + /* Set up overlay video if we can do it at this depth. */ if (pScrn->bitsPerPixel != 8) { - newAdaptor = I830SetupImageVideo(pScreen); + overlayAdaptor = I830SetupImageVideoOverlay(pScreen); + if (overlayAdaptor != NULL) { + adaptors[num_adaptors++] = overlayAdaptor; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to set up overlay video\n"); + } I830InitOffscreenImages(pScreen); } - num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); - - if (newAdaptor) { - if (!num_adaptors) { - num_adaptors = 1; - adaptors = &newAdaptor; + /* Set up textured video if we can do it at this depth and we are on + * supported hardware. + */ + if (pScrn->bitsPerPixel >= 16 && IS_I9XX(pI830)) { + texturedAdaptor = I830SetupImageVideoTextured(pScreen); + if (texturedAdaptor != NULL) { + adaptors[num_adaptors++] = texturedAdaptor; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n"); } else { - newAdaptors = /* need to free this someplace */ - xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *)); - if (newAdaptors) { - memcpy(newAdaptors, adaptors, num_adaptors * - sizeof(XF86VideoAdaptorPtr)); - newAdaptors[num_adaptors] = newAdaptor; - adaptors = newAdaptors; - num_adaptors++; - } + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to set up textured video\n"); } } if (num_adaptors) xf86XVScreenInit(pScreen, adaptors, num_adaptors); - if (newAdaptors) - xfree(newAdaptors); + xfree(adaptors); } static void @@ -644,7 +672,7 @@ I830UpdateGamma(ScrnInfoPtr pScrn) } static XF86VideoAdaptorPtr -I830SetupImageVideo(ScreenPtr pScreen) +I830SetupImageVideoOverlay(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); @@ -652,7 +680,7 @@ I830SetupImageVideo(ScreenPtr pScreen) I830PortPrivPtr pPriv; XF86AttributePtr att; - DPRINTF(PFX, "I830SetupImageVideo\n"); + DPRINTF(PFX, "I830SetupImageVideoOverlay\n"); if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(I830PortPrivRec) + sizeof(DevUnion)))) @@ -705,8 +733,9 @@ I830SetupImageVideo(ScreenPtr pScreen) adapt->GetPortAttribute = I830GetPortAttribute; adapt->QueryBestSize = I830QueryBestSize; adapt->PutImage = I830PutImage; - adapt->QueryImageAttributes = I830QueryImageAttributes; + adapt->QueryImageAttributes = I830QueryImageAttributesOverlay; + pPriv->textured = FALSE; pPriv->colorKey = pI830->colorKey & ((1 << pScrn->depth) - 1); pPriv->videoStatus = 0; pPriv->brightness = 0; @@ -744,8 +773,6 @@ I830SetupImageVideo(ScreenPtr pScreen) pScreen->BlockHandler = I830BlockHandler; xvColorKey = MAKE_ATOM("XV_COLORKEY"); - xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); - xvContrast = MAKE_ATOM("XV_CONTRAST"); xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); /* Allow the pipe to be switched from pipe A to B when in clone mode */ @@ -768,6 +795,86 @@ I830SetupImageVideo(ScreenPtr pScreen) return adapt; } +static XF86VideoAdaptorPtr +I830SetupImageVideoTextured(ScreenPtr pScreen) +{ + XF86VideoAdaptorPtr adapt; + XF86VideoEncodingPtr encoding; + XF86AttributePtr attrs; + I830PortPrivPtr portPrivs; + DevUnion *devUnions; + int nports = 16, i; + int nAttributes; + + DPRINTF(PFX, "I830SetupImageVideoOverlay\n"); + + nAttributes = NUM_TEXTURED_ATTRIBUTES; + + adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec)); + portPrivs = xcalloc(nports, sizeof(I830PortPrivRec)); + devUnions = xcalloc(nports, sizeof(DevUnion)); + encoding = xcalloc(1, sizeof(XF86VideoEncodingRec)); + attrs = xcalloc(nAttributes, sizeof(XF86AttributeRec)); + if (adapt == NULL || portPrivs == NULL || devUnions == NULL || + encoding == NULL || attrs == NULL) + { + xfree(adapt); + xfree(portPrivs); + xfree(devUnions); + xfree(encoding); + xfree(attrs); + return NULL; + } + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = 0; + adapt->name = "Intel(R) Textured Video"; + adapt->nEncodings = 1; + adapt->pEncodings = encoding; + adapt->pEncodings[0].id = 0; + adapt->pEncodings[0].name = "XV_IMAGE"; + adapt->pEncodings[0].width = 2048; + adapt->pEncodings[0].height = 2048; + adapt->pEncodings[0].rate.numerator = 1; + adapt->pEncodings[0].rate.denominator = 1; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = nports; + adapt->pPortPrivates = devUnions; + adapt->nAttributes = nAttributes; + adapt->pAttributes = attrs; + memcpy(attrs, TexturedAttributes, nAttributes * sizeof(XF86AttributeRec)); + adapt->nImages = NUM_IMAGES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = I830StopVideo; + adapt->SetPortAttribute = I830SetPortAttribute; + adapt->GetPortAttribute = I830GetPortAttribute; + adapt->QueryBestSize = I830QueryBestSize; + adapt->PutImage = I830PutImage; + adapt->QueryImageAttributes = I830QueryImageAttributesTextured; + + for (i = 0; i < nports; i++) { + I830PortPrivPtr pPriv = &portPrivs[i]; + + pPriv->textured = TRUE; + pPriv->videoStatus = 0; + pPriv->linear = NULL; + pPriv->currentBuf = 0; + pPriv->doubleBuffer = 1; + + /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */ + REGION_NULL(pScreen, &pPriv->clip); + + adapt->pPortPrivates[i].ptr = (pointer) (pPriv); + } + + return adapt; +} + static Bool RegionsEqual(RegionPtr A, RegionPtr B) { @@ -805,6 +912,9 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + if (pPriv->textured) + return; + DPRINTF(PFX, "I830StopVideo\n"); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); @@ -844,6 +954,14 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + if (pPriv->textured) { + /* XXX: Currently the brightness/saturation attributes aren't hooked up. + * However, apps expect them to be there, and the spec seems to let us + * sneak out of actually implementing them for now. + */ + return Success; + } + if (attribute == xvBrightness) { if ((value < -128) || (value > 127)) return BadValue; @@ -996,13 +1114,12 @@ I830QueryBestSize(ScrnInfoPtr pScrn, } static void -I830CopyPackedData(ScrnInfoPtr pScrn, +I830CopyPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, unsigned char *buf, int srcPitch, int dstPitch, int top, int left, int h, int w) { I830Ptr pI830 = I830PTR(pScrn); - I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; unsigned char *src, *dst; int i,j; unsigned char *s; @@ -1093,12 +1210,12 @@ I830CopyPackedData(ScrnInfoPtr pScrn, /* Copies planar data in *buf to UYVY-packed data in the screen atYBufXOffset. */ static void -I830CopyPlanarToPackedData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, +I830CopyPlanarToPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, + unsigned char *buf, int srcPitch, int srcPitch2, int dstPitch, int srcH, int top, int left, int h, int w, int id) { I830Ptr pI830 = I830PTR(pScrn); - I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; CARD8 *dst1, *srcy, *srcu, *srcv; int y; @@ -1150,12 +1267,12 @@ I830CopyPlanarToPackedData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, } static void -I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, +I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, + unsigned char *buf, int srcPitch, int srcPitch2, int dstPitch, int srcH, int top, int left, int h, int w, int id) { I830Ptr pI830 = I830PTR(pScrn); - I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; int i, j = 0; unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3; unsigned char *s; @@ -2046,7 +2163,6 @@ do { \ (SRC_W << A2_SRC1_CHANNEL_W_SHIFT)); \ } while (0) -#ifdef USE_TEXTURED_VIDEO static void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, RegionPtr dstRegion, @@ -2455,7 +2571,6 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, ADVANCE_LP_RING(); } } -#endif /* USE_TEXTURED_VIDEO */ static FBLinearPtr I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) @@ -2529,7 +2644,7 @@ I830PutImage(ScrnInfoPtr pScrn, I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); INT32 x1, x2, y1, y2; - int srcPitch, srcPitch2 = 0, dstPitch; + int srcPitch, srcPitch2 = 0, dstPitch, destId; int top, left, npixels, nlines, size, loops; BoxRec dstBox; @@ -2575,11 +2690,15 @@ I830PutImage(ScrnInfoPtr pScrn, width, height)) return Success; + destId = id; switch (id) { case FOURCC_YV12: case FOURCC_I420: srcPitch = (width + 3) & ~3; srcPitch2 = ((width >> 1) + 3) & ~3; + if (pPriv->textured) { + destId = FOURCC_YUY2; + } break; case FOURCC_UYVY: case FOURCC_YUY2: @@ -2588,8 +2707,7 @@ I830PutImage(ScrnInfoPtr pScrn, break; } - switch (id) { -#ifndef USE_TEXTURED_VIDEO + switch (destId) { case FOURCC_YV12: case FOURCC_I420: #if 1 @@ -2610,13 +2728,6 @@ I830PutImage(ScrnInfoPtr pScrn, } #endif break; -#else /* USE_TEXTURED_VIDEO */ - case FOURCC_YV12: - case FOURCC_I420: - /* If we're doing textured video, then we're going to pack the data as - * UYVY in framebuffer, so allocate and align the memory that way. - */ -#endif case FOURCC_UYVY: case FOURCC_YUY2: default: @@ -2670,7 +2781,9 @@ I830PutImage(ScrnInfoPtr pScrn, /* Make sure this buffer isn't in use */ loops = 0; - if (*pI830->overlayOn && pPriv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) { + if (!pPriv->textured && *pI830->overlayOn && pPriv->doubleBuffer && + (overlay->OCMD & OVERLAY_ENABLE)) + { while (loops < 1000000) { #if USE_USLEEP_FOR_VIDEO usleep(10); @@ -2704,39 +2817,38 @@ I830PutImage(ScrnInfoPtr pScrn, case FOURCC_I420: top &= ~1; nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; -#ifdef USE_TEXTURED_VIDEO - I830CopyPlanarToPackedData(pScrn, buf, srcPitch, srcPitch2, dstPitch, - height, top, left, nlines, npixels, id); - /* Our data is now in this forat, either way. */ - id = FOURCC_YUY2; -#else - I830CopyPlanarData(pScrn, buf, srcPitch, srcPitch2, dstPitch, height, top, left, - nlines, npixels, id); -#endif + if (pPriv->textured) { + I830CopyPlanarToPackedData(pScrn, pPriv, buf, srcPitch, srcPitch2, + dstPitch, height, top, left, nlines, + npixels, id); + } else { + I830CopyPlanarData(pScrn, pPriv, buf, srcPitch, srcPitch2, dstPitch, + height, top, left, nlines, npixels, id); + } break; case FOURCC_UYVY: case FOURCC_YUY2: default: nlines = ((y2 + 0xffff) >> 16) - top; - I830CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines, - npixels); + I830CopyPackedData(pScrn, pPriv, buf, srcPitch, dstPitch, top, left, + nlines, npixels); break; } -#ifndef USE_TEXTURED_VIDEO - /* update cliplist */ - if (!RegionsEqual(&pPriv->clip, clipBoxes)) { - REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); - xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes); - } + if (!pPriv->textured) { + /* update cliplist */ + if (!RegionsEqual(&pPriv->clip, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); + xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes); + } - I830DisplayVideo(pScrn, id, width, height, dstPitch, - x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); -#else - I915DisplayVideoTextured(pScrn, pPriv, id, clipBoxes, width, height, - dstPitch, - x1, y1, x2, y2, src_w, src_h, drw_w, drw_h, pDraw); -#endif + I830DisplayVideo(pScrn, destId, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); + } else { + I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, + dstPitch, x1, y1, x2, y2, + src_w, src_h, drw_w, drw_h, pDraw); + } pPriv->videoStatus = CLIENT_VIDEO_ON; return Success; @@ -2746,23 +2858,25 @@ static int I830QueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, - int *pitches, int *offsets) + int *pitches, int *offsets, Bool textured) { I830Ptr pI830 = I830PTR(pScrn); int size, tmp; 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; + if (!textured) { + 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; @@ -2815,6 +2929,24 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, return size; } +static int +I830QueryImageAttributesOverlay(ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ + return I830QueryImageAttributes(pScrn, id, w, h, pitches, offsets, FALSE); +} + +static int +I830QueryImageAttributesTextured(ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ + return I830QueryImageAttributes(pScrn, id, w, h, pitches, offsets, TRUE); +} + static void I830BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) |