diff options
Diffstat (limited to 'src/sna/sna_video_textured.c')
-rw-r--r-- | src/sna/sna_video_textured.c | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c new file mode 100644 index 00000000..66c70d4a --- /dev/null +++ b/src/sna/sna_video_textured.c @@ -0,0 +1,428 @@ +/*************************************************************************** + + Copyright 2000-2011 Intel Corporation. All Rights Reserved. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sub license, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice (including the + next paragraph) shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + **************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "sna.h" +#include "sna_video.h" + +#include <xf86xv.h> +#include <X11/extensions/Xv.h> + +#ifdef SNA_XVMC +#define _SNA_XVMC_SERVER_ +#include "sna_video_hwmc.h" +#endif + +#if DEBUG_VIDEO_TEXTURED +#undef DBG +#define DBG(x) ErrorF x +#else +#define NDEBUG 1 +#endif + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvContrast, xvSyncToVblank; + +/* client libraries expect an encoding */ +static const XF86VideoEncodingRec DummyEncoding[1] = { + { + 0, + "XV_IMAGE", + 8192, 8192, + {1, 1} + } +}; + +#define NUM_FORMATS 3 + +static XF86VideoFormatRec Formats[NUM_FORMATS] = { + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#define NUM_TEXTURED_ATTRIBUTES 3 +static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = { + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, + {XvSettable | XvGettable, -1, 1, "XV_SYNC_TO_VBLANK"}, +}; + +#ifdef SNA_XVMC +#define NUM_IMAGES 5 +#define XVMC_IMAGE 1 +#else +#define NUM_IMAGES 4 +#define XVMC_IMAGE 0 +#endif + +static XF86ImageRec Images[NUM_IMAGES] = { + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_UYVY, +#ifdef SNA_XVMC + { + /* + * Below, a dummy picture type that is used in XvPutImage + * only to do an overlay update. + * Introduced for the XvMC client lib. + * Defined to have a zero data size. + */ + FOURCC_XVMC, + XvYUV, + LSBFirst, + {'X', 'V', 'M', 'C', + 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, + 0x38, 0x9B, 0x71}, + 12, + XvPlanar, + 3, + 0, 0, 0, 0, + 8, 8, 8, + 1, 2, 2, + 1, 2, 2, + {'Y', 'V', 'U', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + XvTopToBottom}, +#endif +}; + +static int xvmc_passthrough(int id) +{ +#ifdef SNA_XVMC + return id == FOURCC_XVMC; +#else + return 0; +#endif +} + +static void sna_video_textured_stop(ScrnInfoPtr scrn, + pointer data, + Bool shutdown) +{ + struct sna *sna = to_sna(scrn); + struct sna_video *video = data; + + DBG(("%s()\n", __FUNCTION__)); + + REGION_EMPTY(scrn->pScreen, &video->clip); + + if (!shutdown) + return; + + sna_video_free_buffers(sna, video); +} + +static int +sna_video_textured_set_attribute(ScrnInfoPtr scrn, + Atom attribute, + INT32 value, + pointer data) +{ + struct sna_video *video = data; + + if (attribute == xvBrightness) { + if (value < -128 || value > 127) + return BadValue; + + video->brightness = value; + } else if (attribute == xvContrast) { + if (value < 0 || value > 255) + return BadValue; + + video->contrast = value; + } else if (attribute == xvSyncToVblank) { + if (value < -1 || value > 1) + return BadValue; + + video->SyncToVblank = value; + } else + return BadMatch; + + return Success; +} + +static int +sna_video_textured_get_attribute(ScrnInfoPtr scrn, + Atom attribute, + INT32 *value, + pointer data) +{ + struct sna_video *video = data; + + if (attribute == xvBrightness) + *value = video->brightness; + else if (attribute == xvContrast) + *value = video->contrast; + else if (attribute == xvSyncToVblank) + *value = video->SyncToVblank; + else + return BadMatch; + + return Success; +} + +static void +sna_video_textured_best_size(ScrnInfoPtr scrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, + unsigned int *p_h, + pointer data) +{ + if (vid_w > (drw_w << 1)) + drw_w = vid_w >> 1; + if (vid_h > (drw_h << 1)) + drw_h = vid_h >> 1; + + *p_w = drw_w; + *p_h = drw_h; +} + +/* + * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h). + * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h). + * id is a fourcc code for the format of the video. + * buf is the pointer to the source data in system memory. + * width and height are the w/h of the source data. + * If "sync" is TRUE, then we must be finished with *buf at the point of return + * (which we always are). + * clip is the clipping region in screen space. + * data is a pointer to our port private. + * drawable is some Drawable, which might not be the screen in the case of + * compositing. It's a new argument to the function in the 1.1 server. + */ +static int +sna_video_textured_put_image(ScrnInfoPtr scrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char *buf, + short width, short height, + Bool sync, RegionPtr clip, pointer data, + DrawablePtr drawable) +{ + struct sna *sna = to_sna(scrn); + struct sna_video *video = data; + struct sna_video_frame frame; + PixmapPtr pixmap = get_drawable_pixmap(drawable); + BoxRec dstBox; + xf86CrtcPtr crtc; + int top, left, npixels, nlines; + + if (!sna_video_clip_helper(scrn, video, &crtc, &dstBox, + src_x, src_y, drw_x, drw_y, + src_w, src_h, drw_w, drw_h, + id, + &top, &left, &npixels, &nlines, + clip, width, height)) + return Success; + + sna_video_frame_init(sna, video, id, width, height, &frame); + + if (xvmc_passthrough(id)) { + if (IS_I915G(sna) || IS_I915GM(sna)) { + /* XXX: i915 is not support and needs some + * serious care. grep for KMS in i915_hwmc.c */ + return BadAlloc; + } + + frame.bo = kgem_create_for_name(&sna->kgem, *(uint32_t*)buf); + if (frame.bo == NULL) + return BadAlloc; + } else { + if (!sna_video_copy_data(sna, video, &frame, + top, left, npixels, nlines, + buf)) + return BadAlloc; + } + + if (crtc && video->SyncToVblank != 0) + sna_wait_for_scanline(sna, pixmap, crtc, clip); + + sna->render.video(sna, video, &frame, clip, + src_w, src_h, + drw_w, drw_h, + pixmap); + + sna_video_frame_fini(sna, video, &frame); + + DamageDamageRegion(drawable, clip); + + /* Push the frame to the GPU as soon as possible so + * we can hit the next vsync. + */ + kgem_submit(&sna->kgem); + + return Success; +} + +static int +sna_video_textured_query(ScrnInfoPtr scrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ + int size, tmp; + + if (*w > 8192) + *w = 8192; + if (*h > 8192) + *h = 8192; + + *w = (*w + 1) & ~1; + if (offsets) + offsets[0] = 0; + + switch (id) { + /* IA44 is for XvMC only */ + case FOURCC_IA44: + case FOURCC_AI44: + if (pitches) + pitches[0] = *w; + size = *w * *h; + break; + case FOURCC_YV12: + case FOURCC_I420: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if (pitches) + pitches[0] = size; + size *= *h; + if (offsets) + offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if (pitches) + pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if (offsets) + offsets[2] = size; + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if (pitches) + pitches[0] = size; + size *= *h; + break; +#ifdef SNA_XVMC + case FOURCC_XVMC: + *h = (*h + 1) & ~1; + size = sizeof(struct sna_xvmc_command); + if (pitches) + pitches[0] = size; + break; +#endif + } + + return size; +} + +XF86VideoAdaptorPtr sna_video_textured_setup(struct sna *sna, + ScreenPtr screen) +{ + XF86VideoAdaptorPtr adaptor; + XF86AttributePtr attrs; + struct sna_video *video; + DevUnion *devUnions; + int nports = 16, i; + + if (!sna->render.video) { + xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING, + "Textured video not supported on this hardware\n"); + return NULL; + } + + adaptor = calloc(1, sizeof(XF86VideoAdaptorRec)); + video = calloc(nports, sizeof(struct sna_video)); + devUnions = calloc(nports, sizeof(DevUnion)); + attrs = calloc(NUM_TEXTURED_ATTRIBUTES, sizeof(XF86AttributeRec)); + if (adaptor == NULL || + video == NULL || + devUnions == NULL || + attrs == NULL) { + free(adaptor); + free(video); + free(devUnions); + free(attrs); + return NULL; + } + + adaptor->type = XvWindowMask | XvInputMask | XvImageMask; + adaptor->flags = 0; + adaptor->name = "Intel(R) Textured Video"; + adaptor->nEncodings = 1; + adaptor->pEncodings = xnfalloc(sizeof(DummyEncoding)); + memcpy(adaptor->pEncodings, DummyEncoding, sizeof(DummyEncoding)); + adaptor->nFormats = NUM_FORMATS; + adaptor->pFormats = Formats; + adaptor->nPorts = nports; + adaptor->pPortPrivates = devUnions; + adaptor->nAttributes = NUM_TEXTURED_ATTRIBUTES; + adaptor->pAttributes = attrs; + memcpy(attrs, TexturedAttributes, + NUM_TEXTURED_ATTRIBUTES * sizeof(XF86AttributeRec)); + adaptor->nImages = NUM_IMAGES; + adaptor->pImages = Images; + adaptor->PutVideo = NULL; + adaptor->PutStill = NULL; + adaptor->GetVideo = NULL; + adaptor->GetStill = NULL; + adaptor->StopVideo = sna_video_textured_stop; + adaptor->SetPortAttribute = sna_video_textured_set_attribute; + adaptor->GetPortAttribute = sna_video_textured_get_attribute; + adaptor->QueryBestSize = sna_video_textured_best_size; + adaptor->PutImage = sna_video_textured_put_image; + adaptor->QueryImageAttributes = sna_video_textured_query; + + for (i = 0; i < nports; i++) { + struct sna_video *v = &video[i]; + + v->textured = TRUE; + v->rotation = RR_Rotate_0; + v->SyncToVblank = 1; + + /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */ + RegionNull(&v->clip); + + adaptor->pPortPrivates[i].ptr = v; + } + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK"); + + return adaptor; +} |