From: Rob Clark <r...@ti.com> TODO: + format advertised as I420 appears to actually be NV12 + add non-fourcc format values for hw decode directly to VRAM mapped buffer (skip GART->VRAM move) + CSC_MATRIX and OSD support.. --- src/nouveau_dri2.c | 214 ++++++++++++++++++++++++++++----- src/nouveau_xv.c | 324 +++++++++++++++++++++++++++++++++++++++---------- src/nv30_xv_tex.c | 4 +- src/nv40_xv_tex.c | 4 +- src/nv50_xv.c | 2 +- src/nv_accel_common.c | 11 ++ src/nv_type.h | 1 + src/nvc0_xv.c | 2 +- 8 files changed, 459 insertions(+), 103 deletions(-)
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index d14443f..445cd52 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -10,6 +10,10 @@ #include "dri2.h" #endif +// put these somewhere common.. +#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )) +#define FOURCC_STR(str) FOURCC(str[0], str[1], str[2], str[3]) + #if defined(DRI2) && DRI2INFOREC_VERSION >= 3 struct nouveau_dri2_buffer { DRI2BufferRec base; @@ -22,19 +26,87 @@ nouveau_dri2_buffer(DRI2BufferPtr buf) return (struct nouveau_dri2_buffer *)buf; } -DRI2BufferPtr -nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, - unsigned int format) +static DRI2BufferPtr +nouveau_dri2_create_buffer_2(DrawablePtr pDraw, unsigned int attachment, + unsigned int format, PixmapPtr ppix) { ScreenPtr pScreen = pDraw->pScreen; NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]); - struct nouveau_dri2_buffer *nvbuf; struct nouveau_pixmap *nvpix; - PixmapPtr ppix; + struct nouveau_dri2_buffer *nvbuf; nvbuf = calloc(1, sizeof(*nvbuf)); - if (!nvbuf) + if (!nvbuf) { + // XXX cleanup.. + return NULL; + } + + pNv->exa_force_cp = TRUE; + exaMoveInPixmap(ppix); + pNv->exa_force_cp = FALSE; + + nvbuf->base.attachment = attachment; + nvbuf->base.pitch = ppix->devKind; + nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8; + nvbuf->base.driverPrivate = nvbuf; + nvbuf->base.format = format; + nvbuf->base.flags = 0; + nvbuf->ppix = ppix; + + nvpix = nouveau_pixmap(ppix); + if (!nvpix || !nvpix->bo || + nouveau_bo_handle_get(nvpix->bo, &nvbuf->base.name)) { + pScreen->DestroyPixmap(nvbuf->ppix); + free(nvbuf); return NULL; + } + + return &nvbuf->base; + +} + +static DRI2BufferPtr +nouveau_dri2_create_buffer_vid(DrawablePtr pDraw, unsigned int attachment, + unsigned int format, unsigned int width, unsigned int height) +{ + ScreenPtr pScreen = pDraw->pScreen; + PixmapPtr ppix; + int bpp; + + switch(format) { + case FOURCC('I','4','2','0'): + case FOURCC('Y','V','1','2'): + /* to avoid confusing CreatePixmap too much, call these 1cpp + * and 1.5x height + */ + bpp = 8; + height = ((height + 1) & ~1) * 3 / 2; + break; + case FOURCC('Y','U','Y','2'): + case FOURCC('U','Y','V','Y'): + bpp = 16; + break; + case FOURCC('R','G','B','3'): /* depth=24, bpp=32 */ + case 24: + case FOURCC('R','G','B','4'): /* depth=32, bpp=32 */ + case 32: + bpp = 32; + break; + default: + return NULL; + } + + ppix = pScreen->CreatePixmap(pScreen, width, height, bpp, NOUVEAU_CREATE_PIXMAP_VIDEO); + + return nouveau_dri2_create_buffer_2(pDraw, attachment, format, ppix); +} + +DRI2BufferPtr +nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, + unsigned int format) +{ + ScreenPtr pScreen = pDraw->pScreen; + PixmapPtr ppix; if (attachment == DRI2BufferFrontLeft) { if (pDraw->type == DRAWABLE_PIXMAP) { @@ -59,27 +131,7 @@ nouveau_dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, usage_hint); } - pNv->exa_force_cp = TRUE; - exaMoveInPixmap(ppix); - pNv->exa_force_cp = FALSE; - - nvbuf->base.attachment = attachment; - nvbuf->base.pitch = ppix->devKind; - nvbuf->base.cpp = ppix->drawable.bitsPerPixel / 8; - nvbuf->base.driverPrivate = nvbuf; - nvbuf->base.format = format; - nvbuf->base.flags = 0; - nvbuf->ppix = ppix; - - nvpix = nouveau_pixmap(ppix); - if (!nvpix || !nvpix->bo || - nouveau_bo_handle_get(nvpix->bo, &nvbuf->base.name)) { - pScreen->DestroyPixmap(nvbuf->ppix); - free(nvbuf); - return NULL; - } - - return &nvbuf->base; + return nouveau_dri2_create_buffer_2(pDraw, attachment, format, ppix); } void @@ -95,6 +147,13 @@ nouveau_dri2_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buf) free(nvbuf); } +/* moveme: */ +int +nouveau_put_texture_image(DrawablePtr pDraw, PixmapPtr srcPix, int id, + short src_x, short src_y, short drw_x, short drw_y, + short src_w, short src_h, short drw_w, short drw_h, + short width, short height); + void nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) @@ -332,6 +391,49 @@ fail: } static Bool +nouveau_dri2_schedule_swap_vid(ClientPtr client, DrawablePtr draw, + DRI2BufferPtr dst, DRI2BufferPtr src, + BoxPtr b, DrawablePtr osd, + CARD64 *target_msc, CARD64 divisor, CARD64 remainder, + DRI2SwapEventPtr func, void *data) +{ + ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum]; + PixmapPtr src_pix = nouveau_dri2_buffer(src)->ppix; + short width, height; + int ret; + + width = src_pix->drawable.width; + height = src_pix->drawable.height; + + if (src->format == FOURCC_STR("I420") || + src->format == FOURCC_STR("YV12")) { + /* undo the 'height *= 1.5' trick to recover real height */ + height = (height * 2) / 3; + } + + /* attempt to hijack some of the XV USE_TEXTURE code.. maybe not the + * cleanest way, or even work on all cards, but just for proof of concept.. + * + * XXX this probably won't work for RGB formats, at least not on all + * chipset versions (like NV50).. probably want to use the CopyRegion + * code path (or something similar?) for RGB?? + */ + ret = nouveau_put_texture_image(draw, src_pix, src->format, + b->x1, b->y1, draw->x, draw->y, + b->x2 - b->x1, b->y2 - b->y1, draw->width, draw->height, + width, height); + + if (ret != Success) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, "blit failed: %d\n", ret); + return FALSE; + } + + DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); + + return TRUE; +} + +static Bool nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw, CARD64 target_msc, CARD64 divisor, CARD64 remainder) { @@ -396,6 +498,37 @@ nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) return TRUE; } +#define ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static int +nouveau_set_attribute(DrawablePtr pDraw, Atom attribute, + int len, const CARD32 *val) +{ + /* just for testing.. bogus colorspace conversion matrix.. */ + if (attribute == ATOM("XV_CSC_MATRIX")) { + return Success; + } + return BadMatch; +} + +static int +nouveau_get_attribute(DrawablePtr pDraw, Atom attribute, + int *len, const CARD32 **val) +{ + /* just for testing.. bogus colorspace conversion matrix.. */ + if (attribute == ATOM("XV_CSC_MATRIX")) { + static const CARD32 csc[] = { + 0x00, 0x01, 0x02, 0x03, + 0x10, 0x11, 0x12, 0x13, + 0x20, 0x21, 0x22, 0x23, + }; + *val = csc; + *len = sizeof(csc) / 4; + return Success; + } + return BadMatch; +} + void nouveau_dri2_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, @@ -428,28 +561,47 @@ nouveau_dri2_init(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); DRI2InfoRec dri2 = { 0 }; - const char *drivernames[2][2] = { - { "nouveau", "nouveau" }, - { "nouveau_vieux", "nouveau_vieux" } + const char *drivernames[2][3] = { + { "nouveau", "nouveau", "nouveau" }, + { "nouveau_vieux", "nouveau_vieux", NULL } + }; + const unsigned int formats[] = { + FOURCC_STR("YUY2"), + FOURCC_STR("YV12"), + FOURCC_STR("UYVY"), + FOURCC_STR("I420"), + FOURCC_STR("RGB3"), /* depth=24, bpp=32 */ + FOURCC_STR("RGB4"), /* depth=32, bpp=32 */ + /* non-common formats: */ + // XXX check what might have been passed by mesa!! + 24, + 32, }; if (pNv->Architecture >= NV_ARCH_30) dri2.driverNames = drivernames[0]; else dri2.driverNames = drivernames[1]; - dri2.numDrivers = 2; + dri2.numDrivers = 3; dri2.driverName = dri2.driverNames[0]; + dri2.numFormats = ARRAY_SIZE(formats); + dri2.formats = formats; + dri2.fd = nouveau_device(pNv->dev)->fd; dri2.deviceName = pNv->drm_device_name; dri2.version = DRI2INFOREC_VERSION; dri2.CreateBuffer = nouveau_dri2_create_buffer; + dri2.CreateBufferVid = nouveau_dri2_create_buffer_vid; dri2.DestroyBuffer = nouveau_dri2_destroy_buffer; dri2.CopyRegion = nouveau_dri2_copy_region; dri2.ScheduleSwap = nouveau_dri2_schedule_swap; + dri2.ScheduleSwapVid = nouveau_dri2_schedule_swap_vid; dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait; dri2.GetMSC = nouveau_dri2_get_msc; + dri2.SetAttribute = nouveau_set_attribute; + dri2.GetAttribute = nouveau_get_attribute; return DRI2ScreenInit(pScreen, &dri2); } diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c index 5a5337c..2733a2c 100644 --- a/src/nouveau_xv.c +++ b/src/nouveau_xv.c @@ -561,6 +561,10 @@ NVCopyNV12ColorPlanes(unsigned char *src1, unsigned char *src2, } +// put these somewhere common.. +#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )) +#define FOURCC_STR(str) FOURCC(str[0], str[1], str[2], str[3]) + static int NV_set_dimensions(ScrnInfoPtr pScrn, int action_flags, INT32 *xa, INT32 *xb, INT32 *ya, INT32 *yb, short *src_x, short *src_y, @@ -887,6 +891,87 @@ NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, } } +/* move from GART -> VRAM */ +static int +nouveau_xv_m2mf(ScrnInfoPtr pScrn, int action_flags, + struct nouveau_bo *src /* GART buffer */, + struct nouveau_bo *dst /* VRAM buffer */, + int offset, int uv_offset, int nlines, int line_len, int dstPitch) +{ + NVPtr pNv = NVPTR(pScrn); + struct nouveau_channel *chan = pNv->chan; + struct nouveau_grobj *m2mf = pNv->NvMemFormat; + + if (pNv->Architecture >= NV_ARCH_C0) { + nvc0_xv_m2mf(m2mf, dst, uv_offset, dstPitch, + nlines, src, line_len); + return Success; + } + + if (MARK_RING(chan, 64, 4)) + return BadAlloc; + + BEGIN_RING(chan, m2mf, + NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); + OUT_RING (chan, pNv->chan->gart->handle); + OUT_RING (chan, pNv->chan->vram->handle); + + if (pNv->Architecture >= NV_ARCH_50) { + BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1); + OUT_RING (chan, 1); + + BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 7); + OUT_RING (chan, 0); + OUT_RING (chan, src->tile_mode << 4); + OUT_RING (chan, dstPitch); + OUT_RING (chan, nlines); + OUT_RING (chan, 1); + OUT_RING (chan, 0); + OUT_RING (chan, 0); + } + + /* DMA to VRAM */ + if ( (action_flags & IS_YV12) && + !(action_flags & CONVERT_TO_YUY2)) { + /* we start the color plane transfer separately */ + + BEGIN_RING(chan, m2mf, + NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + if (OUT_RELOCl(chan, src, + line_len * nlines, + NOUVEAU_BO_GART | NOUVEAU_BO_RD) || + OUT_RELOCl(chan, dst, + offset + uv_offset, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { + MARK_UNDO(chan); + return BadAlloc; + } + OUT_RING (chan, line_len); + OUT_RING (chan, dstPitch); + OUT_RING (chan, line_len); + OUT_RING (chan, (nlines >> 1)); + OUT_RING (chan, (1<<8)|1); + OUT_RING (chan, 0); + } + + BEGIN_RING(chan, m2mf, + NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + if (OUT_RELOCl(chan, src, 0, + NOUVEAU_BO_GART | NOUVEAU_BO_RD) || + OUT_RELOCl(chan, dst, offset, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { + MARK_UNDO(chan); + return BadAlloc; + } + OUT_RING (chan, line_len); + OUT_RING (chan, dstPitch); + OUT_RING (chan, line_len); + OUT_RING (chan, nlines); + OUT_RING (chan, (1<<8)|1); + OUT_RING (chan, 0); + + return Success; +} /** * NVPutImage @@ -936,8 +1021,6 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, * and lines we are interested in */ int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0; - struct nouveau_channel *chan = pNv->chan; - struct nouveau_grobj *m2mf = pNv->NvMemFormat; Bool skip = FALSE; BoxRec dstBox; CARD32 tmp = 0; @@ -1111,73 +1194,17 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, nouveau_bo_unmap(destination_buffer); - if (pNv->Architecture >= NV_ARCH_C0) { - nvc0_xv_m2mf(m2mf, pPriv->video_mem, uv_offset, dstPitch, - nlines, destination_buffer, line_len); - goto put_image; - } - - if (MARK_RING(chan, 64, 4)) - return FALSE; - - BEGIN_RING(chan, m2mf, - NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); - OUT_RING (chan, pNv->chan->gart->handle); - OUT_RING (chan, pNv->chan->vram->handle); - - if (pNv->Architecture >= NV_ARCH_50) { - BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1); - OUT_RING (chan, 1); - - BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 7); - OUT_RING (chan, 0); - OUT_RING (chan, destination_buffer->tile_mode << 4); - OUT_RING (chan, dstPitch); - OUT_RING (chan, nlines); - OUT_RING (chan, 1); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - } - - /* DMA to VRAM */ - if ( (action_flags & IS_YV12) && - !(action_flags & CONVERT_TO_YUY2)) { - /* we start the color plane transfer separately */ - - BEGIN_RING(chan, m2mf, - NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - if (OUT_RELOCl(chan, destination_buffer, - line_len * nlines, - NOUVEAU_BO_GART | NOUVEAU_BO_RD) || - OUT_RELOCl(chan, pPriv->video_mem, - offset + uv_offset, - NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { - MARK_UNDO(chan); - return BadAlloc; - } - OUT_RING (chan, line_len); - OUT_RING (chan, dstPitch); - OUT_RING (chan, line_len); - OUT_RING (chan, (nlines >> 1)); - OUT_RING (chan, (1<<8)|1); - OUT_RING (chan, 0); + ret = nouveau_xv_m2mf(pScrn, action_flags, + destination_buffer, pPriv->video_mem, + offset, uv_offset, nlines, line_len, dstPitch); + if (ret != Success) { + return ret; } - BEGIN_RING(chan, m2mf, - NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - if (OUT_RELOCl(chan, destination_buffer, 0, - NOUVEAU_BO_GART | NOUVEAU_BO_RD) || - OUT_RELOCl(chan, pPriv->video_mem, offset, - NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { - MARK_UNDO(chan); - return BadAlloc; + if (pNv->Architecture >= NV_ARCH_C0) { + /* is this needed? It is to preserve the original code flow */ + goto put_image; } - OUT_RING (chan, line_len); - OUT_RING (chan, dstPitch); - OUT_RING (chan, line_len); - OUT_RING (chan, nlines); - OUT_RING (chan, (1<<8)|1); - OUT_RING (chan, 0); } else { CPU_copy: nouveau_bo_map(pPriv->video_mem, NOUVEAU_BO_WR); @@ -1356,6 +1383,171 @@ put_image: return Success; } +int +nouveau_put_texture_image(DrawablePtr pDraw, PixmapPtr srcPix, int id, + short src_x, short src_y, short drw_x, short drw_y, + short src_w, short src_h, short drw_w, short drw_h, + short width, short height) +{ + ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + PixmapPtr dstPix = NVGetDrawablePixmap(pDraw); + BoxRec dstBox; + RegionRec clipRegion; + int action_flags; + struct nouveau_bo *src; + int ret = BadImplementation; + + // XXX we just need pPriv->video_mem... maybe there is a better way? + NVPortPrivPtr pPriv = (NVPortPrivPtr)((pNv)->textureAdaptor[0]->pPortPrivates[0].ptr); + + /* source box */ + INT32 xa = 0, xb = 0, ya = 0, yb = 0; + /* size to allocate in VRAM and in GART respectively */ + int newFBSize = 0, newTTSize = 0; /* ignored */ + /* card VRAM offsets, source offsets for U and V planes */ + int offset = 0, uv_offset = 0, s2offset = 0, s3offset = 0; + /* source pitch, source pitch of U and V planes in case of YV12, + * VRAM destination pitch + */ + int srcPitch = 0, srcPitch2 = 0, dstPitch = 0; + /* position of the given source data (using src_*), number of pixels + * and lines we are interested in + */ + int top = 0, left = 0, right = 0, bottom = 0, npixels = 0, nlines = 0; + /* length of a line, like npixels, but in bytes */ + int line_len = 0; + + RegionInit(&clipRegion, (&(BoxRec){ 0, 0, pDraw->width, pDraw->height }), 0); + RegionTranslate(&clipRegion, pDraw->x, pDraw->y); + + action_flags = USE_TEXTURE; + + switch(id) { + case FOURCC_YUY2: + case FOURCC_UYVY: + action_flags |= IS_YUY2; + break; + case FOURCC_I420: + action_flags |= SWAP_UV; + /* fallthrough */ + case FOURCC_YV12: + action_flags |= IS_YV12; + break; + case FOURCC_RGB: + case FOURCC('R','G','B','4'): + case FOURCC('R','G','B','3'): + action_flags |= IS_RGB; + break; + default: + return BadColor; + } + + if (NV_set_dimensions(pScrn, action_flags, &xa, &xb, &ya, &yb, + &src_x, &src_y, &src_w, &src_h, + &drw_x, &drw_y, &drw_w, &drw_h, + &left, &top, &right, &bottom, &dstBox, + &npixels, &nlines, &clipRegion, width, height)) { + return Success; + } + + /* note: in Xv code, pixel buffer is src, uploaded YUV data is dst + * which becomes the src for the PutTextureImage() step.. so dstPitch + * is really our srcPitch (of src pixmap) and srcPitch's are ignored.. + * as are a couple other things.. + */ + if (NV_calculate_pitches_and_mem_size(pNv, action_flags, &srcPitch, + &srcPitch2, &dstPitch, &s2offset, + &s3offset, &uv_offset, + &newFBSize, &newTTSize, + &line_len, npixels, nlines, + width, height)) { + return BadImplementation; + } + + /* Ensure src and dst pixmap is in offscreen memory */ + pNv->exa_force_cp = TRUE; + exaMoveInPixmap(dstPix); + exaMoveInPixmap(srcPix); + pNv->exa_force_cp = FALSE; + + if (!exaGetPixmapDriverPrivate(dstPix) || + !exaGetPixmapDriverPrivate(srcPix)) { + return BadAlloc; + } + + src = nouveau_pixmap_bo(srcPix); + +#ifdef COMPOSITE + /* Convert screen coords to pixmap coords */ + if (dstPix->screen_x || dstPix->screen_y) { + REGION_TRANSLATE(pScrn->pScreen, &clipRegion, + -dstPix->screen_x, -dstPix->screen_y); + dstBox.x1 -= dstPix->screen_x; + dstBox.x2 -= dstPix->screen_x; + dstBox.y1 -= dstPix->screen_y; + dstBox.y2 -= dstPix->screen_y; + } +#endif + + /* TODO check if src buffer is already in VRAM.. for hw decode + * we probably want to allow giving the client buffers in VRAM + * directly (via non-fourcc format values) + */ + + ret = nouveau_xv_bo_realloc(pScrn, NOUVEAU_BO_VRAM, newFBSize, + &pPriv->video_mem); + if (ret) + return BadAlloc; + + ret = nouveau_xv_m2mf(pScrn, action_flags, src, pPriv->video_mem, + offset, uv_offset, nlines, line_len, dstPitch); + if (ret != Success) { + return ret; + } + + if (pNv->Architecture == NV_ARCH_30) { + ret = NV30PutTextureImage(pScrn, pPriv->video_mem, + offset, uv_offset, + id, dstPitch, &dstBox, 0, 0, + xb, yb, npixels, nlines, + src_w, src_h, drw_w, drw_h, + &clipRegion, dstPix, NULL); + } else if (pNv->Architecture == NV_ARCH_40) { + ret = NV40PutTextureImage(pScrn, pPriv->video_mem, + offset, uv_offset, + id, dstPitch, &dstBox, 0, 0, + xb, yb, npixels, nlines, + src_w, src_h, drw_w, drw_h, + &clipRegion, dstPix, NULL); + } else if (pNv->Architecture == NV_ARCH_50) { + ret = nv50_xv_image_put(pScrn, pPriv->video_mem, + offset, uv_offset, + id, dstPitch, &dstBox, 0, 0, + xb, yb, npixels, nlines, + src_w, src_h, drw_w, drw_h, + &clipRegion, dstPix, NULL); + } else { + ret = nvc0_xv_image_put(pScrn, pPriv->video_mem, + offset, uv_offset, + id, dstPitch, &dstBox, 0, 0, + xb, yb, npixels, nlines, + src_w, src_h, drw_w, drw_h, + &clipRegion, dstPix, NULL); + } + +#ifdef COMPOSITE + /* Damage tracking */ + if (!(action_flags & USE_OVERLAY)) + DamageDamageRegion(&dstPix->drawable, &clipRegion); +#endif + + RegionUninit(&clipRegion); + + return ret; +} + + /** * QueryImageAttributes * diff --git a/src/nv30_xv_tex.c b/src/nv30_xv_tex.c index 6d4e089..9c0e828 100644 --- a/src/nv30_xv_tex.c +++ b/src/nv30_xv_tex.c @@ -259,7 +259,7 @@ NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *rankine = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); - Bool bicubic = pPriv->bicubic; + Bool bicubic = pPriv && pPriv->bicubic; float X1, X2, Y1, Y2; BoxPtr pbox; int nbox; @@ -349,7 +349,7 @@ NV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, } /* Just before rendering we wait for vblank in the non-composited case. */ - if (pPriv->SyncToVBlank) { + if (pPriv && pPriv->SyncToVBlank) { FIRE_RING(chan); NV11SyncToVBlank(ppix, dstBox); } diff --git a/src/nv40_xv_tex.c b/src/nv40_xv_tex.c index 0910e12..6249faf 100644 --- a/src/nv40_xv_tex.c +++ b/src/nv40_xv_tex.c @@ -263,7 +263,7 @@ NV40PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *curie = pNv->Nv3D; struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); - Bool bicubic = pPriv->bicubic; + Bool bicubic = pPriv && pPriv->bicubic; float X1, X2, Y1, Y2; BoxPtr pbox; int nbox; @@ -338,7 +338,7 @@ NV40PutTextureImage(ScrnInfoPtr pScrn, OUT_RING (chan, 1); /* Just before rendering we wait for vblank in the non-composited case. */ - if (pPriv->SyncToVBlank) { + if (pPriv && pPriv->SyncToVBlank) { FIRE_RING(chan); NV11SyncToVBlank(ppix, dstBox); } diff --git a/src/nv50_xv.c b/src/nv50_xv.c index ddeb5bb..8b6bd67 100644 --- a/src/nv50_xv.c +++ b/src/nv50_xv.c @@ -290,7 +290,7 @@ nv50_xv_image_put(ScrnInfoPtr pScrn, if (!nv50_xv_state_emit(ppix, id, src, packed_y, uv, width, height)) return BadAlloc; - if (pPriv->SyncToVBlank) { + if (pPriv && pPriv->SyncToVBlank) { NV50SyncToVBlank(ppix, dstBox); } diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index 735f47f..7775331 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -30,6 +30,7 @@ nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, int bpp, NVPtr pNv = NVPTR(scrn); Bool scanout = (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT); Bool tiled = (usage_hint & NOUVEAU_CREATE_PIXMAP_TILED); + Bool video = (usage_hint & NOUVEAU_CREATE_PIXMAP_VIDEO); int tile_mode = 0, tile_flags = 0; int flags = NOUVEAU_BO_MAP | (bpp >= 8 ? NOUVEAU_BO_VRAM : 0); int cpp = bpp / 8, ret; @@ -114,6 +115,16 @@ nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, int bpp, if (usage_hint & NOUVEAU_CREATE_PIXMAP_SCANOUT) tile_flags |= NOUVEAU_BO_TILE_SCANOUT; + if (video) { + if (pNv->Architecture == NV_ARCH_50) + tile_flags = 0x7000; + else if (pNv->Architecture == NV_ARCH_C0) + tile_flags = 0xfe00; + tile_flags |= NOUVEAU_BO_TILE_SCANOUT; + tile_mode = 0; + flags = NOUVEAU_BO_MAP | NOUVEAU_BO_GART; + } + ret = nouveau_bo_new_tile(pNv->dev, flags, 0, *pitch * height, tile_mode, tile_flags, bo); if (ret) diff --git a/src/nv_type.h b/src/nv_type.h index 4204556..c73c156 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -156,6 +156,7 @@ typedef struct _NVPortPrivRec { #define NOUVEAU_CREATE_PIXMAP_ZETA 0x10000000 #define NOUVEAU_CREATE_PIXMAP_TILED 0x20000000 #define NOUVEAU_CREATE_PIXMAP_SCANOUT 0x40000000 +#define NOUVEAU_CREATE_PIXMAP_VIDEO 0x80000000 struct nouveau_pixmap { struct nouveau_bo *bo; diff --git a/src/nvc0_xv.c b/src/nvc0_xv.c index 41ec7a8..149eaaf 100644 --- a/src/nvc0_xv.c +++ b/src/nvc0_xv.c @@ -343,7 +343,7 @@ nvc0_xv_image_put(ScrnInfoPtr pScrn, if (!nvc0_xv_state_emit(ppix, id, src, packed_y, uv, width, height)) return BadAlloc; - if (0 && pPriv->SyncToVBlank) { + if (0 && pPriv && pPriv->SyncToVBlank) { NV50SyncToVBlank(ppix, dstBox); } -- 1.7.5.4 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel