vmwarevideo.c revision 16fd1166
16df26cacSmrg/*
26df26cacSmrg * Copyright 2007 by VMware, Inc.
36df26cacSmrg *
46df26cacSmrg * Permission is hereby granted, free of charge, to any person obtaining a
56df26cacSmrg * copy of this software and associated documentation files (the "Software"),
66df26cacSmrg * to deal in the Software without restriction, including without limitation
76df26cacSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86df26cacSmrg * and/or sell copies of the Software, and to permit persons to whom the
96df26cacSmrg * Software is furnished to do so, subject to the following conditions:
106df26cacSmrg *
116df26cacSmrg * The above copyright notice and this permission notice shall be included in
126df26cacSmrg * all copies or substantial portions of the Software.
136df26cacSmrg *
146df26cacSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156df26cacSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166df26cacSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
176df26cacSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
186df26cacSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
196df26cacSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
206df26cacSmrg * OTHER DEALINGS IN THE SOFTWARE.
216df26cacSmrg *
226df26cacSmrg * Except as contained in this notice, the name of the copyright holder(s)
236df26cacSmrg * and author(s) shall not be used in advertising or otherwise to promote
246df26cacSmrg * the sale, use or other dealings in this Software without prior written
256df26cacSmrg * authorization from the copyright holder(s) and author(s).
266df26cacSmrg */
276df26cacSmrg
286df26cacSmrg/*
296df26cacSmrg * vmwarevideo.c --
306df26cacSmrg *
316df26cacSmrg *      Xv extension support.
326df26cacSmrg *      See http://www.xfree86.org/current/DESIGN16.html
336df26cacSmrg *
346df26cacSmrg */
356df26cacSmrg
366df26cacSmrg
376df26cacSmrg#ifdef HAVE_CONFIG_H
386df26cacSmrg#include "config.h"
396df26cacSmrg#endif
406df26cacSmrg
416df26cacSmrg#include "vmware.h"
426df26cacSmrg#include "xf86xv.h"
436df26cacSmrg#include "fourcc.h"
446df26cacSmrg#include "svga_escape.h"
456df26cacSmrg#include "svga_overlay.h"
466df26cacSmrg
476df26cacSmrg#include <X11/extensions/Xv.h>
486df26cacSmrg
496df26cacSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
506df26cacSmrg
516df26cacSmrg/*
526df26cacSmrg * Used to pack structs
536df26cacSmrg */
546df26cacSmrg#define PACKED __attribute__((__packed__))
556df26cacSmrg
566df26cacSmrg/*
576df26cacSmrg * Number of videos that can be played simultaneously
586df26cacSmrg */
596df26cacSmrg#define VMWARE_VID_NUM_PORTS 1
606df26cacSmrg
616df26cacSmrg/*
6216fd1166Smrg * Using a dark shade as the default colorKey
636df26cacSmrg */
6416fd1166Smrg#define VMWARE_VIDEO_COLORKEY 0x100701
656df26cacSmrg
666df26cacSmrg/*
676df26cacSmrg * Maximum dimensions
686df26cacSmrg */
696df26cacSmrg#define VMWARE_VID_MAX_WIDTH    2048
706df26cacSmrg#define VMWARE_VID_MAX_HEIGHT   2048
716df26cacSmrg
726df26cacSmrg#define VMWARE_VID_NUM_ENCODINGS 1
736df26cacSmrgstatic XF86VideoEncodingRec vmwareVideoEncodings[] =
746df26cacSmrg{
756df26cacSmrg    {
766df26cacSmrg       0,
776df26cacSmrg       "XV_IMAGE",
786df26cacSmrg       VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT,
796df26cacSmrg       {1, 1}
806df26cacSmrg    }
816df26cacSmrg};
826df26cacSmrg
836df26cacSmrg#define VMWARE_VID_NUM_FORMATS 2
846df26cacSmrgstatic XF86VideoFormatRec vmwareVideoFormats[] =
856df26cacSmrg{
866df26cacSmrg    { 16, TrueColor},
876df26cacSmrg    { 24, TrueColor}
886df26cacSmrg};
896df26cacSmrg
9016fd1166Smrg#define VMWARE_VID_NUM_IMAGES 3
916df26cacSmrgstatic XF86ImageRec vmwareVideoImages[] =
926df26cacSmrg{
936df26cacSmrg    XVIMAGE_YV12,
9416fd1166Smrg    XVIMAGE_YUY2,
9516fd1166Smrg    XVIMAGE_UYVY
966df26cacSmrg};
976df26cacSmrg
9816fd1166Smrg#define VMWARE_VID_NUM_ATTRIBUTES 2
996df26cacSmrgstatic XF86AttributeRec vmwareVideoAttributes[] =
1006df26cacSmrg{
1016df26cacSmrg    {
1026df26cacSmrg        XvGettable | XvSettable,
1036df26cacSmrg        0x000000,
1046df26cacSmrg        0xffffff,
1056df26cacSmrg        "XV_COLORKEY"
10616fd1166Smrg    },
10716fd1166Smrg    {
10816fd1166Smrg        XvGettable | XvSettable,
10916fd1166Smrg        0,
11016fd1166Smrg        1,
11116fd1166Smrg        "XV_AUTOPAINT_COLORKEY"
1126df26cacSmrg    }
1136df26cacSmrg};
1146df26cacSmrg
1156df26cacSmrg/*
1166df26cacSmrg * Video frames are stored in a circular list of buffers.
1176df26cacSmrg */
1186df26cacSmrg#define VMWARE_VID_NUM_BUFFERS 1
1196df26cacSmrg/*
1206df26cacSmrg * Defines the structure used to hold and pass video data to the host
1216df26cacSmrg */
1226df26cacSmrgtypedef struct {
1236df26cacSmrg   uint32  dataOffset;
1246df26cacSmrg   pointer data;
1256df26cacSmrg} VMWAREVideoBuffer;
1266df26cacSmrg
1276df26cacSmrgtypedef struct {
1286df26cacSmrg   uint32 size;
1296df26cacSmrg   uint32 offset;
1306df26cacSmrg} VMWAREOffscreenRec, *VMWAREOffscreenPtr;
1316df26cacSmrg
1326df26cacSmrg/*
1336df26cacSmrg * Trivial offscreen manager that allocates memory from the
1346df26cacSmrg * bottom of the VRAM.
1356df26cacSmrg */
1366df26cacSmrgstatic VMWAREOffscreenRec offscreenMgr;
1376df26cacSmrg
1386df26cacSmrg/*
1396df26cacSmrg * structs that reside in fmt_priv.
1406df26cacSmrg */
1416df26cacSmrgtypedef struct {
1426df26cacSmrg    int pitches[3];
1436df26cacSmrg    int offsets[3];
1446df26cacSmrg} VMWAREVideoFmtData;
1456df26cacSmrg
1466df26cacSmrg/*
1476df26cacSmrg * Structure representing a specific video stream.
1486df26cacSmrg */
1496df26cacSmrgstruct VMWAREVideoRec {
1506df26cacSmrg   uint32             streamId;
1516df26cacSmrg   /*
1526df26cacSmrg    * Function prototype same as XvPutImage.
1536df26cacSmrg    */
1546df26cacSmrg   int                (*play)(ScrnInfoPtr, struct VMWAREVideoRec *,
1556df26cacSmrg                              short, short, short, short, short,
1566df26cacSmrg                              short, short, short, int, unsigned char*,
15716fd1166Smrg                              short, short, RegionPtr);
1586df26cacSmrg   /*
1596df26cacSmrg    * Offscreen memory region used to pass video data to the host.
1606df26cacSmrg    */
1616df26cacSmrg   VMWAREOffscreenPtr fbarea;
1626df26cacSmrg   VMWAREVideoBuffer  bufs[VMWARE_VID_NUM_BUFFERS];
1636df26cacSmrg   uint8              currBuf;
1646df26cacSmrg   uint32             size;
1656df26cacSmrg   uint32             colorKey;
16616fd1166Smrg   Bool               isAutoPaintColorkey;
1676df26cacSmrg   uint32             flags;
16816fd1166Smrg   RegionRec          clipBoxes;
1696df26cacSmrg   VMWAREVideoFmtData *fmt_priv;
1706df26cacSmrg};
1716df26cacSmrg
1726df26cacSmrgtypedef struct VMWAREVideoRec VMWAREVideoRec;
1736df26cacSmrgtypedef VMWAREVideoRec *VMWAREVideoPtr;
1746df26cacSmrg
1756df26cacSmrg/*
1766df26cacSmrg * Callback functions
1776df26cacSmrg */
17816fd1166Smrg#ifdef HAVE_XORG_SERVER_1_0_99_901
1796df26cacSmrgstatic int vmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1806df26cacSmrg                            short drw_x, short drw_y, short src_w, short src_h,
1816df26cacSmrg                            short drw_w, short drw_h, int image,
1826df26cacSmrg                            unsigned char *buf, short width, short height,
1836df26cacSmrg                            Bool sync, RegionPtr clipBoxes, pointer data,
1846df26cacSmrg                            DrawablePtr dst);
1856df26cacSmrg#else
1866df26cacSmrgstatic int vmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1876df26cacSmrg                            short drw_x, short drw_y, short src_w, short src_h,
1886df26cacSmrg                            short drw_w, short drw_h, int image,
1896df26cacSmrg                            unsigned char *buf, short width, short height,
1906df26cacSmrg                            Bool sync, RegionPtr clipBoxes, pointer data);
1916df26cacSmrg#endif
1926df26cacSmrgstatic void vmwareStopVideo(ScrnInfoPtr pScrn, pointer data, Bool Cleanup);
1936df26cacSmrgstatic int vmwareQueryImageAttributes(ScrnInfoPtr pScrn, int format,
1946df26cacSmrg                                      unsigned short *width,
1956df26cacSmrg                                      unsigned short *height, int *pitches,
1966df26cacSmrg                                      int *offsets);
1976df26cacSmrgstatic int vmwareSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1986df26cacSmrg                                  INT32 value, pointer data);
1996df26cacSmrgstatic int vmwareGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
2006df26cacSmrg                                  INT32 *value, pointer data);
2016df26cacSmrgstatic void vmwareQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
2026df26cacSmrg                                short vid_w, short vid_h, short drw_w,
2036df26cacSmrg                                short drw_h, unsigned int *p_w,
2046df26cacSmrg                                unsigned int *p_h, pointer data);
2056df26cacSmrg
2066df26cacSmrg/*
2076df26cacSmrg * Local functions for video streams
2086df26cacSmrg */
2096df26cacSmrgstatic XF86VideoAdaptorPtr vmwareVideoSetup(ScrnInfoPtr pScrn);
2106df26cacSmrgstatic int vmwareVideoInitStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
2116df26cacSmrg                                 short src_x, short src_y, short drw_x,
2126df26cacSmrg                                 short drw_y, short src_w, short src_h,
2136df26cacSmrg                                 short drw_w, short drw_h, int format,
21416fd1166Smrg                                 unsigned char *buf, short width,
21516fd1166Smrg                                 short height, RegionPtr clipBoxes);
2166df26cacSmrgstatic int vmwareVideoInitAttributes(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
2176df26cacSmrg                                     int format, unsigned short width,
2186df26cacSmrg                                     unsigned short height);
2196df26cacSmrgstatic int vmwareVideoPlay(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
2206df26cacSmrg                           short src_x, short src_y, short drw_x,
2216df26cacSmrg                           short drw_y, short src_w, short src_h,
2226df26cacSmrg                           short drw_w, short drw_h, int format,
2236df26cacSmrg                           unsigned char *buf, short width,
22416fd1166Smrg                           short height, RegionPtr clipBoxes);
2256df26cacSmrgstatic void vmwareVideoFlush(VMWAREPtr pVMWARE, uint32 streamId);
2266df26cacSmrgstatic void vmwareVideoSetOneReg(VMWAREPtr pVMWARE, uint32 streamId,
2276df26cacSmrg                                 uint32 regId, uint32 value);
2286df26cacSmrgstatic void vmwareVideoEndStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid);
2296df26cacSmrg
2306df26cacSmrg/*
2316df26cacSmrg * Offscreen memory manager functions
2326df26cacSmrg */
2336df26cacSmrgstatic void vmwareOffscreenInit(void);
2346df26cacSmrgstatic VMWAREOffscreenPtr vmwareOffscreenAllocate(VMWAREPtr pVMWARE,
2356df26cacSmrg                                                  uint32 size);
2366df26cacSmrgstatic void vmwareOffscreenFree(VMWAREOffscreenPtr memptr);
2376df26cacSmrg
2386df26cacSmrg
2396df26cacSmrg/*
2406df26cacSmrg *-----------------------------------------------------------------------------
2416df26cacSmrg *
2426df26cacSmrg * vmwareCheckVideoSanity --
2436df26cacSmrg *
2446df26cacSmrg *    Ensures that on ModeSwitch the offscreen memory used
2456df26cacSmrg *    by the Xv streams doesn't become part of the guest framebuffer.
2466df26cacSmrg *
2476df26cacSmrg * Results:
2486df26cacSmrg *    None
2496df26cacSmrg *
2506df26cacSmrg * Side effects:
2516df26cacSmrg *    If it is found that the offscreen used by video streams  lies
2526df26cacSmrg *    within the range of the framebuffer(after ModeSwitch) then the video
2536df26cacSmrg *    streams will be stopped.
2546df26cacSmrg *
2556df26cacSmrg *-----------------------------------------------------------------------------
2566df26cacSmrg */
2576df26cacSmrg
2586df26cacSmrgvoid
2596df26cacSmrgvmwareCheckVideoSanity(ScrnInfoPtr pScrn)
2606df26cacSmrg{
2616df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
2626df26cacSmrg    VMWAREVideoPtr pVid;
2636df26cacSmrg
2646df26cacSmrg   if (offscreenMgr.size == 0 ||
2656df26cacSmrg       offscreenMgr.offset > pVMWARE->FbSize) {
2666df26cacSmrg       return ;
2676df26cacSmrg   }
2686df26cacSmrg
2696df26cacSmrg   pVid = (VMWAREVideoPtr) &pVMWARE->videoStreams[VMWARE_VID_NUM_PORTS];
2706df26cacSmrg   vmwareStopVideo(pScrn, pVid, TRUE);
2716df26cacSmrg}
2726df26cacSmrg
2736df26cacSmrg
2746df26cacSmrg/*
2756df26cacSmrg *-----------------------------------------------------------------------------
2766df26cacSmrg *
2776df26cacSmrg * vmwareOffscreenInit --
2786df26cacSmrg *
2796df26cacSmrg *    Initializes the trivial Offscreen memory manager.
2806df26cacSmrg *
2816df26cacSmrg * Results:
2826df26cacSmrg *    None.
2836df26cacSmrg *
2846df26cacSmrg * Side effects:
2856df26cacSmrg *    Initializes the Offscreen manager meta-data structure.
2866df26cacSmrg *
2876df26cacSmrg *-----------------------------------------------------------------------------
2886df26cacSmrg */
2896df26cacSmrg
2906df26cacSmrgstatic void
2916df26cacSmrgvmwareOffscreenInit(void)
2926df26cacSmrg{
2936df26cacSmrg    offscreenMgr.size = 0;
2946df26cacSmrg    offscreenMgr.offset  = 0;
2956df26cacSmrg}
2966df26cacSmrg
2976df26cacSmrg
2986df26cacSmrg/*
2996df26cacSmrg *-----------------------------------------------------------------------------
3006df26cacSmrg *
3016df26cacSmrg * vmwareOffscreenAllocate --
3026df26cacSmrg *
3036df26cacSmrg *    Allocates offscreen memory.
3046df26cacSmrg *    Memory is allocated from the bottom part of the VRAM.
3056df26cacSmrg *    The memory manager is trivial iand can handle only 1 video-stream.
3066df26cacSmrg *    ----------
3076df26cacSmrg *    |        |
3086df26cacSmrg *    |  FB    |
3096df26cacSmrg *    |        |
3106df26cacSmrg *    |---------
3116df26cacSmrg *    |        |
3126df26cacSmrg *    |        |
3136df26cacSmrg *    |--------|
3146df26cacSmrg *    | Offscr |
3156df26cacSmrg *    |--------|
3166df26cacSmrg *
3176df26cacSmrg *      VRAM
3186df26cacSmrg *
3196df26cacSmrg * Results:
3206df26cacSmrg *    Pointer to the allocated Offscreen memory.
3216df26cacSmrg *
3226df26cacSmrg * Side effects:
3236df26cacSmrg *    Updates the Offscreen memory manager meta-data structure.
3246df26cacSmrg *
3256df26cacSmrg *-----------------------------------------------------------------------------
3266df26cacSmrg */
3276df26cacSmrg
3286df26cacSmrgstatic VMWAREOffscreenPtr
3296df26cacSmrgvmwareOffscreenAllocate(VMWAREPtr pVMWARE, uint32 size)
3306df26cacSmrg{
3316df26cacSmrg    VMWAREOffscreenPtr memptr;
3326df26cacSmrg
3336df26cacSmrg    if ((pVMWARE->videoRam - pVMWARE->FbSize - pVMWARE->fbPitch - 7) < size) {
3346df26cacSmrg        return NULL;
3356df26cacSmrg    }
3366df26cacSmrg
3376df26cacSmrg    memptr = xalloc(sizeof(VMWAREOffscreenRec));
3386df26cacSmrg    if (!memptr) {
3396df26cacSmrg        return NULL;
3406df26cacSmrg    }
3416df26cacSmrg    memptr->size = size;
3426df26cacSmrg    memptr->offset  = (pVMWARE->videoRam - size) & ~7;
3436df26cacSmrg
3446df26cacSmrg    VmwareLog(("vmwareOffscreenAllocate: Offset:%x", memptr->offset));
3456df26cacSmrg
3466df26cacSmrg    offscreenMgr.size = memptr->size;
3476df26cacSmrg    offscreenMgr.offset = memptr->offset;
3486df26cacSmrg    return memptr;
3496df26cacSmrg}
3506df26cacSmrg
3516df26cacSmrg
3526df26cacSmrg/*
3536df26cacSmrg *-----------------------------------------------------------------------------
3546df26cacSmrg *
3556df26cacSmrg * vmwareOffscreenFree --
3566df26cacSmrg *
3576df26cacSmrg *    Frees the allocated offscreen memory.
3586df26cacSmrg *
3596df26cacSmrg * Results:
3606df26cacSmrg *    None.
3616df26cacSmrg *
3626df26cacSmrg * Side effects:
3636df26cacSmrg *    Updates the Offscreen memory manager meta-data structure.
3646df26cacSmrg *
3656df26cacSmrg *-----------------------------------------------------------------------------
3666df26cacSmrg */
3676df26cacSmrg
3686df26cacSmrgstatic void
3696df26cacSmrgvmwareOffscreenFree(VMWAREOffscreenPtr memptr)
3706df26cacSmrg{
3716df26cacSmrg    if (memptr) {
3726df26cacSmrg        free(memptr);
3736df26cacSmrg    }
3746df26cacSmrg
3756df26cacSmrg    offscreenMgr.size = 0;
3766df26cacSmrg    offscreenMgr.offset = 0;
3776df26cacSmrg}
3786df26cacSmrg
3796df26cacSmrg
3806df26cacSmrg/*
3816df26cacSmrg *-----------------------------------------------------------------------------
3826df26cacSmrg *
3836df26cacSmrg * vmwareVideoEnabled --
3846df26cacSmrg *
3856df26cacSmrg *    Checks if Video FIFO and Escape FIFO cap are enabled.
3866df26cacSmrg *
3876df26cacSmrg * Results:
3886df26cacSmrg *    TRUE if required caps are enabled, FALSE otherwise.
3896df26cacSmrg *
3906df26cacSmrg * Side effects:
3916df26cacSmrg *    None.
3926df26cacSmrg *
3936df26cacSmrg *-----------------------------------------------------------------------------
3946df26cacSmrg */
3956df26cacSmrg
39616fd1166SmrgBool
39716fd1166SmrgvmwareVideoEnabled(VMWAREPtr pVMWARE)
3986df26cacSmrg{
3996df26cacSmrg    return ((pVMWARE->vmwareCapability & SVGA_CAP_EXTENDED_FIFO) &&
4006df26cacSmrg            (pVMWARE->vmwareFIFO[SVGA_FIFO_CAPABILITIES] &
4016df26cacSmrg             (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE)));
4026df26cacSmrg}
4036df26cacSmrg
4046df26cacSmrg
4056df26cacSmrg/*
4066df26cacSmrg *-----------------------------------------------------------------------------
4076df26cacSmrg *
4086df26cacSmrg * vmwareVideoInit --
4096df26cacSmrg *
4106df26cacSmrg *    Initializes Xv support.
4116df26cacSmrg *
4126df26cacSmrg * Results:
4136df26cacSmrg *    TRUE on success, FALSE on error.
4146df26cacSmrg *
4156df26cacSmrg * Side effects:
4166df26cacSmrg *    Xv support is initialized. Memory is allocated for all supported
4176df26cacSmrg *    video streams.
4186df26cacSmrg *
4196df26cacSmrg *-----------------------------------------------------------------------------
4206df26cacSmrg */
4216df26cacSmrg
42216fd1166SmrgBool
42316fd1166SmrgvmwareVideoInit(ScreenPtr pScreen)
4246df26cacSmrg{
4256df26cacSmrg    ScrnInfoPtr pScrn = infoFromScreen(pScreen);
4266df26cacSmrg    XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL;
4276df26cacSmrg    XF86VideoAdaptorPtr newAdaptor = NULL;
4286df26cacSmrg    int numAdaptors;
4296df26cacSmrg
4306df26cacSmrg    TRACEPOINT
4316df26cacSmrg
4326df26cacSmrg    vmwareOffscreenInit();
4336df26cacSmrg
4346df26cacSmrg    numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors);
4356df26cacSmrg
4366df26cacSmrg    newAdaptor = vmwareVideoSetup(pScrn);
4376df26cacSmrg    if (!newAdaptor) {
4386df26cacSmrg        VmwareLog(("Failed to initialize Xv extension \n"));
4396df26cacSmrg        return FALSE;
4406df26cacSmrg    }
4416df26cacSmrg
4426df26cacSmrg    if (!numAdaptors) {
4436df26cacSmrg        numAdaptors = 1;
4446df26cacSmrg        overlayAdaptors = &newAdaptor;
4456df26cacSmrg    } else {
4466df26cacSmrg         newAdaptors = xalloc((numAdaptors + 1) *
4476df26cacSmrg                              sizeof(XF86VideoAdaptorPtr*));
4486df26cacSmrg         if (!newAdaptors) {
4496df26cacSmrg            xf86XVFreeVideoAdaptorRec(newAdaptor);
4506df26cacSmrg            return FALSE;
4516df26cacSmrg         }
4526df26cacSmrg
4536df26cacSmrg         memcpy(newAdaptors, overlayAdaptors,
4546df26cacSmrg                numAdaptors * sizeof(XF86VideoAdaptorPtr));
4556df26cacSmrg         newAdaptors[numAdaptors++] = newAdaptor;
4566df26cacSmrg         overlayAdaptors = newAdaptors;
4576df26cacSmrg    }
4586df26cacSmrg
4596df26cacSmrg    if (!xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors)) {
4606df26cacSmrg        VmwareLog(("Failed to initialize Xv extension\n"));
4616df26cacSmrg        xf86XVFreeVideoAdaptorRec(newAdaptor);
4626df26cacSmrg        return FALSE;
4636df26cacSmrg    }
4646df26cacSmrg
4656df26cacSmrg    if (newAdaptors) {
4666df26cacSmrg        xfree(newAdaptors);
4676df26cacSmrg    }
4686df26cacSmrg
4696df26cacSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4706df26cacSmrg               "Initialized VMware Xv extension successfully.\n");
4716df26cacSmrg    return TRUE;
4726df26cacSmrg}
4736df26cacSmrg
4746df26cacSmrg
4756df26cacSmrg/*
4766df26cacSmrg *-----------------------------------------------------------------------------
4776df26cacSmrg *
4786df26cacSmrg * vmwareVideoEnd --
4796df26cacSmrg *
4806df26cacSmrg *    Unitializes video.
4816df26cacSmrg *
4826df26cacSmrg * Results:
4836df26cacSmrg *    None.
4846df26cacSmrg *
4856df26cacSmrg * Side effects:
4866df26cacSmrg *    pVMWARE->videoStreams = NULL
4876df26cacSmrg *
4886df26cacSmrg *-----------------------------------------------------------------------------
4896df26cacSmrg */
4906df26cacSmrg
49116fd1166Smrgvoid
49216fd1166SmrgvmwareVideoEnd(ScreenPtr pScreen)
4936df26cacSmrg{
4946df26cacSmrg    ScrnInfoPtr pScrn = infoFromScreen(pScreen);
4956df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
4966df26cacSmrg    VMWAREVideoPtr pVid;
4976df26cacSmrg    int i;
4986df26cacSmrg
4996df26cacSmrg    TRACEPOINT
5006df26cacSmrg
5016df26cacSmrg    /*
5026df26cacSmrg     * Video streams are allocated after the DevUnion array
5036df26cacSmrg     * (see VideoSetup)
5046df26cacSmrg     */
5056df26cacSmrg    pVid = (VMWAREVideoPtr) &pVMWARE->videoStreams[VMWARE_VID_NUM_PORTS];
5066df26cacSmrg    for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
5076df26cacSmrg        vmwareVideoEndStream(pScrn, &pVid[i]);
5086df26cacSmrg    }
5096df26cacSmrg
5106df26cacSmrg    free(pVMWARE->videoStreams);
5116df26cacSmrg    pVMWARE->videoStreams = NULL;
5126df26cacSmrg}
5136df26cacSmrg
5146df26cacSmrg
5156df26cacSmrg/*
5166df26cacSmrg *-----------------------------------------------------------------------------
5176df26cacSmrg *
5186df26cacSmrg * vmwareVideoSetup --
5196df26cacSmrg *
5206df26cacSmrg *    Initializes a XF86VideoAdaptor structure with the capabilities and
5216df26cacSmrg *    functions supported by this video driver.
5226df26cacSmrg *
5236df26cacSmrg * Results:
5246df26cacSmrg *    On success initialized XF86VideoAdaptor struct or NULL on error
5256df26cacSmrg *
5266df26cacSmrg * Side effects:
5276df26cacSmrg *    None.
5286df26cacSmrg *
5296df26cacSmrg *-----------------------------------------------------------------------------
5306df26cacSmrg */
5316df26cacSmrg
53216fd1166Smrgstatic XF86VideoAdaptorPtr
53316fd1166SmrgvmwareVideoSetup(ScrnInfoPtr pScrn)
5346df26cacSmrg{
5356df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
5366df26cacSmrg    XF86VideoAdaptorPtr adaptor;
5376df26cacSmrg    VMWAREVideoPtr pPriv;
5386df26cacSmrg    DevUnion *du;
5396df26cacSmrg    int i;
5406df26cacSmrg
5416df26cacSmrg    TRACEPOINT
5426df26cacSmrg
5436df26cacSmrg    adaptor = xf86XVAllocateVideoAdaptorRec(pScrn);
5446df26cacSmrg    if (!adaptor) {
5456df26cacSmrg        VmwareLog(("Not enough memory\n"));
5466df26cacSmrg        return NULL;
5476df26cacSmrg    }
5486df26cacSmrg    du = xcalloc(1, VMWARE_VID_NUM_PORTS *
5496df26cacSmrg        (sizeof(DevUnion) + sizeof(VMWAREVideoRec)));
5506df26cacSmrg
5516df26cacSmrg    if (!du) {
5526df26cacSmrg        VmwareLog(("Not enough memory.\n"));
5536df26cacSmrg        xf86XVFreeVideoAdaptorRec(adaptor);
5546df26cacSmrg        return NULL;
5556df26cacSmrg    }
5566df26cacSmrg
5576df26cacSmrg    adaptor->type = XvInputMask | XvImageMask | XvWindowMask;
5586df26cacSmrg    adaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
5596df26cacSmrg    adaptor->name = "VMware Video Engine";
5606df26cacSmrg    adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS;
5616df26cacSmrg    adaptor->pEncodings = vmwareVideoEncodings;
5626df26cacSmrg    adaptor->nFormats = VMWARE_VID_NUM_FORMATS;
5636df26cacSmrg    adaptor->pFormats = vmwareVideoFormats;
5646df26cacSmrg    adaptor->nPorts = VMWARE_VID_NUM_PORTS;
5656df26cacSmrg
5666df26cacSmrg    pPriv = (VMWAREVideoPtr) &du[VMWARE_VID_NUM_PORTS];
5676df26cacSmrg    adaptor->pPortPrivates = du;
5686df26cacSmrg
5696df26cacSmrg    for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
5706df26cacSmrg        pPriv[i].streamId = i;
5716df26cacSmrg        pPriv[i].play = vmwareVideoInitStream;
5726df26cacSmrg        pPriv[i].flags = SVGA_VIDEO_FLAG_COLORKEY;
5736df26cacSmrg        pPriv[i].colorKey = VMWARE_VIDEO_COLORKEY;
57416fd1166Smrg        pPriv[i].isAutoPaintColorkey = TRUE;
5756df26cacSmrg        adaptor->pPortPrivates[i].ptr = &pPriv[i];
5766df26cacSmrg    }
5776df26cacSmrg    pVMWARE->videoStreams = du;
5786df26cacSmrg
5796df26cacSmrg    adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES;
5806df26cacSmrg    adaptor->pAttributes = vmwareVideoAttributes;
5816df26cacSmrg
5826df26cacSmrg    adaptor->nImages = VMWARE_VID_NUM_IMAGES;
5836df26cacSmrg    adaptor->pImages = vmwareVideoImages;
5846df26cacSmrg
5856df26cacSmrg    adaptor->PutVideo = NULL;
5866df26cacSmrg    adaptor->PutStill = NULL;
5876df26cacSmrg    adaptor->GetVideo = NULL;
5886df26cacSmrg    adaptor->GetStill = NULL;
5896df26cacSmrg    adaptor->StopVideo = vmwareStopVideo;
5906df26cacSmrg    adaptor->SetPortAttribute = vmwareSetPortAttribute;
5916df26cacSmrg    adaptor->GetPortAttribute = vmwareGetPortAttribute;
5926df26cacSmrg    adaptor->QueryBestSize = vmwareQueryBestSize;
5936df26cacSmrg    adaptor->PutImage = vmwareXvPutImage;
5946df26cacSmrg    adaptor->QueryImageAttributes = vmwareQueryImageAttributes;
5956df26cacSmrg
5966df26cacSmrg    return adaptor;
5976df26cacSmrg}
5986df26cacSmrg
5996df26cacSmrg
6006df26cacSmrg/*
6016df26cacSmrg *-----------------------------------------------------------------------------
6026df26cacSmrg *
6036df26cacSmrg * vmwareVideoInitStream --
6046df26cacSmrg *
6056df26cacSmrg *    Initializes a video stream in response to the first PutImage() on a
6066df26cacSmrg *    video stream. The process goes as follows:
6076df26cacSmrg *    - Figure out characteristics according to format
6086df26cacSmrg *    - Allocate offscreen memory
6096df26cacSmrg *    - Pass on video to Play() functions
6106df26cacSmrg *
6116df26cacSmrg * Results:
6126df26cacSmrg *    Success or XvBadAlloc on failure.
6136df26cacSmrg *
6146df26cacSmrg * Side effects:
6156df26cacSmrg *    Video stream is initialized and its first frame sent to the host
6166df26cacSmrg *    (done by VideoPlay() function called at the end)
6176df26cacSmrg *
6186df26cacSmrg *-----------------------------------------------------------------------------
6196df26cacSmrg */
6206df26cacSmrg
62116fd1166Smrgstatic int
62216fd1166SmrgvmwareVideoInitStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
62316fd1166Smrg                      short src_x, short src_y, short drw_x,
62416fd1166Smrg                      short drw_y, short src_w, short src_h,
62516fd1166Smrg                      short drw_w, short drw_h, int format,
62616fd1166Smrg                      unsigned char *buf, short width,
62716fd1166Smrg                      short height, RegionPtr clipBoxes)
6286df26cacSmrg{
6296df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
6306df26cacSmrg    int i;
6316df26cacSmrg
6326df26cacSmrg    TRACEPOINT
6336df26cacSmrg
6346df26cacSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
6356df26cacSmrg               "Initializing Xv video-stream with id:%d format:%d\n",
6366df26cacSmrg                pVid->streamId, format);
6376df26cacSmrg
6386df26cacSmrg    pVid->size = vmwareVideoInitAttributes(pScrn, pVid, format, width,
6396df26cacSmrg                                           height);
6406df26cacSmrg
6416df26cacSmrg    if (pVid->size == -1) {
6426df26cacSmrg        VmwareLog(("Could not initialize 0x%x video stream\n", format));
6436df26cacSmrg        return XvBadAlloc;
6446df26cacSmrg    }
6456df26cacSmrg
6466df26cacSmrg    pVid->play = vmwareVideoPlay;
6476df26cacSmrg
6486df26cacSmrg    pVid->fbarea = vmwareOffscreenAllocate(pVMWARE,
6496df26cacSmrg                       pVid->size * VMWARE_VID_NUM_BUFFERS);
6506df26cacSmrg
6516df26cacSmrg    if (!pVid->fbarea) {
6526df26cacSmrg       VmwareLog(("Could not allocate offscreen memory\n"));
6536df26cacSmrg       vmwareVideoEndStream(pScrn, pVid);
6546df26cacSmrg       return BadAlloc;
6556df26cacSmrg    }
6566df26cacSmrg
6576df26cacSmrg    pVid->bufs[0].dataOffset = pVid->fbarea->offset;
6586df26cacSmrg    pVid->bufs[0].data = pVMWARE->FbBase + pVid->bufs[0].dataOffset;
6596df26cacSmrg
6606df26cacSmrg    for (i = 1; i < VMWARE_VID_NUM_BUFFERS; ++i) {
6616df26cacSmrg        pVid->bufs[i].dataOffset = pVid->bufs[i-1].dataOffset + pVid->size;
6626df26cacSmrg        pVid->bufs[i].data = pVMWARE->FbBase + pVid->bufs[i].dataOffset;
6636df26cacSmrg    }
6646df26cacSmrg    pVid->currBuf = 0;
6656df26cacSmrg
66616fd1166Smrg    REGION_COPY(pScrn->pScreen, &pVid->clipBoxes, clipBoxes);
66716fd1166Smrg
66816fd1166Smrg    if (pVid->isAutoPaintColorkey) {
66916fd1166Smrg        xf86XVFillKeyHelper(pScrn->pScreen, pVid->colorKey, clipBoxes);
67016fd1166Smrg    }
67116fd1166Smrg
6726df26cacSmrg    VmwareLog(("Got offscreen region, offset %d, size %d "
6736df26cacSmrg               "(yuv size in bytes: %d)\n",
6746df26cacSmrg               pVid->fbarea->offset, pVid->fbarea->size, pVid->size));
6756df26cacSmrg
6766df26cacSmrg    return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w, src_h,
67716fd1166Smrg                      drw_w, drw_h, format, buf, width, height, clipBoxes);
6786df26cacSmrg}
6796df26cacSmrg
6806df26cacSmrg
6816df26cacSmrg/*
6826df26cacSmrg *-----------------------------------------------------------------------------
6836df26cacSmrg *
6846df26cacSmrg * vmwareVideoInitAttributes --
6856df26cacSmrg *
6866df26cacSmrg *    Fetches the format specific attributes using QueryImageAttributes().
6876df26cacSmrg *
6886df26cacSmrg * Results:
6896df26cacSmrg *    size of the YUV frame on success and -1 on error.
6906df26cacSmrg *
6916df26cacSmrg * Side effects:
6926df26cacSmrg *    The video stream gets the format specific attributes(fmtData).
6936df26cacSmrg *
6946df26cacSmrg *-----------------------------------------------------------------------------
6956df26cacSmrg */
6966df26cacSmrg
69716fd1166Smrgstatic int
69816fd1166SmrgvmwareVideoInitAttributes(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
69916fd1166Smrg                          int format, unsigned short width,
70016fd1166Smrg                          unsigned short height)
7016df26cacSmrg{
7026df26cacSmrg    int size;
7036df26cacSmrg    VMWAREVideoFmtData *fmtData;
7046df26cacSmrg
7056df26cacSmrg    TRACEPOINT
7066df26cacSmrg
7076df26cacSmrg    fmtData = xcalloc(1, sizeof(VMWAREVideoFmtData));
7086df26cacSmrg    if (!fmtData) {
7096df26cacSmrg        return -1;
7106df26cacSmrg    }
7116df26cacSmrg
7126df26cacSmrg    size = vmwareQueryImageAttributes(pScrn, format, &width, &height,
7136df26cacSmrg                                      fmtData->pitches, fmtData->offsets);
7146df26cacSmrg    if (size == -1) {
7156df26cacSmrg        free(fmtData);
7166df26cacSmrg        return -1;
7176df26cacSmrg    }
7186df26cacSmrg
7196df26cacSmrg    pVid->fmt_priv = fmtData;
7206df26cacSmrg    return size;
7216df26cacSmrg}
7226df26cacSmrg
7236df26cacSmrg
7246df26cacSmrg/*
7256df26cacSmrg *-----------------------------------------------------------------------------
7266df26cacSmrg *
7276df26cacSmrg * vmwareVideoPlay --
7286df26cacSmrg *
7296df26cacSmrg *    Sends all the attributes associated with the video frame using the
7306df26cacSmrg *    FIFO ESCAPE mechanism to the host.
7316df26cacSmrg *
7326df26cacSmrg * Results:
7336df26cacSmrg *    Always returns Success.
7346df26cacSmrg *
7356df26cacSmrg * Side effects:
7366df26cacSmrg *    None.
7376df26cacSmrg *
7386df26cacSmrg *-----------------------------------------------------------------------------
7396df26cacSmrg */
7406df26cacSmrg
74116fd1166Smrgstatic int
74216fd1166SmrgvmwareVideoPlay(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
74316fd1166Smrg                short src_x, short src_y, short drw_x,
74416fd1166Smrg                short drw_y, short src_w, short src_h,
74516fd1166Smrg                short drw_w, short drw_h, int format,
74616fd1166Smrg                unsigned char *buf, short width,
74716fd1166Smrg                short height, RegionPtr clipBoxes)
7486df26cacSmrg{
7496df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
7506df26cacSmrg    uint32 *fifoItem;
7516df26cacSmrg    int i, regId;
7526df26cacSmrg    struct PACKED _item {
7536df26cacSmrg        uint32 regId;
7546df26cacSmrg        uint32 value;
7556df26cacSmrg    };
7566df26cacSmrg
7576df26cacSmrg    struct PACKED _body {
7586df26cacSmrg        uint32 escape;
7596df26cacSmrg        uint32 streamId;
7606df26cacSmrg        struct _item items[SVGA_VIDEO_NUM_REGS];
7616df26cacSmrg    };
7626df26cacSmrg
7636df26cacSmrg    struct PACKED _cmdSetRegs {
7646df26cacSmrg        uint32 cmd;
7656df26cacSmrg        uint32 nsid;
7666df26cacSmrg        uint32 size;
7676df26cacSmrg        struct _body body;
7686df26cacSmrg    };
7696df26cacSmrg
7706df26cacSmrg    struct _cmdSetRegs cmdSetRegs;
7716df26cacSmrg    struct _item *items;
77216fd1166Smrg    int size;
77316fd1166Smrg    VMWAREVideoFmtData *fmtData;
77416fd1166Smrg    unsigned short w, h;
7756df26cacSmrg
77616fd1166Smrg    w = width;
77716fd1166Smrg    h = height;
77816fd1166Smrg    fmtData = pVid->fmt_priv;
77916fd1166Smrg
78016fd1166Smrg    size = vmwareQueryImageAttributes(pScrn, format, &w, &h,
78116fd1166Smrg                                      fmtData->pitches, fmtData->offsets);
78216fd1166Smrg
78316fd1166Smrg    if (size > pVid->size) {
78416fd1166Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Increase in size of Xv video "
78516fd1166Smrg                   "frame streamId:%d.\n", pVid->streamId);
78616fd1166Smrg        vmwareStopVideo(pScrn, pVid, TRUE);
78716fd1166Smrg        return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w,
78816fd1166Smrg                          src_h, drw_w, drw_h, format, buf, width, height,
78916fd1166Smrg                          clipBoxes);
79016fd1166Smrg    }
79116fd1166Smrg
79216fd1166Smrg    pVid->size = size;
7936df26cacSmrg    memcpy(pVid->bufs[pVid->currBuf].data, buf, pVid->size);
7946df26cacSmrg
7956df26cacSmrg    cmdSetRegs.cmd = SVGA_CMD_ESCAPE;
7966df26cacSmrg    cmdSetRegs.nsid = SVGA_ESCAPE_NSID_VMWARE;
7976df26cacSmrg    cmdSetRegs.size = sizeof(cmdSetRegs.body);
7986df26cacSmrg    cmdSetRegs.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
7996df26cacSmrg    cmdSetRegs.body.streamId = pVid->streamId;
8006df26cacSmrg
8016df26cacSmrg    items = cmdSetRegs.body.items;
8026df26cacSmrg    for (i = SVGA_VIDEO_ENABLED; i < SVGA_VIDEO_NUM_REGS; i++) {
8036df26cacSmrg        items[i].regId = i;
8046df26cacSmrg    }
8056df26cacSmrg
8066df26cacSmrg    items[SVGA_VIDEO_ENABLED].value = TRUE;
8076df26cacSmrg    items[SVGA_VIDEO_DATA_OFFSET].value =
8086df26cacSmrg        pVid->bufs[pVid->currBuf].dataOffset;
8096df26cacSmrg    items[SVGA_VIDEO_SIZE].value = pVid->size;
8106df26cacSmrg    items[SVGA_VIDEO_FORMAT].value = format;
81116fd1166Smrg    items[SVGA_VIDEO_WIDTH].value = w;
81216fd1166Smrg    items[SVGA_VIDEO_HEIGHT].value = h;
8136df26cacSmrg    items[SVGA_VIDEO_SRC_X].value = src_x;
8146df26cacSmrg    items[SVGA_VIDEO_SRC_Y].value = src_y;
8156df26cacSmrg    items[SVGA_VIDEO_SRC_WIDTH].value = src_w;
8166df26cacSmrg    items[SVGA_VIDEO_SRC_HEIGHT].value = src_h;
8176df26cacSmrg    items[SVGA_VIDEO_DST_X].value = drw_x;
8186df26cacSmrg    items[SVGA_VIDEO_DST_Y].value = drw_y;
8196df26cacSmrg    items[SVGA_VIDEO_DST_WIDTH]. value = drw_w;
8206df26cacSmrg    items[SVGA_VIDEO_DST_HEIGHT].value = drw_h;
8216df26cacSmrg    items[SVGA_VIDEO_COLORKEY].value = pVid->colorKey;
8226df26cacSmrg    items[SVGA_VIDEO_FLAGS].value = pVid->flags;
8236df26cacSmrg
8246df26cacSmrg    for (i = 0, regId = SVGA_VIDEO_PITCH_1; i < 3; i++, regId++) {
82516fd1166Smrg        items[regId].value = fmtData->pitches[i];
8266df26cacSmrg    }
8276df26cacSmrg
8286df26cacSmrg    fifoItem = (uint32 *) &cmdSetRegs;
8296df26cacSmrg    for (i = 0; i <  sizeof(cmdSetRegs) / sizeof(uint32); i++) {
8306df26cacSmrg        vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]);
8316df26cacSmrg    }
8326df26cacSmrg
83316fd1166Smrg    /*
83416fd1166Smrg     *  Update the clipList and paint the colorkey, if required.
83516fd1166Smrg     */
83616fd1166Smrg    if (!vmwareIsRegionEqual(&pVid->clipBoxes, clipBoxes)) {
83716fd1166Smrg        REGION_COPY(pScrn->pScreen, &pVid->clipBoxes, clipBoxes);
83816fd1166Smrg        if (pVid->isAutoPaintColorkey) {
83916fd1166Smrg            xf86XVFillKeyHelper(pScrn->pScreen, pVid->colorKey, clipBoxes);
84016fd1166Smrg        }
84116fd1166Smrg    }
84216fd1166Smrg
8436df26cacSmrg    vmwareVideoFlush(pVMWARE, pVid->streamId);
8446df26cacSmrg
8456df26cacSmrg    pVid->currBuf = ++pVid->currBuf & (VMWARE_VID_NUM_BUFFERS - 1);
84616fd1166Smrg
8476df26cacSmrg    return Success;
8486df26cacSmrg}
8496df26cacSmrg
8506df26cacSmrg
8516df26cacSmrg/*
8526df26cacSmrg *-----------------------------------------------------------------------------
8536df26cacSmrg *
8546df26cacSmrg * vmwareVideoFlush --
8556df26cacSmrg *
8566df26cacSmrg *    Sends the VIDEO_FLUSH command (FIFO ESCAPE mechanism) asking the host
8576df26cacSmrg *    to play the video stream or end it.
8586df26cacSmrg *
8596df26cacSmrg * Results:
8606df26cacSmrg *    None.
8616df26cacSmrg *
8626df26cacSmrg * Side effects:
8636df26cacSmrg *    None.
8646df26cacSmrg *
8656df26cacSmrg *-----------------------------------------------------------------------------
8666df26cacSmrg */
8676df26cacSmrg
86816fd1166Smrgstatic void
86916fd1166SmrgvmwareVideoFlush(VMWAREPtr pVMWARE, uint32 streamId)
8706df26cacSmrg{
8716df26cacSmrg    struct PACKED _body {
8726df26cacSmrg        uint32 escape;
8736df26cacSmrg        uint32 streamId;
8746df26cacSmrg    };
8756df26cacSmrg
8766df26cacSmrg    struct PACKED _cmdFlush {
8776df26cacSmrg        uint32 cmd;
8786df26cacSmrg        uint32 nsid;
8796df26cacSmrg        uint32 size;
8806df26cacSmrg        struct _body body;
8816df26cacSmrg    };
8826df26cacSmrg
8836df26cacSmrg    struct _cmdFlush cmdFlush;
8846df26cacSmrg    uint32 *fifoItem;
8856df26cacSmrg    int i;
8866df26cacSmrg
8876df26cacSmrg    cmdFlush.cmd = SVGA_CMD_ESCAPE;
8886df26cacSmrg    cmdFlush.nsid = SVGA_ESCAPE_NSID_VMWARE;
8896df26cacSmrg    cmdFlush.size = sizeof(cmdFlush.body);
8906df26cacSmrg    cmdFlush.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_FLUSH;
8916df26cacSmrg    cmdFlush.body.streamId = streamId;
8926df26cacSmrg
8936df26cacSmrg    fifoItem = (uint32 *) &cmdFlush;
8946df26cacSmrg    for (i = 0; i < sizeof(cmdFlush) / sizeof(uint32); i++) {
8956df26cacSmrg        vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]);
8966df26cacSmrg    }
8976df26cacSmrg}
8986df26cacSmrg
8996df26cacSmrg
9006df26cacSmrg/*
9016df26cacSmrg *-----------------------------------------------------------------------------
9026df26cacSmrg *
9036df26cacSmrg * vmwareVideoSetOneReg --
9046df26cacSmrg *
9056df26cacSmrg *    Sets one video register using the FIFO ESCAPE mechanidm.
9066df26cacSmrg *
9076df26cacSmrg * Results:
9086df26cacSmrg *    None.
9096df26cacSmrg *
9106df26cacSmrg * Side effects:
9116df26cacSmrg *    None.
9126df26cacSmrg *-----------------------------------------------------------------------------
9136df26cacSmrg */
9146df26cacSmrg
91516fd1166Smrgstatic void
91616fd1166SmrgvmwareVideoSetOneReg(VMWAREPtr pVMWARE, uint32 streamId,
91716fd1166Smrg                     uint32 regId, uint32 value)
9186df26cacSmrg{
9196df26cacSmrg    struct PACKED _item {
9206df26cacSmrg        uint32 regId;
9216df26cacSmrg        uint32 value;
9226df26cacSmrg    };
9236df26cacSmrg
9246df26cacSmrg    struct PACKED _body {
9256df26cacSmrg        uint32 escape;
9266df26cacSmrg        uint32 streamId;
9276df26cacSmrg        struct _item item;
9286df26cacSmrg    };
9296df26cacSmrg
9306df26cacSmrg    struct PACKED _cmdSetRegs {
9316df26cacSmrg        uint32 cmd;
9326df26cacSmrg        uint32 nsid;
9336df26cacSmrg        uint32 size;
9346df26cacSmrg        struct _body body;
9356df26cacSmrg    };
9366df26cacSmrg
9376df26cacSmrg    struct _cmdSetRegs cmdSetRegs;
9386df26cacSmrg    int i;
9396df26cacSmrg    uint32 *fifoItem;
9406df26cacSmrg
9416df26cacSmrg    cmdSetRegs.cmd = SVGA_CMD_ESCAPE;
9426df26cacSmrg    cmdSetRegs.nsid = SVGA_ESCAPE_NSID_VMWARE;
9436df26cacSmrg    cmdSetRegs.size = sizeof(cmdSetRegs.body);
9446df26cacSmrg    cmdSetRegs.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
9456df26cacSmrg    cmdSetRegs.body.streamId = streamId;
9466df26cacSmrg    cmdSetRegs.body.item.regId = regId;
9476df26cacSmrg    cmdSetRegs.body.item.value = value;
9486df26cacSmrg
9496df26cacSmrg    fifoItem = (uint32 *) &cmdSetRegs;
9506df26cacSmrg    for (i = 0; i < sizeof(cmdSetRegs) / sizeof(uint32); i++) {
9516df26cacSmrg        vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]);
9526df26cacSmrg    }
9536df26cacSmrg}
9546df26cacSmrg
9556df26cacSmrg
9566df26cacSmrg/*
9576df26cacSmrg *-----------------------------------------------------------------------------
9586df26cacSmrg *
9596df26cacSmrg * vmwareVideoEndStream --
9606df26cacSmrg *
9616df26cacSmrg *    Frees up all resources (if any) taken by a video stream.
9626df26cacSmrg *
9636df26cacSmrg * Results:
9646df26cacSmrg *    None.
9656df26cacSmrg *
9666df26cacSmrg * Side effects:
9676df26cacSmrg *    Same as above.
9686df26cacSmrg *
9696df26cacSmrg *-----------------------------------------------------------------------------
9706df26cacSmrg */
9716df26cacSmrg
97216fd1166Smrgstatic void
97316fd1166SmrgvmwareVideoEndStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid)
9746df26cacSmrg{
9756df26cacSmrg    uint32 id, colorKey, flags;
97616fd1166Smrg    Bool isAutoPaintColorkey;
9776df26cacSmrg
9786df26cacSmrg    if (pVid->fmt_priv) {
9796df26cacSmrg        free(pVid->fmt_priv);
9806df26cacSmrg    }
9816df26cacSmrg
9826df26cacSmrg    if (pVid->fbarea) {
9836df26cacSmrg        vmwareOffscreenFree(pVid->fbarea);
9846df26cacSmrg        pVid->fbarea =  NULL;
9856df26cacSmrg    }
9866df26cacSmrg
9876df26cacSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
9886df26cacSmrg               "Terminating Xv video-stream id:%d\n", pVid->streamId);
9896df26cacSmrg    /*
9906df26cacSmrg     * reset stream for next video
9916df26cacSmrg     */
9926df26cacSmrg    id = pVid->streamId;
9936df26cacSmrg    colorKey = pVid->colorKey;
9946df26cacSmrg    flags = pVid->flags;
99516fd1166Smrg    isAutoPaintColorkey = pVid->isAutoPaintColorkey;
99616fd1166Smrg
9976df26cacSmrg    memset(pVid, 0, sizeof(*pVid));
99816fd1166Smrg
9996df26cacSmrg    pVid->streamId = id;
10006df26cacSmrg    pVid->play = vmwareVideoInitStream;
10016df26cacSmrg    pVid->colorKey = colorKey;
10026df26cacSmrg    pVid->flags = flags;
100316fd1166Smrg    pVid->isAutoPaintColorkey = isAutoPaintColorkey;
10046df26cacSmrg}
10056df26cacSmrg
10066df26cacSmrg
10076df26cacSmrg/*
10086df26cacSmrg *-----------------------------------------------------------------------------
10096df26cacSmrg *
10106df26cacSmrg * vmwareXvPutImage --
10116df26cacSmrg *
10126df26cacSmrg *    Main video playback function. It copies the passed data which is in
10136df26cacSmrg *    the specified format (e.g. FOURCC_YV12) into the overlay.
10146df26cacSmrg *
10156df26cacSmrg *    If sync is TRUE the driver should not return from this
10166df26cacSmrg *    function until it is through reading the data from buf.
10176df26cacSmrg *
10186df26cacSmrg *    There are two function prototypes to cope with the API change in X.org
10196df26cacSmrg *    7.1
10206df26cacSmrg *
10216df26cacSmrg * Results:
10226df26cacSmrg *    Success or XvBadAlloc on failure
10236df26cacSmrg *
10246df26cacSmrg * Side effects:
10256df26cacSmrg *    Video stream will be played(initialized if 1st frame) on success
10266df26cacSmrg *    or will fail on error.
10276df26cacSmrg *
10286df26cacSmrg *-----------------------------------------------------------------------------
10296df26cacSmrg */
10306df26cacSmrg
103116fd1166Smrg#ifdef HAVE_XORG_SERVER_1_0_99_901
103216fd1166Smrgstatic int
103316fd1166SmrgvmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
103416fd1166Smrg                 short drw_x, short drw_y, short src_w, short src_h,
103516fd1166Smrg                 short drw_w, short drw_h, int format,
103616fd1166Smrg                 unsigned char *buf, short width, short height,
103716fd1166Smrg                 Bool sync, RegionPtr clipBoxes, pointer data,
103816fd1166Smrg                 DrawablePtr dst)
10396df26cacSmrg#else
104016fd1166Smrgstatic int
104116fd1166SmrgvmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
104216fd1166Smrg                 short drw_x, short drw_y, short src_w, short src_h,
104316fd1166Smrg                 short drw_w, short drw_h, int format,
104416fd1166Smrg                 unsigned char *buf, short width, short height,
104516fd1166Smrg                 Bool sync, RegionPtr clipBoxes, pointer data)
10466df26cacSmrg#endif
10476df26cacSmrg{
10486df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
10496df26cacSmrg    VMWAREVideoPtr pVid = data;
10506df26cacSmrg
10516df26cacSmrg    TRACEPOINT
10526df26cacSmrg
10536df26cacSmrg    if (!vmwareVideoEnabled(pVMWARE)) {
10546df26cacSmrg        return XvBadAlloc;
10556df26cacSmrg    }
10566df26cacSmrg
10576df26cacSmrg    return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w, src_h,
105816fd1166Smrg                      drw_w, drw_h, format, buf, width, height, clipBoxes);
10596df26cacSmrg}
10606df26cacSmrg
10616df26cacSmrg
10626df26cacSmrg/*
10636df26cacSmrg *-----------------------------------------------------------------------------
10646df26cacSmrg *
10656df26cacSmrg * vmwareStopVideo --
10666df26cacSmrg *
10676df26cacSmrg *    Called when we should stop playing video for a particular stream. If
10686df26cacSmrg *    Cleanup is FALSE, the "stop" operation is only temporary, and thus we
10696df26cacSmrg *    don't do anything. If Cleanup is TRUE we kill the video stream by
10706df26cacSmrg *    sending a message to the host and freeing up the stream.
10716df26cacSmrg *
10726df26cacSmrg * Results:
10736df26cacSmrg *    None.
10746df26cacSmrg *
10756df26cacSmrg * Side effects:
10766df26cacSmrg *    See above.
10776df26cacSmrg *
10786df26cacSmrg *-----------------------------------------------------------------------------
10796df26cacSmrg */
10806df26cacSmrg
108116fd1166Smrgstatic void
108216fd1166SmrgvmwareStopVideo(ScrnInfoPtr pScrn, pointer data, Bool Cleanup)
10836df26cacSmrg{
10846df26cacSmrg    VMWAREVideoPtr pVid = data;
10856df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
10866df26cacSmrg    TRACEPOINT
10876df26cacSmrg
10886df26cacSmrg    if (!vmwareVideoEnabled(pVMWARE)) {
10896df26cacSmrg        return;
10906df26cacSmrg    }
10916df26cacSmrg    if (!Cleanup) {
109216fd1166Smrg        VmwareLog(("vmwareStopVideo: Cleanup is FALSE.\n"));
10936df26cacSmrg        return;
10946df26cacSmrg    }
10956df26cacSmrg    vmwareVideoSetOneReg(pVMWARE, pVid->streamId,
10966df26cacSmrg                         SVGA_VIDEO_ENABLED, FALSE);
10976df26cacSmrg
10986df26cacSmrg    vmwareVideoFlush(pVMWARE, pVid->streamId);
10996df26cacSmrg    vmwareVideoEndStream(pScrn, pVid);
11006df26cacSmrg
11016df26cacSmrg}
11026df26cacSmrg
11036df26cacSmrg
11046df26cacSmrg/*
11056df26cacSmrg *-----------------------------------------------------------------------------
11066df26cacSmrg *
11076df26cacSmrg * vmwareQueryImageAttributes --
11086df26cacSmrg *
11096df26cacSmrg *    From the spec: This function is called to let the driver specify how data
11106df26cacSmrg *    for a particular image of size width by height should be stored.
11116df26cacSmrg *    Sometimes only the size and corrected width and height are needed. In
11126df26cacSmrg *    that case pitches and offsets are NULL.
11136df26cacSmrg *
11146df26cacSmrg * Results:
11156df26cacSmrg *    The size of the memory required for the image, or -1 on error.
11166df26cacSmrg *
11176df26cacSmrg * Side effects:
11186df26cacSmrg *    None.
11196df26cacSmrg *
11206df26cacSmrg *-----------------------------------------------------------------------------
11216df26cacSmrg */
11226df26cacSmrg
112316fd1166Smrgstatic int
112416fd1166SmrgvmwareQueryImageAttributes(ScrnInfoPtr pScrn, int format,
112516fd1166Smrg                           unsigned short *width, unsigned short *height,
112616fd1166Smrg                           int *pitches, int *offsets)
11276df26cacSmrg{
11286df26cacSmrg    INT32 size, tmp;
11296df26cacSmrg
11306df26cacSmrg    TRACEPOINT
11316df26cacSmrg
11326df26cacSmrg    if (*width > VMWARE_VID_MAX_WIDTH) {
11336df26cacSmrg        *width = VMWARE_VID_MAX_WIDTH;
11346df26cacSmrg    }
11356df26cacSmrg    if (*height > VMWARE_VID_MAX_HEIGHT) {
11366df26cacSmrg        *height = VMWARE_VID_MAX_HEIGHT;
11376df26cacSmrg    }
11386df26cacSmrg
11396df26cacSmrg    *width = (*width + 1) & ~1;
11406df26cacSmrg    if (offsets != NULL) {
11416df26cacSmrg        offsets[0] = 0;
11426df26cacSmrg    }
11436df26cacSmrg
11446df26cacSmrg    switch (format) {
11456df26cacSmrg       case FOURCC_YV12:
11466df26cacSmrg           *height = (*height + 1) & ~1;
11476df26cacSmrg           size = (*width + 3) & ~3;
11486df26cacSmrg           if (pitches) {
11496df26cacSmrg               pitches[0] = size;
11506df26cacSmrg           }
11516df26cacSmrg           size *= *height;
11526df26cacSmrg           if (offsets) {
11536df26cacSmrg               offsets[1] = size;
11546df26cacSmrg           }
11556df26cacSmrg           tmp = ((*width >> 1) + 3) & ~3;
11566df26cacSmrg           if (pitches) {
11576df26cacSmrg                pitches[1] = pitches[2] = tmp;
11586df26cacSmrg           }
11596df26cacSmrg           tmp *= (*height >> 1);
11606df26cacSmrg           size += tmp;
11616df26cacSmrg           if (offsets) {
11626df26cacSmrg               offsets[2] = size;
11636df26cacSmrg           }
11646df26cacSmrg           size += tmp;
11656df26cacSmrg           break;
116616fd1166Smrg       case FOURCC_UYVY:
11676df26cacSmrg       case FOURCC_YUY2:
11686df26cacSmrg           size = *width * 2;
11696df26cacSmrg           if (pitches) {
11706df26cacSmrg               pitches[0] = size;
11716df26cacSmrg           }
11726df26cacSmrg           size *= *height;
11736df26cacSmrg           break;
11746df26cacSmrg       default:
11756df26cacSmrg           VmwareLog(("Query for invalid video format %d\n", format));
11766df26cacSmrg           return -1;
11776df26cacSmrg    }
11786df26cacSmrg    return size;
11796df26cacSmrg}
11806df26cacSmrg
11816df26cacSmrg
11826df26cacSmrg/*
11836df26cacSmrg *-----------------------------------------------------------------------------
11846df26cacSmrg *
11856df26cacSmrg * vmwareSetPortAttribute --
11866df26cacSmrg *
11876df26cacSmrg *    From the spec: A port may have particular attributes such as colorKey, hue,
11886df26cacSmrg *    saturation, brightness or contrast. Xv clients set these
11896df26cacSmrg *    attribute values by sending attribute strings (Atoms) to the server.
11906df26cacSmrg *
11916df26cacSmrg * Results:
11926df26cacSmrg *    Success if the attribute exists and XvBadAlloc otherwise.
11936df26cacSmrg *
11946df26cacSmrg * Side effects:
11956df26cacSmrg *    The respective attribute gets the new value.
11966df26cacSmrg *
11976df26cacSmrg *-----------------------------------------------------------------------------
11986df26cacSmrg */
11996df26cacSmrg
120016fd1166Smrgstatic int
120116fd1166SmrgvmwareSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
120216fd1166Smrg                       INT32 value, pointer data)
12036df26cacSmrg{
12046df26cacSmrg    VMWAREVideoPtr pVid = (VMWAREVideoPtr) data;
12056df26cacSmrg    Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
120616fd1166Smrg    Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
12076df26cacSmrg
12086df26cacSmrg    if (attribute == xvColorKey) {
120916fd1166Smrg        VmwareLog(("Set colorkey:0x%x\n", value));
12106df26cacSmrg        pVid->colorKey = value;
121116fd1166Smrg    } else if (attribute == xvAutoPaint) {
121216fd1166Smrg        VmwareLog(("Set autoPaint: %s\n", value? "TRUE": "FALSE"));
121316fd1166Smrg        pVid->isAutoPaintColorkey = value;
12146df26cacSmrg    } else {
12156df26cacSmrg        return XvBadAlloc;
12166df26cacSmrg    }
121716fd1166Smrg
12186df26cacSmrg    return Success;
12196df26cacSmrg}
12206df26cacSmrg
12216df26cacSmrg
12226df26cacSmrg/*
12236df26cacSmrg *-----------------------------------------------------------------------------
12246df26cacSmrg *
12256df26cacSmrg * vmwareGetPortAttribute --
12266df26cacSmrg *
12276df26cacSmrg *    From the spec: A port may have particular attributes such as hue,
12286df26cacSmrg *    saturation, brightness or contrast. Xv clients get these
12296df26cacSmrg *    attribute values by sending attribute strings (Atoms) to the server
12306df26cacSmrg *
12316df26cacSmrg * Results:
12326df26cacSmrg *    Success if the attribute exists and XvBadAlloc otherwise.
12336df26cacSmrg *
12346df26cacSmrg * Side effects:
12356df26cacSmrg *    "value" contains the requested attribute on success.
12366df26cacSmrg *
12376df26cacSmrg *-----------------------------------------------------------------------------
12386df26cacSmrg */
12396df26cacSmrg
124016fd1166Smrgstatic int
124116fd1166SmrgvmwareGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
124216fd1166Smrg                       INT32 *value, pointer data)
12436df26cacSmrg{
12446df26cacSmrg    VMWAREVideoPtr pVid = (VMWAREVideoPtr) data;
12456df26cacSmrg    Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
124616fd1166Smrg    Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
12476df26cacSmrg
12486df26cacSmrg    if (attribute == xvColorKey) {
12496df26cacSmrg        *value = pVid->colorKey;
125016fd1166Smrg    } else if (attribute == xvAutoPaint) {
125116fd1166Smrg        *value = pVid->isAutoPaintColorkey;
12526df26cacSmrg    } else {
12536df26cacSmrg        return XvBadAlloc;
12546df26cacSmrg    }
125516fd1166Smrg
12566df26cacSmrg    return Success;
12576df26cacSmrg}
12586df26cacSmrg
12596df26cacSmrg
12606df26cacSmrg/*
12616df26cacSmrg *-----------------------------------------------------------------------------
12626df26cacSmrg *
12636df26cacSmrg * vmwareQueryBestSize --
12646df26cacSmrg *
12656df26cacSmrg *    From the spec: QueryBestSize provides the client with a way to query what
12666df26cacSmrg *    the destination dimensions would end up being if they were to request
12676df26cacSmrg *    that an area vid_w by vid_h from the video stream be scaled to rectangle
12686df26cacSmrg *    of drw_w by drw_h on the screen. Since it is not expected that all
12696df26cacSmrg *    hardware will be able to get the target dimensions exactly, it is
12706df26cacSmrg *    important that the driver provide this function.
12716df26cacSmrg *
12726df26cacSmrg *    This function seems to never be called, but to be on the safe side
12736df26cacSmrg *    we apply the same logic that QueryImageAttributes has for width
12746df26cacSmrg *    and height
12756df26cacSmrg *
12766df26cacSmrg * Results:
12776df26cacSmrg *    None.
12786df26cacSmrg *
12796df26cacSmrg * Side effects:
12806df26cacSmrg *    None
12816df26cacSmrg *
12826df26cacSmrg *-----------------------------------------------------------------------------
12836df26cacSmrg */
12846df26cacSmrg
128516fd1166Smrgstatic void
128616fd1166SmrgvmwareQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
128716fd1166Smrg                    short vid_w, short vid_h, short drw_w,
128816fd1166Smrg                    short drw_h, unsigned int *p_w,
128916fd1166Smrg                    unsigned int *p_h, pointer data)
12906df26cacSmrg{
12916df26cacSmrg    *p_w = (drw_w + 1) & ~1;
12926df26cacSmrg    *p_h = drw_h;
12936df26cacSmrg
12946df26cacSmrg    return;
12956df26cacSmrg}
12966df26cacSmrg
1297