/* * Copyright 2007 by VMware, Inc. * * 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, sublicense, * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. * * Except as contained in this notice, the name of the copyright holder(s) * and author(s) shall not be used in advertising or otherwise to promote * the sale, use or other dealings in this Software without prior written * authorization from the copyright holder(s) and author(s). */ /* * vmwarevideo.c -- * * Xv extension support. * See http://www.xfree86.org/current/DESIGN16.html * */ #include "xf86xv.h" #include "fourcc.h" #include "pipe/p_compiler.h" /* * We can't incude svga_types.h due to conflicting types for Bool. */ typedef int64_t int64; typedef uint64_t uint64; typedef int32_t int32; typedef uint32_t uint32; typedef int16_t int16; typedef uint16_t uint16; typedef int8_t int8; typedef uint8_t uint8; #include "svga/include/svga_reg.h" #include "svga/include/svga_escape.h" #include "svga/include/svga_overlay.h" #include "vmw_driver.h" #include #include "xf86drm.h" #include "../../winsys/svga/drm/vmwgfx_drm.h" #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) /* * Number of videos that can be played simultaneously */ #define VMWARE_VID_NUM_PORTS 1 /* * Using a dark shade as the default colorKey */ #define VMWARE_VIDEO_COLORKEY 0x100701 /* * Maximum dimensions */ #define VMWARE_VID_MAX_WIDTH 2048 #define VMWARE_VID_MAX_HEIGHT 2048 #define VMWARE_VID_NUM_ENCODINGS 1 static XF86VideoEncodingRec vmwareVideoEncodings[] = { { 0, "XV_IMAGE", VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT, {1, 1} } }; #define VMWARE_VID_NUM_FORMATS 2 static XF86VideoFormatRec vmwareVideoFormats[] = { { 16, TrueColor}, { 24, TrueColor} }; #define VMWARE_VID_NUM_IMAGES 3 static XF86ImageRec vmwareVideoImages[] = { XVIMAGE_YV12, XVIMAGE_YUY2, XVIMAGE_UYVY }; #define VMWARE_VID_NUM_ATTRIBUTES 2 static XF86AttributeRec vmwareVideoAttributes[] = { { XvGettable | XvSettable, 0x000000, 0xffffff, "XV_COLORKEY" }, { XvGettable | XvSettable, 0, 1, "XV_AUTOPAINT_COLORKEY" } }; /* * Video frames are stored in a circular list of buffers. * Must be power or two, See vmw_video_port_play. */ #define VMWARE_VID_NUM_BUFFERS 1 /* * Defines the structure used to hold and pass video data to the host */ struct vmw_video_buffer { unsigned handle; int size; void *data; void *extra_data; struct vmw_dma_buffer *buf; }; /** * Structure representing a single video stream, aka port. * * Ports maps one to one to a SVGA stream. Port is just * what Xv calls a SVGA stream. */ struct vmw_video_port { /* * Function prototype same as XvPutImage. * * This is either set to vmw_video_port_init or vmw_video_port_play. * At init this function is set to port_init. In port_init we set it * to port_play and call it, after initializing the struct. */ int (*play)(ScrnInfoPtr, struct vmw_video_port *, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, RegionPtr); /* values to go into the SVGAOverlayUnit */ uint32 streamId; uint32 colorKey; uint32 flags; /* round robin of buffers */ unsigned currBuf; struct vmw_video_buffer bufs[VMWARE_VID_NUM_BUFFERS]; /* properties that applies to all buffers */ int size; int pitches[3]; int offsets[3]; /* things for X */ RegionRec clipBoxes; Bool isAutoPaintColorkey; }; /** * Structure holding all the infromation for video. */ struct vmw_video_private { int fd; /** ports */ struct vmw_video_port port[VMWARE_VID_NUM_PORTS]; /** Used to store port pointers pointers */ DevUnion port_ptr[VMWARE_VID_NUM_PORTS]; }; /* * Callback functions exported to Xv, prefixed with vmw_xv_*. */ static int vmw_xv_put_image(ScrnInfoPtr pScrn, 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 image, unsigned char *buf, short width, short height, Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr dst); static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup); static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, unsigned short *width, unsigned short *height, int *pitches, int *offsets); static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data); static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data); static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, pointer data); /* * Local functions. */ static XF86VideoAdaptorPtr vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_customizer *vmw); static int vmw_video_port_init(ScrnInfoPtr pScrn, struct vmw_video_port *port, 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 format, unsigned char *buf, short width, short height, RegionPtr clipBoxes); static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, 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 format, unsigned char *buf, short width, short height, RegionPtr clipBoxes); static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port); static int vmw_video_buffer_alloc(struct vmw_customizer *vmw, int size, struct vmw_video_buffer *out); static int vmw_video_buffer_free(struct vmw_customizer *vmw, struct vmw_video_buffer *out); /* *----------------------------------------------------------------------------- * * vmw_video_init -- * * Initializes Xv support. * * Results: * TRUE on success, FALSE on error. * * Side effects: * Xv support is initialized. Memory is allocated for all supported * video streams. * *----------------------------------------------------------------------------- */ Bool vmw_video_init(struct vmw_customizer *vmw) { ScrnInfoPtr pScrn = vmw->pScrn; ScreenPtr pScreen = pScrn->pScreen; XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL; XF86VideoAdaptorPtr newAdaptor = NULL; int numAdaptors; unsigned int ntot, nfree; debug_printf("%s: enter\n", __func__); if (vmw_ioctl_num_streams(vmw, &ntot, &nfree) != 0) { debug_printf("No stream ioctl support\n"); return FALSE; } if (nfree == 0) { debug_printf("No free streams\n"); return FALSE; } numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors); newAdaptor = vmw_video_init_adaptor(pScrn, vmw); if (!newAdaptor) { debug_printf("Failed to initialize Xv extension\n"); return FALSE; } if (!numAdaptors) { numAdaptors = 1; overlayAdaptors = &newAdaptor; } else { newAdaptors = malloc((numAdaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); if (!newAdaptors) { xf86XVFreeVideoAdaptorRec(newAdaptor); return FALSE; } memcpy(newAdaptors, overlayAdaptors, numAdaptors * sizeof(XF86VideoAdaptorPtr)); newAdaptors[numAdaptors++] = newAdaptor; overlayAdaptors = newAdaptors; } if (!xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors)) { debug_printf("Failed to initialize Xv extension\n"); xf86XVFreeVideoAdaptorRec(newAdaptor); return FALSE; } if (newAdaptors) { free(newAdaptors); } debug_printf("Initialized VMware Xv extension successfully\n"); return TRUE; } /* *----------------------------------------------------------------------------- * * vmw_video_close -- * * Unitializes video. * * Results: * TRUE. * * Side effects: * vmw->video_priv = NULL * *----------------------------------------------------------------------------- */ Bool vmw_video_close(struct vmw_customizer *vmw) { ScrnInfoPtr pScrn = vmw->pScrn; struct vmw_video_private *video; int i; debug_printf("%s: enter\n", __func__); video = vmw->video_priv; if (!video) return TRUE; for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { /* make sure the port is stoped as well */ vmw_xv_stop_video(pScrn, &video->port[i], TRUE); vmw_ioctl_unref_stream(vmw, video->port[i].streamId); REGION_UNINIT(pScreen, &video->port[i].clipBoxes); } /* XXX: I'm sure this function is missing code for turning off Xv */ free(vmw->video_priv); vmw->video_priv = NULL; return TRUE; } /* *----------------------------------------------------------------------------- * * vmw_video_stop_all -- * * Stop all video streams from playing. * * Results: * None. * * Side effects: * All buffers are freed. * *----------------------------------------------------------------------------- */ void vmw_video_stop_all(struct vmw_customizer *vmw) { ScrnInfoPtr pScrn = vmw->pScrn; struct vmw_video_private *video = vmw->video_priv; int i; debug_printf("%s: enter\n", __func__); if (!video) return; for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { vmw_xv_stop_video(pScrn, &video->port[i], TRUE); } } /* *----------------------------------------------------------------------------- * * vmw_video_init_adaptor -- * * Initializes a XF86VideoAdaptor structure with the capabilities and * functions supported by this video driver. * * Results: * On success initialized XF86VideoAdaptor struct or NULL on error * * Side effects: * None. * *----------------------------------------------------------------------------- */ static XF86VideoAdaptorPtr vmw_video_init_adaptor(ScrnInfoPtr pScrn, struct vmw_customizer *vmw) { XF86VideoAdaptorPtr adaptor; struct vmw_video_private *video; int i; debug_printf("%s: enter \n", __func__); adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); if (!adaptor) { debug_printf("Not enough memory\n"); return NULL; } video = calloc(1, sizeof(*video)); if (!video) { debug_printf("Not enough memory.\n"); xf86XVFreeVideoAdaptorRec(adaptor); return NULL; } vmw->video_priv = video; adaptor->type = XvInputMask | XvImageMask | XvWindowMask; /** * Note: CLIP_TO_VIEWPORT was removed from the flags, since with the * crtc/output based modesetting, the viewport is not updated on * RandR modeswitches. Hence the video may incorrectly be clipped away. * The correct approach, (if needed) would be to clip against the * scanout area union of all active crtcs. Revisit if needed. */ adaptor->flags = VIDEO_OVERLAID_IMAGES; adaptor->name = "VMware Video Engine"; adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS; adaptor->pEncodings = vmwareVideoEncodings; adaptor->nFormats = VMWARE_VID_NUM_FORMATS; adaptor->pFormats = vmwareVideoFormats; adaptor->nPorts = VMWARE_VID_NUM_PORTS; adaptor->pPortPrivates = video->port_ptr; for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { vmw_ioctl_claim_stream(vmw, &video->port[i].streamId); video->port[i].play = vmw_video_port_init; video->port[i].flags = SVGA_VIDEO_FLAG_COLORKEY; video->port[i].colorKey = VMWARE_VIDEO_COLORKEY; video->port[i].isAutoPaintColorkey = TRUE; REGION_NULL(pScrn->pScreen, &video->port[i].clipBoxes); adaptor->pPortPrivates[i].ptr = &video->port[i]; } adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES; adaptor->pAttributes = vmwareVideoAttributes; adaptor->nImages = VMWARE_VID_NUM_IMAGES; adaptor->pImages = vmwareVideoImages; adaptor->PutVideo = NULL; adaptor->PutStill = NULL; adaptor->GetVideo = NULL; adaptor->GetStill = NULL; adaptor->StopVideo = vmw_xv_stop_video; adaptor->SetPortAttribute = vmw_xv_set_port_attribute; adaptor->GetPortAttribute = vmw_xv_get_port_attribute; adaptor->QueryBestSize = vmw_xv_query_best_size; adaptor->PutImage = vmw_xv_put_image; adaptor->QueryImageAttributes = vmw_xv_query_image_attributes; debug_printf("%s: done %p\n", __func__, adaptor); return adaptor; } /* *----------------------------------------------------------------------------- * * vmw_video_port_init -- * * Initializes a video stream in response to the first PutImage() on a * video stream. The process goes as follows: * - Figure out characteristics according to format * - Allocate offscreen memory * - Pass on video to Play() functions * * Results: * Success or XvBadAlloc on failure. * * Side effects: * Video stream is initialized and its first frame sent to the host * (done by VideoPlay() function called at the end) * *----------------------------------------------------------------------------- */ static int vmw_video_port_init(ScrnInfoPtr pScrn, struct vmw_video_port *port, 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 format, unsigned char *buf, short width, short height, RegionPtr clipBoxes) { struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); unsigned short w, h; int i, ret; debug_printf("\t%s: id %d, format %d\n", __func__, port->streamId, format); w = width; h = height; /* init all the format attributes, used for buffers */ port->size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, port->pitches, port->offsets); if (port->size == -1) return XvBadAlloc; port->play = vmw_video_port_play; for (i = 0; i < VMWARE_VID_NUM_BUFFERS; ++i) { ret = vmw_video_buffer_alloc(vmw, port->size, &port->bufs[i]); if (ret != Success) break; } /* Free all allocated buffers on failure */ if (ret != Success) { for (--i; i >= 0; --i) { vmw_video_buffer_free(vmw, &port->bufs[i]); } return ret; } port->currBuf = 0; REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes); if (port->isAutoPaintColorkey) xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes); xorg_flush(pScrn->pScreen); return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, format, buf, width, height, clipBoxes); } /* *----------------------------------------------------------------------------- * * vmw_video_port_play -- * * Sends all the attributes associated with the video frame using the * FIFO ESCAPE mechanism to the host. * * Results: * Always returns Success. * * Side effects: * None. * *----------------------------------------------------------------------------- */ static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmw_video_port *port, 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 format, unsigned char *buf, short width, short height, RegionPtr clipBoxes) { struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); struct drm_vmw_control_stream_arg arg; unsigned short w, h; int size; int ret; debug_printf("\t%s: enter\n", __func__); w = width; h = height; /* we don't update the ports size */ size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, port->pitches, port->offsets); if (size > port->size) { debug_printf("\t%s: Increase in size of Xv video frame streamId:%d.\n", __func__, port->streamId); vmw_xv_stop_video(pScrn, port, TRUE); return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, format, buf, width, height, clipBoxes); } memcpy(port->bufs[port->currBuf].data, buf, port->size); memset(&arg, 0, sizeof(arg)); arg.stream_id = port->streamId; arg.enabled = TRUE; arg.flags = port->flags; arg.color_key = port->colorKey; arg.handle = port->bufs[port->currBuf].handle; arg.format = format; arg.size = port->size; arg.width = w; arg.height = h; arg.src.x = src_x; arg.src.y = src_y; arg.src.w = src_w; arg.src.h = src_h; arg.dst.x = drw_x; arg.dst.y = drw_y; arg.dst.w = drw_w; arg.dst.h = drw_h; arg.pitch[0] = port->pitches[0]; arg.pitch[1] = port->pitches[1]; arg.pitch[2] = port->pitches[2]; arg.offset = 0; /* * Update the clipList and paint the colorkey, if required. */ if (!REGION_EQUAL(pScrn->pScreen, &port->clipBoxes, clipBoxes)) { REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes); if (port->isAutoPaintColorkey) xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes); } xorg_flush(pScrn->pScreen); ret = drmCommandWrite(vmw->fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg)); if (ret) { vmw_video_port_cleanup(pScrn, port); return XvBadAlloc; } if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS) port->currBuf = 0; return Success; } /* *----------------------------------------------------------------------------- * * vmw_video_port_cleanup -- * * Frees up all resources (if any) taken by a video stream. * * Results: * None. * * Side effects: * Same as above. * *----------------------------------------------------------------------------- */ static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmw_video_port *port) { struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); uint32 id, colorKey, flags; Bool isAutoPaintColorkey; int i; debug_printf("\t%s: enter\n", __func__); for (i = 0; i < VMWARE_VID_NUM_BUFFERS; i++) { vmw_video_buffer_free(vmw, &port->bufs[i]); } /* * reset stream for next video */ id = port->streamId; colorKey = port->colorKey; flags = port->flags; isAutoPaintColorkey = port->isAutoPaintColorkey; memset(port, 0, sizeof(*port)); port->streamId = id; port->play = vmw_video_port_init; port->colorKey = colorKey; port->flags = flags; port->isAutoPaintColorkey = isAutoPaintColorkey; } /* *----------------------------------------------------------------------------- * * vmw_video_buffer_alloc -- * * Allocates and map a kernel buffer to be used as data storage. * * Results: * XvBadAlloc on failure, otherwise Success. * * Side effects: * Calls into the kernel, sets members of out. * *----------------------------------------------------------------------------- */ static int vmw_video_buffer_alloc(struct vmw_customizer *vmw, int size, struct vmw_video_buffer *out) { out->buf = vmw_ioctl_buffer_create(vmw, size, &out->handle); if (!out->buf) return XvBadAlloc; out->data = vmw_ioctl_buffer_map(vmw, out->buf); if (!out->data) { vmw_ioctl_buffer_destroy(vmw, out->buf); out->handle = 0; out->buf = NULL; return XvBadAlloc; } out->size = size; out->extra_data = calloc(1, size); debug_printf("\t\t%s: allocated buffer %p of size %i\n", __func__, out, size); return Success; } /* *----------------------------------------------------------------------------- * * vmw_video_buffer_free -- * * Frees and unmaps an allocated kernel buffer. * * Results: * Success. * * Side effects: * Calls into the kernel, sets members of out to 0. * *----------------------------------------------------------------------------- */ static int vmw_video_buffer_free(struct vmw_customizer *vmw, struct vmw_video_buffer *out) { if (out->size == 0) return Success; free(out->extra_data); vmw_ioctl_buffer_unmap(vmw, out->buf); vmw_ioctl_buffer_destroy(vmw, out->buf); out->buf = NULL; out->data = NULL; out->handle = 0; out->size = 0; debug_printf("\t\t%s: freed buffer %p\n", __func__, out); return Success; } /* *----------------------------------------------------------------------------- * * vmw_xv_put_image -- * * Main video playback function. It copies the passed data which is in * the specified format (e.g. FOURCC_YV12) into the overlay. * * If sync is TRUE the driver should not return from this * function until it is through reading the data from buf. * * Results: * Success or XvBadAlloc on failure * * Side effects: * Video port will be played(initialized if 1st frame) on success * or will fail on error. * *----------------------------------------------------------------------------- */ static int vmw_xv_put_image(ScrnInfoPtr pScrn, 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 format, unsigned char *buf, short width, short height, Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr dst) { struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); struct vmw_video_port *port = data; debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, width, height); if (!vmw->video_priv) return XvBadAlloc; return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, format, buf, width, height, clipBoxes); } /* *----------------------------------------------------------------------------- * * vmw_xv_stop_video -- * * Called when we should stop playing video for a particular stream. If * Cleanup is FALSE, the "stop" operation is only temporary, and thus we * don't do anything. If Cleanup is TRUE we kill the video port by * sending a message to the host and freeing up the stream. * * Results: * None. * * Side effects: * See above. * *----------------------------------------------------------------------------- */ static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) { struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); struct vmw_video_port *port = data; struct drm_vmw_control_stream_arg arg; int ret; debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE"); if (!vmw->video_priv) return; REGION_EMPTY(pScrn->pScreen, &port->clipBoxes); if (!cleanup) return; memset(&arg, 0, sizeof(arg)); arg.stream_id = port->streamId; arg.enabled = FALSE; ret = drmCommandWrite(vmw->fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg)); assert(ret == 0); vmw_video_port_cleanup(pScrn, port); } /* *----------------------------------------------------------------------------- * * vmw_xv_query_image_attributes -- * * From the spec: This function is called to let the driver specify how data * for a particular image of size width by height should be stored. * Sometimes only the size and corrected width and height are needed. In * that case pitches and offsets are NULL. * * Results: * The size of the memory required for the image, or -1 on error. * * Side effects: * None. * *----------------------------------------------------------------------------- */ static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, unsigned short *width, unsigned short *height, int *pitches, int *offsets) { INT32 size, tmp; if (*width > VMWARE_VID_MAX_WIDTH) { *width = VMWARE_VID_MAX_WIDTH; } if (*height > VMWARE_VID_MAX_HEIGHT) { *height = VMWARE_VID_MAX_HEIGHT; } *width = (*width + 1) & ~1; if (offsets != NULL) { offsets[0] = 0; } switch (format) { case FOURCC_YV12: *height = (*height + 1) & ~1; size = (*width + 3) & ~3; if (pitches) { pitches[0] = size; } size *= *height; if (offsets) { offsets[1] = size; } tmp = ((*width >> 1) + 3) & ~3; if (pitches) { pitches[1] = pitches[2] = tmp; } tmp *= (*height >> 1); size += tmp; if (offsets) { offsets[2] = size; } size += tmp; break; case FOURCC_UYVY: case FOURCC_YUY2: size = *width * 2; if (pitches) { pitches[0] = size; } size *= *height; break; default: debug_printf("Query for invalid video format %d\n", format); return -1; } return size; } /* *----------------------------------------------------------------------------- * * vmw_xv_set_port_attribute -- * * From the spec: A port may have particular attributes such as colorKey, hue, * saturation, brightness or contrast. Xv clients set these * attribute values by sending attribute strings (Atoms) to the server. * * Results: * Success if the attribute exists and XvBadAlloc otherwise. * * Side effects: * The respective attribute gets the new value. * *----------------------------------------------------------------------------- */ static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { struct vmw_video_port *port = data; Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); if (attribute == xvColorKey) { debug_printf("%s: Set colorkey:0x%x\n", __func__, (unsigned)value); port->colorKey = value; } else if (attribute == xvAutoPaint) { debug_printf("%s: Set autoPaint: %s\n", __func__, value? "TRUE": "FALSE"); port->isAutoPaintColorkey = value; } else { return XvBadAlloc; } return Success; } /* *----------------------------------------------------------------------------- * * vmw_xv_get_port_attribute -- * * From the spec: A port may have particular attributes such as hue, * saturation, brightness or contrast. Xv clients get these * attribute values by sending attribute strings (Atoms) to the server * * Results: * Success if the attribute exists and XvBadAlloc otherwise. * * Side effects: * "value" contains the requested attribute on success. * *----------------------------------------------------------------------------- */ static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data) { struct vmw_video_port *port = data; Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); if (attribute == xvColorKey) { *value = port->colorKey; } else if (attribute == xvAutoPaint) { *value = port->isAutoPaintColorkey; } else { return XvBadAlloc; } return Success; } /* *----------------------------------------------------------------------------- * * vmw_xv_query_best_size -- * * From the spec: QueryBestSize provides the client with a way to query what * the destination dimensions would end up being if they were to request * that an area vid_w by vid_h from the video stream be scaled to rectangle * of drw_w by drw_h on the screen. Since it is not expected that all * hardware will be able to get the target dimensions exactly, it is * important that the driver provide this function. * * This function seems to never be called, but to be on the safe side * we apply the same logic that QueryImageAttributes has for width * and height. * * Results: * None. * * Side effects: * None. * *----------------------------------------------------------------------------- */ static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, pointer data) { *p_w = (drw_w + 1) & ~1; *p_h = drw_h; return; }