vmwarevideo.c revision a241306c
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
49a241306cSmrg#ifndef HAVE_XORG_SERVER_1_5_0
50a241306cSmrg#include <xf86_ansic.h>
51a241306cSmrg#include <xf86_libc.h>
52a241306cSmrg#endif
53a241306cSmrg
546df26cacSmrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
556df26cacSmrg
566df26cacSmrg/*
576df26cacSmrg * Used to pack structs
586df26cacSmrg */
596df26cacSmrg#define PACKED __attribute__((__packed__))
606df26cacSmrg
616df26cacSmrg/*
626df26cacSmrg * Number of videos that can be played simultaneously
636df26cacSmrg */
646df26cacSmrg#define VMWARE_VID_NUM_PORTS 1
656df26cacSmrg
666df26cacSmrg/*
6716fd1166Smrg * Using a dark shade as the default colorKey
686df26cacSmrg */
6916fd1166Smrg#define VMWARE_VIDEO_COLORKEY 0x100701
706df26cacSmrg
716df26cacSmrg/*
726df26cacSmrg * Maximum dimensions
736df26cacSmrg */
746df26cacSmrg#define VMWARE_VID_MAX_WIDTH    2048
756df26cacSmrg#define VMWARE_VID_MAX_HEIGHT   2048
766df26cacSmrg
776df26cacSmrg#define VMWARE_VID_NUM_ENCODINGS 1
786df26cacSmrgstatic XF86VideoEncodingRec vmwareVideoEncodings[] =
796df26cacSmrg{
806df26cacSmrg    {
816df26cacSmrg       0,
826df26cacSmrg       "XV_IMAGE",
836df26cacSmrg       VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT,
846df26cacSmrg       {1, 1}
856df26cacSmrg    }
866df26cacSmrg};
876df26cacSmrg
886df26cacSmrg#define VMWARE_VID_NUM_FORMATS 2
896df26cacSmrgstatic XF86VideoFormatRec vmwareVideoFormats[] =
906df26cacSmrg{
916df26cacSmrg    { 16, TrueColor},
926df26cacSmrg    { 24, TrueColor}
936df26cacSmrg};
946df26cacSmrg
9516fd1166Smrg#define VMWARE_VID_NUM_IMAGES 3
966df26cacSmrgstatic XF86ImageRec vmwareVideoImages[] =
976df26cacSmrg{
986df26cacSmrg    XVIMAGE_YV12,
9916fd1166Smrg    XVIMAGE_YUY2,
10016fd1166Smrg    XVIMAGE_UYVY
1016df26cacSmrg};
1026df26cacSmrg
10316fd1166Smrg#define VMWARE_VID_NUM_ATTRIBUTES 2
1046df26cacSmrgstatic XF86AttributeRec vmwareVideoAttributes[] =
1056df26cacSmrg{
1066df26cacSmrg    {
1076df26cacSmrg        XvGettable | XvSettable,
1086df26cacSmrg        0x000000,
1096df26cacSmrg        0xffffff,
1106df26cacSmrg        "XV_COLORKEY"
11116fd1166Smrg    },
11216fd1166Smrg    {
11316fd1166Smrg        XvGettable | XvSettable,
11416fd1166Smrg        0,
11516fd1166Smrg        1,
11616fd1166Smrg        "XV_AUTOPAINT_COLORKEY"
1176df26cacSmrg    }
1186df26cacSmrg};
1196df26cacSmrg
1206df26cacSmrg/*
1216df26cacSmrg * Video frames are stored in a circular list of buffers.
1226df26cacSmrg */
1236df26cacSmrg#define VMWARE_VID_NUM_BUFFERS 1
1246df26cacSmrg/*
1256df26cacSmrg * Defines the structure used to hold and pass video data to the host
1266df26cacSmrg */
1276df26cacSmrgtypedef struct {
1286df26cacSmrg   uint32  dataOffset;
1296df26cacSmrg   pointer data;
1306df26cacSmrg} VMWAREVideoBuffer;
1316df26cacSmrg
1326df26cacSmrgtypedef struct {
1336df26cacSmrg   uint32 size;
1346df26cacSmrg   uint32 offset;
1356df26cacSmrg} VMWAREOffscreenRec, *VMWAREOffscreenPtr;
1366df26cacSmrg
1376df26cacSmrg/*
1386df26cacSmrg * Trivial offscreen manager that allocates memory from the
1396df26cacSmrg * bottom of the VRAM.
1406df26cacSmrg */
1416df26cacSmrgstatic VMWAREOffscreenRec offscreenMgr;
1426df26cacSmrg
1436df26cacSmrg/*
1446df26cacSmrg * structs that reside in fmt_priv.
1456df26cacSmrg */
1466df26cacSmrgtypedef struct {
1476df26cacSmrg    int pitches[3];
1486df26cacSmrg    int offsets[3];
1496df26cacSmrg} VMWAREVideoFmtData;
1506df26cacSmrg
1516df26cacSmrg/*
1526df26cacSmrg * Structure representing a specific video stream.
1536df26cacSmrg */
1546df26cacSmrgstruct VMWAREVideoRec {
1556df26cacSmrg   uint32             streamId;
1566df26cacSmrg   /*
1576df26cacSmrg    * Function prototype same as XvPutImage.
1586df26cacSmrg    */
1596df26cacSmrg   int                (*play)(ScrnInfoPtr, struct VMWAREVideoRec *,
1606df26cacSmrg                              short, short, short, short, short,
1616df26cacSmrg                              short, short, short, int, unsigned char*,
16216fd1166Smrg                              short, short, RegionPtr);
1636df26cacSmrg   /*
1646df26cacSmrg    * Offscreen memory region used to pass video data to the host.
1656df26cacSmrg    */
1666df26cacSmrg   VMWAREOffscreenPtr fbarea;
1676df26cacSmrg   VMWAREVideoBuffer  bufs[VMWARE_VID_NUM_BUFFERS];
1686df26cacSmrg   uint8              currBuf;
1696df26cacSmrg   uint32             size;
1706df26cacSmrg   uint32             colorKey;
17116fd1166Smrg   Bool               isAutoPaintColorkey;
1726df26cacSmrg   uint32             flags;
17316fd1166Smrg   RegionRec          clipBoxes;
1746df26cacSmrg   VMWAREVideoFmtData *fmt_priv;
1756df26cacSmrg};
1766df26cacSmrg
1776df26cacSmrgtypedef struct VMWAREVideoRec VMWAREVideoRec;
1786df26cacSmrgtypedef VMWAREVideoRec *VMWAREVideoPtr;
1796df26cacSmrg
1806df26cacSmrg/*
1816df26cacSmrg * Callback functions
1826df26cacSmrg */
18316fd1166Smrg#ifdef HAVE_XORG_SERVER_1_0_99_901
1846df26cacSmrgstatic int vmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1856df26cacSmrg                            short drw_x, short drw_y, short src_w, short src_h,
1866df26cacSmrg                            short drw_w, short drw_h, int image,
1876df26cacSmrg                            unsigned char *buf, short width, short height,
1886df26cacSmrg                            Bool sync, RegionPtr clipBoxes, pointer data,
1896df26cacSmrg                            DrawablePtr dst);
1906df26cacSmrg#else
1916df26cacSmrgstatic int vmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
1926df26cacSmrg                            short drw_x, short drw_y, short src_w, short src_h,
1936df26cacSmrg                            short drw_w, short drw_h, int image,
1946df26cacSmrg                            unsigned char *buf, short width, short height,
1956df26cacSmrg                            Bool sync, RegionPtr clipBoxes, pointer data);
1966df26cacSmrg#endif
1976df26cacSmrgstatic void vmwareStopVideo(ScrnInfoPtr pScrn, pointer data, Bool Cleanup);
1986df26cacSmrgstatic int vmwareQueryImageAttributes(ScrnInfoPtr pScrn, int format,
1996df26cacSmrg                                      unsigned short *width,
2006df26cacSmrg                                      unsigned short *height, int *pitches,
2016df26cacSmrg                                      int *offsets);
2026df26cacSmrgstatic int vmwareSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
2036df26cacSmrg                                  INT32 value, pointer data);
2046df26cacSmrgstatic int vmwareGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
2056df26cacSmrg                                  INT32 *value, pointer data);
2066df26cacSmrgstatic void vmwareQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
2076df26cacSmrg                                short vid_w, short vid_h, short drw_w,
2086df26cacSmrg                                short drw_h, unsigned int *p_w,
2096df26cacSmrg                                unsigned int *p_h, pointer data);
2106df26cacSmrg
2116df26cacSmrg/*
2126df26cacSmrg * Local functions for video streams
2136df26cacSmrg */
2146df26cacSmrgstatic XF86VideoAdaptorPtr vmwareVideoSetup(ScrnInfoPtr pScrn);
2156df26cacSmrgstatic int vmwareVideoInitStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
2166df26cacSmrg                                 short src_x, short src_y, short drw_x,
2176df26cacSmrg                                 short drw_y, short src_w, short src_h,
2186df26cacSmrg                                 short drw_w, short drw_h, int format,
21916fd1166Smrg                                 unsigned char *buf, short width,
22016fd1166Smrg                                 short height, RegionPtr clipBoxes);
2216df26cacSmrgstatic int vmwareVideoInitAttributes(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
2226df26cacSmrg                                     int format, unsigned short width,
2236df26cacSmrg                                     unsigned short height);
2246df26cacSmrgstatic int vmwareVideoPlay(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
2256df26cacSmrg                           short src_x, short src_y, short drw_x,
2266df26cacSmrg                           short drw_y, short src_w, short src_h,
2276df26cacSmrg                           short drw_w, short drw_h, int format,
2286df26cacSmrg                           unsigned char *buf, short width,
22916fd1166Smrg                           short height, RegionPtr clipBoxes);
2306df26cacSmrgstatic void vmwareVideoFlush(VMWAREPtr pVMWARE, uint32 streamId);
2316df26cacSmrgstatic void vmwareVideoSetOneReg(VMWAREPtr pVMWARE, uint32 streamId,
2326df26cacSmrg                                 uint32 regId, uint32 value);
2336df26cacSmrgstatic void vmwareVideoEndStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid);
2346df26cacSmrg
2356df26cacSmrg/*
2366df26cacSmrg * Offscreen memory manager functions
2376df26cacSmrg */
2386df26cacSmrgstatic void vmwareOffscreenInit(void);
2396df26cacSmrgstatic VMWAREOffscreenPtr vmwareOffscreenAllocate(VMWAREPtr pVMWARE,
2406df26cacSmrg                                                  uint32 size);
2416df26cacSmrgstatic void vmwareOffscreenFree(VMWAREOffscreenPtr memptr);
2426df26cacSmrg
2436df26cacSmrg
2446df26cacSmrg/*
2456df26cacSmrg *-----------------------------------------------------------------------------
2466df26cacSmrg *
2476df26cacSmrg * vmwareCheckVideoSanity --
2486df26cacSmrg *
2496df26cacSmrg *    Ensures that on ModeSwitch the offscreen memory used
2506df26cacSmrg *    by the Xv streams doesn't become part of the guest framebuffer.
2516df26cacSmrg *
2526df26cacSmrg * Results:
2536df26cacSmrg *    None
2546df26cacSmrg *
2556df26cacSmrg * Side effects:
2566df26cacSmrg *    If it is found that the offscreen used by video streams  lies
2576df26cacSmrg *    within the range of the framebuffer(after ModeSwitch) then the video
2586df26cacSmrg *    streams will be stopped.
2596df26cacSmrg *
2606df26cacSmrg *-----------------------------------------------------------------------------
2616df26cacSmrg */
2626df26cacSmrg
2636df26cacSmrgvoid
2646df26cacSmrgvmwareCheckVideoSanity(ScrnInfoPtr pScrn)
2656df26cacSmrg{
2666df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
2676df26cacSmrg    VMWAREVideoPtr pVid;
2686df26cacSmrg
2696df26cacSmrg   if (offscreenMgr.size == 0 ||
2706df26cacSmrg       offscreenMgr.offset > pVMWARE->FbSize) {
2716df26cacSmrg       return ;
2726df26cacSmrg   }
2736df26cacSmrg
2746df26cacSmrg   pVid = (VMWAREVideoPtr) &pVMWARE->videoStreams[VMWARE_VID_NUM_PORTS];
2756df26cacSmrg   vmwareStopVideo(pScrn, pVid, TRUE);
2766df26cacSmrg}
2776df26cacSmrg
2786df26cacSmrg
2796df26cacSmrg/*
2806df26cacSmrg *-----------------------------------------------------------------------------
2816df26cacSmrg *
2826df26cacSmrg * vmwareOffscreenInit --
2836df26cacSmrg *
2846df26cacSmrg *    Initializes the trivial Offscreen memory manager.
2856df26cacSmrg *
2866df26cacSmrg * Results:
2876df26cacSmrg *    None.
2886df26cacSmrg *
2896df26cacSmrg * Side effects:
2906df26cacSmrg *    Initializes the Offscreen manager meta-data structure.
2916df26cacSmrg *
2926df26cacSmrg *-----------------------------------------------------------------------------
2936df26cacSmrg */
2946df26cacSmrg
2956df26cacSmrgstatic void
2966df26cacSmrgvmwareOffscreenInit(void)
2976df26cacSmrg{
2986df26cacSmrg    offscreenMgr.size = 0;
2996df26cacSmrg    offscreenMgr.offset  = 0;
3006df26cacSmrg}
3016df26cacSmrg
3026df26cacSmrg
3036df26cacSmrg/*
3046df26cacSmrg *-----------------------------------------------------------------------------
3056df26cacSmrg *
3066df26cacSmrg * vmwareOffscreenAllocate --
3076df26cacSmrg *
3086df26cacSmrg *    Allocates offscreen memory.
3096df26cacSmrg *    Memory is allocated from the bottom part of the VRAM.
3106df26cacSmrg *    The memory manager is trivial iand can handle only 1 video-stream.
3116df26cacSmrg *    ----------
3126df26cacSmrg *    |        |
3136df26cacSmrg *    |  FB    |
3146df26cacSmrg *    |        |
3156df26cacSmrg *    |---------
3166df26cacSmrg *    |        |
3176df26cacSmrg *    |        |
3186df26cacSmrg *    |--------|
3196df26cacSmrg *    | Offscr |
3206df26cacSmrg *    |--------|
3216df26cacSmrg *
3226df26cacSmrg *      VRAM
3236df26cacSmrg *
3246df26cacSmrg * Results:
3256df26cacSmrg *    Pointer to the allocated Offscreen memory.
3266df26cacSmrg *
3276df26cacSmrg * Side effects:
3286df26cacSmrg *    Updates the Offscreen memory manager meta-data structure.
3296df26cacSmrg *
3306df26cacSmrg *-----------------------------------------------------------------------------
3316df26cacSmrg */
3326df26cacSmrg
3336df26cacSmrgstatic VMWAREOffscreenPtr
3346df26cacSmrgvmwareOffscreenAllocate(VMWAREPtr pVMWARE, uint32 size)
3356df26cacSmrg{
3366df26cacSmrg    VMWAREOffscreenPtr memptr;
3376df26cacSmrg
3386df26cacSmrg    if ((pVMWARE->videoRam - pVMWARE->FbSize - pVMWARE->fbPitch - 7) < size) {
3396df26cacSmrg        return NULL;
3406df26cacSmrg    }
3416df26cacSmrg
342a241306cSmrg    memptr = malloc(sizeof(VMWAREOffscreenRec));
3436df26cacSmrg    if (!memptr) {
3446df26cacSmrg        return NULL;
3456df26cacSmrg    }
3466df26cacSmrg    memptr->size = size;
3476df26cacSmrg    memptr->offset  = (pVMWARE->videoRam - size) & ~7;
3486df26cacSmrg
3496df26cacSmrg    VmwareLog(("vmwareOffscreenAllocate: Offset:%x", memptr->offset));
3506df26cacSmrg
3516df26cacSmrg    offscreenMgr.size = memptr->size;
3526df26cacSmrg    offscreenMgr.offset = memptr->offset;
3536df26cacSmrg    return memptr;
3546df26cacSmrg}
3556df26cacSmrg
3566df26cacSmrg
3576df26cacSmrg/*
3586df26cacSmrg *-----------------------------------------------------------------------------
3596df26cacSmrg *
3606df26cacSmrg * vmwareOffscreenFree --
3616df26cacSmrg *
3626df26cacSmrg *    Frees the allocated offscreen memory.
3636df26cacSmrg *
3646df26cacSmrg * Results:
3656df26cacSmrg *    None.
3666df26cacSmrg *
3676df26cacSmrg * Side effects:
3686df26cacSmrg *    Updates the Offscreen memory manager meta-data structure.
3696df26cacSmrg *
3706df26cacSmrg *-----------------------------------------------------------------------------
3716df26cacSmrg */
3726df26cacSmrg
3736df26cacSmrgstatic void
3746df26cacSmrgvmwareOffscreenFree(VMWAREOffscreenPtr memptr)
3756df26cacSmrg{
3766df26cacSmrg    if (memptr) {
3776df26cacSmrg        free(memptr);
3786df26cacSmrg    }
3796df26cacSmrg
3806df26cacSmrg    offscreenMgr.size = 0;
3816df26cacSmrg    offscreenMgr.offset = 0;
3826df26cacSmrg}
3836df26cacSmrg
3846df26cacSmrg
3856df26cacSmrg/*
3866df26cacSmrg *-----------------------------------------------------------------------------
3876df26cacSmrg *
3886df26cacSmrg * vmwareVideoEnabled --
3896df26cacSmrg *
3906df26cacSmrg *    Checks if Video FIFO and Escape FIFO cap are enabled.
3916df26cacSmrg *
3926df26cacSmrg * Results:
3936df26cacSmrg *    TRUE if required caps are enabled, FALSE otherwise.
3946df26cacSmrg *
3956df26cacSmrg * Side effects:
3966df26cacSmrg *    None.
3976df26cacSmrg *
3986df26cacSmrg *-----------------------------------------------------------------------------
3996df26cacSmrg */
4006df26cacSmrg
40116fd1166SmrgBool
40216fd1166SmrgvmwareVideoEnabled(VMWAREPtr pVMWARE)
4036df26cacSmrg{
4046df26cacSmrg    return ((pVMWARE->vmwareCapability & SVGA_CAP_EXTENDED_FIFO) &&
4056df26cacSmrg            (pVMWARE->vmwareFIFO[SVGA_FIFO_CAPABILITIES] &
4066df26cacSmrg             (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE)));
4076df26cacSmrg}
4086df26cacSmrg
4096df26cacSmrg
4106df26cacSmrg/*
4116df26cacSmrg *-----------------------------------------------------------------------------
4126df26cacSmrg *
4136df26cacSmrg * vmwareVideoInit --
4146df26cacSmrg *
4156df26cacSmrg *    Initializes Xv support.
4166df26cacSmrg *
4176df26cacSmrg * Results:
4186df26cacSmrg *    TRUE on success, FALSE on error.
4196df26cacSmrg *
4206df26cacSmrg * Side effects:
4216df26cacSmrg *    Xv support is initialized. Memory is allocated for all supported
4226df26cacSmrg *    video streams.
4236df26cacSmrg *
4246df26cacSmrg *-----------------------------------------------------------------------------
4256df26cacSmrg */
4266df26cacSmrg
42716fd1166SmrgBool
42816fd1166SmrgvmwareVideoInit(ScreenPtr pScreen)
4296df26cacSmrg{
4306df26cacSmrg    ScrnInfoPtr pScrn = infoFromScreen(pScreen);
4316df26cacSmrg    XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL;
4326df26cacSmrg    XF86VideoAdaptorPtr newAdaptor = NULL;
4336df26cacSmrg    int numAdaptors;
4346df26cacSmrg
4356df26cacSmrg    TRACEPOINT
4366df26cacSmrg
4376df26cacSmrg    vmwareOffscreenInit();
4386df26cacSmrg
4396df26cacSmrg    numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors);
4406df26cacSmrg
4416df26cacSmrg    newAdaptor = vmwareVideoSetup(pScrn);
4426df26cacSmrg    if (!newAdaptor) {
4436df26cacSmrg        VmwareLog(("Failed to initialize Xv extension \n"));
4446df26cacSmrg        return FALSE;
4456df26cacSmrg    }
4466df26cacSmrg
4476df26cacSmrg    if (!numAdaptors) {
4486df26cacSmrg        numAdaptors = 1;
4496df26cacSmrg        overlayAdaptors = &newAdaptor;
4506df26cacSmrg    } else {
451a241306cSmrg         newAdaptors = malloc((numAdaptors + 1) *
4526df26cacSmrg                              sizeof(XF86VideoAdaptorPtr*));
4536df26cacSmrg         if (!newAdaptors) {
4546df26cacSmrg            xf86XVFreeVideoAdaptorRec(newAdaptor);
4556df26cacSmrg            return FALSE;
4566df26cacSmrg         }
4576df26cacSmrg
4586df26cacSmrg         memcpy(newAdaptors, overlayAdaptors,
4596df26cacSmrg                numAdaptors * sizeof(XF86VideoAdaptorPtr));
4606df26cacSmrg         newAdaptors[numAdaptors++] = newAdaptor;
4616df26cacSmrg         overlayAdaptors = newAdaptors;
4626df26cacSmrg    }
4636df26cacSmrg
4646df26cacSmrg    if (!xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors)) {
4656df26cacSmrg        VmwareLog(("Failed to initialize Xv extension\n"));
4666df26cacSmrg        xf86XVFreeVideoAdaptorRec(newAdaptor);
4676df26cacSmrg        return FALSE;
4686df26cacSmrg    }
4696df26cacSmrg
4706df26cacSmrg    if (newAdaptors) {
471a241306cSmrg        free(newAdaptors);
4726df26cacSmrg    }
4736df26cacSmrg
4746df26cacSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4756df26cacSmrg               "Initialized VMware Xv extension successfully.\n");
4766df26cacSmrg    return TRUE;
4776df26cacSmrg}
4786df26cacSmrg
4796df26cacSmrg
4806df26cacSmrg/*
4816df26cacSmrg *-----------------------------------------------------------------------------
4826df26cacSmrg *
4836df26cacSmrg * vmwareVideoEnd --
4846df26cacSmrg *
4856df26cacSmrg *    Unitializes video.
4866df26cacSmrg *
4876df26cacSmrg * Results:
4886df26cacSmrg *    None.
4896df26cacSmrg *
4906df26cacSmrg * Side effects:
4916df26cacSmrg *    pVMWARE->videoStreams = NULL
4926df26cacSmrg *
4936df26cacSmrg *-----------------------------------------------------------------------------
4946df26cacSmrg */
4956df26cacSmrg
49616fd1166Smrgvoid
49716fd1166SmrgvmwareVideoEnd(ScreenPtr pScreen)
4986df26cacSmrg{
4996df26cacSmrg    ScrnInfoPtr pScrn = infoFromScreen(pScreen);
5006df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
5016df26cacSmrg    VMWAREVideoPtr pVid;
5026df26cacSmrg    int i;
5036df26cacSmrg
5046df26cacSmrg    TRACEPOINT
5056df26cacSmrg
5066df26cacSmrg    /*
5076df26cacSmrg     * Video streams are allocated after the DevUnion array
5086df26cacSmrg     * (see VideoSetup)
5096df26cacSmrg     */
5106df26cacSmrg    pVid = (VMWAREVideoPtr) &pVMWARE->videoStreams[VMWARE_VID_NUM_PORTS];
5116df26cacSmrg    for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
5126df26cacSmrg        vmwareVideoEndStream(pScrn, &pVid[i]);
513a241306cSmrg	REGION_UNINIT(pScreen, &pVid[i].clipBoxes);
5146df26cacSmrg    }
5156df26cacSmrg
5166df26cacSmrg    free(pVMWARE->videoStreams);
5176df26cacSmrg    pVMWARE->videoStreams = NULL;
5186df26cacSmrg}
5196df26cacSmrg
5206df26cacSmrg
5216df26cacSmrg/*
5226df26cacSmrg *-----------------------------------------------------------------------------
5236df26cacSmrg *
5246df26cacSmrg * vmwareVideoSetup --
5256df26cacSmrg *
5266df26cacSmrg *    Initializes a XF86VideoAdaptor structure with the capabilities and
5276df26cacSmrg *    functions supported by this video driver.
5286df26cacSmrg *
5296df26cacSmrg * Results:
5306df26cacSmrg *    On success initialized XF86VideoAdaptor struct or NULL on error
5316df26cacSmrg *
5326df26cacSmrg * Side effects:
5336df26cacSmrg *    None.
5346df26cacSmrg *
5356df26cacSmrg *-----------------------------------------------------------------------------
5366df26cacSmrg */
5376df26cacSmrg
53816fd1166Smrgstatic XF86VideoAdaptorPtr
53916fd1166SmrgvmwareVideoSetup(ScrnInfoPtr pScrn)
5406df26cacSmrg{
5416df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
5426df26cacSmrg    XF86VideoAdaptorPtr adaptor;
5436df26cacSmrg    VMWAREVideoPtr pPriv;
5446df26cacSmrg    DevUnion *du;
5456df26cacSmrg    int i;
5466df26cacSmrg
5476df26cacSmrg    TRACEPOINT
5486df26cacSmrg
5496df26cacSmrg    adaptor = xf86XVAllocateVideoAdaptorRec(pScrn);
5506df26cacSmrg    if (!adaptor) {
5516df26cacSmrg        VmwareLog(("Not enough memory\n"));
5526df26cacSmrg        return NULL;
5536df26cacSmrg    }
554a241306cSmrg    du = calloc(1, VMWARE_VID_NUM_PORTS *
5556df26cacSmrg        (sizeof(DevUnion) + sizeof(VMWAREVideoRec)));
5566df26cacSmrg
5576df26cacSmrg    if (!du) {
5586df26cacSmrg        VmwareLog(("Not enough memory.\n"));
5596df26cacSmrg        xf86XVFreeVideoAdaptorRec(adaptor);
5606df26cacSmrg        return NULL;
5616df26cacSmrg    }
5626df26cacSmrg
5636df26cacSmrg    adaptor->type = XvInputMask | XvImageMask | XvWindowMask;
5646df26cacSmrg    adaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
5656df26cacSmrg    adaptor->name = "VMware Video Engine";
5666df26cacSmrg    adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS;
5676df26cacSmrg    adaptor->pEncodings = vmwareVideoEncodings;
5686df26cacSmrg    adaptor->nFormats = VMWARE_VID_NUM_FORMATS;
5696df26cacSmrg    adaptor->pFormats = vmwareVideoFormats;
5706df26cacSmrg    adaptor->nPorts = VMWARE_VID_NUM_PORTS;
5716df26cacSmrg
5726df26cacSmrg    pPriv = (VMWAREVideoPtr) &du[VMWARE_VID_NUM_PORTS];
5736df26cacSmrg    adaptor->pPortPrivates = du;
5746df26cacSmrg
5756df26cacSmrg    for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
5766df26cacSmrg        pPriv[i].streamId = i;
5776df26cacSmrg        pPriv[i].play = vmwareVideoInitStream;
5786df26cacSmrg        pPriv[i].flags = SVGA_VIDEO_FLAG_COLORKEY;
5796df26cacSmrg        pPriv[i].colorKey = VMWARE_VIDEO_COLORKEY;
58016fd1166Smrg        pPriv[i].isAutoPaintColorkey = TRUE;
581a241306cSmrg	REGION_NULL(pScreen, &pPriv[i].clipBoxes);
5826df26cacSmrg        adaptor->pPortPrivates[i].ptr = &pPriv[i];
5836df26cacSmrg    }
5846df26cacSmrg    pVMWARE->videoStreams = du;
5856df26cacSmrg
5866df26cacSmrg    adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES;
5876df26cacSmrg    adaptor->pAttributes = vmwareVideoAttributes;
5886df26cacSmrg
5896df26cacSmrg    adaptor->nImages = VMWARE_VID_NUM_IMAGES;
5906df26cacSmrg    adaptor->pImages = vmwareVideoImages;
5916df26cacSmrg
5926df26cacSmrg    adaptor->PutVideo = NULL;
5936df26cacSmrg    adaptor->PutStill = NULL;
5946df26cacSmrg    adaptor->GetVideo = NULL;
5956df26cacSmrg    adaptor->GetStill = NULL;
5966df26cacSmrg    adaptor->StopVideo = vmwareStopVideo;
5976df26cacSmrg    adaptor->SetPortAttribute = vmwareSetPortAttribute;
5986df26cacSmrg    adaptor->GetPortAttribute = vmwareGetPortAttribute;
5996df26cacSmrg    adaptor->QueryBestSize = vmwareQueryBestSize;
6006df26cacSmrg    adaptor->PutImage = vmwareXvPutImage;
6016df26cacSmrg    adaptor->QueryImageAttributes = vmwareQueryImageAttributes;
6026df26cacSmrg
6036df26cacSmrg    return adaptor;
6046df26cacSmrg}
6056df26cacSmrg
6066df26cacSmrg
6076df26cacSmrg/*
6086df26cacSmrg *-----------------------------------------------------------------------------
6096df26cacSmrg *
6106df26cacSmrg * vmwareVideoInitStream --
6116df26cacSmrg *
6126df26cacSmrg *    Initializes a video stream in response to the first PutImage() on a
6136df26cacSmrg *    video stream. The process goes as follows:
6146df26cacSmrg *    - Figure out characteristics according to format
6156df26cacSmrg *    - Allocate offscreen memory
6166df26cacSmrg *    - Pass on video to Play() functions
6176df26cacSmrg *
6186df26cacSmrg * Results:
6196df26cacSmrg *    Success or XvBadAlloc on failure.
6206df26cacSmrg *
6216df26cacSmrg * Side effects:
6226df26cacSmrg *    Video stream is initialized and its first frame sent to the host
6236df26cacSmrg *    (done by VideoPlay() function called at the end)
6246df26cacSmrg *
6256df26cacSmrg *-----------------------------------------------------------------------------
6266df26cacSmrg */
6276df26cacSmrg
62816fd1166Smrgstatic int
62916fd1166SmrgvmwareVideoInitStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
63016fd1166Smrg                      short src_x, short src_y, short drw_x,
63116fd1166Smrg                      short drw_y, short src_w, short src_h,
63216fd1166Smrg                      short drw_w, short drw_h, int format,
63316fd1166Smrg                      unsigned char *buf, short width,
63416fd1166Smrg                      short height, RegionPtr clipBoxes)
6356df26cacSmrg{
6366df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
6376df26cacSmrg    int i;
6386df26cacSmrg
6396df26cacSmrg    TRACEPOINT
6406df26cacSmrg
6416df26cacSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
6426df26cacSmrg               "Initializing Xv video-stream with id:%d format:%d\n",
6436df26cacSmrg                pVid->streamId, format);
6446df26cacSmrg
6456df26cacSmrg    pVid->size = vmwareVideoInitAttributes(pScrn, pVid, format, width,
6466df26cacSmrg                                           height);
6476df26cacSmrg
6486df26cacSmrg    if (pVid->size == -1) {
6496df26cacSmrg        VmwareLog(("Could not initialize 0x%x video stream\n", format));
6506df26cacSmrg        return XvBadAlloc;
6516df26cacSmrg    }
6526df26cacSmrg
6536df26cacSmrg    pVid->play = vmwareVideoPlay;
6546df26cacSmrg
6556df26cacSmrg    pVid->fbarea = vmwareOffscreenAllocate(pVMWARE,
6566df26cacSmrg                       pVid->size * VMWARE_VID_NUM_BUFFERS);
6576df26cacSmrg
6586df26cacSmrg    if (!pVid->fbarea) {
6596df26cacSmrg       VmwareLog(("Could not allocate offscreen memory\n"));
6606df26cacSmrg       vmwareVideoEndStream(pScrn, pVid);
6616df26cacSmrg       return BadAlloc;
6626df26cacSmrg    }
6636df26cacSmrg
6646df26cacSmrg    pVid->bufs[0].dataOffset = pVid->fbarea->offset;
6656df26cacSmrg    pVid->bufs[0].data = pVMWARE->FbBase + pVid->bufs[0].dataOffset;
6666df26cacSmrg
6676df26cacSmrg    for (i = 1; i < VMWARE_VID_NUM_BUFFERS; ++i) {
6686df26cacSmrg        pVid->bufs[i].dataOffset = pVid->bufs[i-1].dataOffset + pVid->size;
6696df26cacSmrg        pVid->bufs[i].data = pVMWARE->FbBase + pVid->bufs[i].dataOffset;
6706df26cacSmrg    }
6716df26cacSmrg    pVid->currBuf = 0;
6726df26cacSmrg
67316fd1166Smrg    REGION_COPY(pScrn->pScreen, &pVid->clipBoxes, clipBoxes);
67416fd1166Smrg
67516fd1166Smrg    if (pVid->isAutoPaintColorkey) {
676a241306cSmrg	BoxPtr boxes = REGION_RECTS(&pVid->clipBoxes);
677a241306cSmrg	int nBoxes = REGION_NUM_RECTS(&pVid->clipBoxes);
678a241306cSmrg
67916fd1166Smrg        xf86XVFillKeyHelper(pScrn->pScreen, pVid->colorKey, clipBoxes);
680a241306cSmrg
681a241306cSmrg	/**
682a241306cSmrg	 * Force update to paint the colorkey before the overlay flush.
683a241306cSmrg	 */
684a241306cSmrg
685a241306cSmrg	while(nBoxes--)
686a241306cSmrg	    vmwareSendSVGACmdUpdate(pVMWARE, boxes++);
68716fd1166Smrg    }
68816fd1166Smrg
6896df26cacSmrg    VmwareLog(("Got offscreen region, offset %d, size %d "
6906df26cacSmrg               "(yuv size in bytes: %d)\n",
6916df26cacSmrg               pVid->fbarea->offset, pVid->fbarea->size, pVid->size));
6926df26cacSmrg
6936df26cacSmrg    return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w, src_h,
69416fd1166Smrg                      drw_w, drw_h, format, buf, width, height, clipBoxes);
6956df26cacSmrg}
6966df26cacSmrg
6976df26cacSmrg
6986df26cacSmrg/*
6996df26cacSmrg *-----------------------------------------------------------------------------
7006df26cacSmrg *
7016df26cacSmrg * vmwareVideoInitAttributes --
7026df26cacSmrg *
7036df26cacSmrg *    Fetches the format specific attributes using QueryImageAttributes().
7046df26cacSmrg *
7056df26cacSmrg * Results:
7066df26cacSmrg *    size of the YUV frame on success and -1 on error.
7076df26cacSmrg *
7086df26cacSmrg * Side effects:
7096df26cacSmrg *    The video stream gets the format specific attributes(fmtData).
7106df26cacSmrg *
7116df26cacSmrg *-----------------------------------------------------------------------------
7126df26cacSmrg */
7136df26cacSmrg
71416fd1166Smrgstatic int
71516fd1166SmrgvmwareVideoInitAttributes(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
71616fd1166Smrg                          int format, unsigned short width,
71716fd1166Smrg                          unsigned short height)
7186df26cacSmrg{
7196df26cacSmrg    int size;
7206df26cacSmrg    VMWAREVideoFmtData *fmtData;
7216df26cacSmrg
7226df26cacSmrg    TRACEPOINT
7236df26cacSmrg
724a241306cSmrg    fmtData = calloc(1, sizeof(VMWAREVideoFmtData));
7256df26cacSmrg    if (!fmtData) {
7266df26cacSmrg        return -1;
7276df26cacSmrg    }
7286df26cacSmrg
7296df26cacSmrg    size = vmwareQueryImageAttributes(pScrn, format, &width, &height,
7306df26cacSmrg                                      fmtData->pitches, fmtData->offsets);
7316df26cacSmrg    if (size == -1) {
7326df26cacSmrg        free(fmtData);
7336df26cacSmrg        return -1;
7346df26cacSmrg    }
7356df26cacSmrg
7366df26cacSmrg    pVid->fmt_priv = fmtData;
7376df26cacSmrg    return size;
7386df26cacSmrg}
7396df26cacSmrg
7406df26cacSmrg
7416df26cacSmrg/*
7426df26cacSmrg *-----------------------------------------------------------------------------
7436df26cacSmrg *
7446df26cacSmrg * vmwareVideoPlay --
7456df26cacSmrg *
7466df26cacSmrg *    Sends all the attributes associated with the video frame using the
7476df26cacSmrg *    FIFO ESCAPE mechanism to the host.
7486df26cacSmrg *
7496df26cacSmrg * Results:
7506df26cacSmrg *    Always returns Success.
7516df26cacSmrg *
7526df26cacSmrg * Side effects:
7536df26cacSmrg *    None.
7546df26cacSmrg *
7556df26cacSmrg *-----------------------------------------------------------------------------
7566df26cacSmrg */
7576df26cacSmrg
75816fd1166Smrgstatic int
75916fd1166SmrgvmwareVideoPlay(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid,
76016fd1166Smrg                short src_x, short src_y, short drw_x,
76116fd1166Smrg                short drw_y, short src_w, short src_h,
76216fd1166Smrg                short drw_w, short drw_h, int format,
76316fd1166Smrg                unsigned char *buf, short width,
76416fd1166Smrg                short height, RegionPtr clipBoxes)
7656df26cacSmrg{
7666df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
7676df26cacSmrg    uint32 *fifoItem;
7686df26cacSmrg    int i, regId;
7696df26cacSmrg    struct PACKED _item {
7706df26cacSmrg        uint32 regId;
7716df26cacSmrg        uint32 value;
7726df26cacSmrg    };
7736df26cacSmrg
7746df26cacSmrg    struct PACKED _body {
7756df26cacSmrg        uint32 escape;
7766df26cacSmrg        uint32 streamId;
7776df26cacSmrg        struct _item items[SVGA_VIDEO_NUM_REGS];
7786df26cacSmrg    };
7796df26cacSmrg
7806df26cacSmrg    struct PACKED _cmdSetRegs {
7816df26cacSmrg        uint32 cmd;
7826df26cacSmrg        uint32 nsid;
7836df26cacSmrg        uint32 size;
7846df26cacSmrg        struct _body body;
7856df26cacSmrg    };
7866df26cacSmrg
7876df26cacSmrg    struct _cmdSetRegs cmdSetRegs;
7886df26cacSmrg    struct _item *items;
78916fd1166Smrg    int size;
79016fd1166Smrg    VMWAREVideoFmtData *fmtData;
79116fd1166Smrg    unsigned short w, h;
7926df26cacSmrg
79316fd1166Smrg    w = width;
79416fd1166Smrg    h = height;
79516fd1166Smrg    fmtData = pVid->fmt_priv;
79616fd1166Smrg
79716fd1166Smrg    size = vmwareQueryImageAttributes(pScrn, format, &w, &h,
79816fd1166Smrg                                      fmtData->pitches, fmtData->offsets);
79916fd1166Smrg
80016fd1166Smrg    if (size > pVid->size) {
80116fd1166Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Increase in size of Xv video "
80216fd1166Smrg                   "frame streamId:%d.\n", pVid->streamId);
80316fd1166Smrg        vmwareStopVideo(pScrn, pVid, TRUE);
80416fd1166Smrg        return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w,
80516fd1166Smrg                          src_h, drw_w, drw_h, format, buf, width, height,
80616fd1166Smrg                          clipBoxes);
80716fd1166Smrg    }
80816fd1166Smrg
80916fd1166Smrg    pVid->size = size;
8106df26cacSmrg    memcpy(pVid->bufs[pVid->currBuf].data, buf, pVid->size);
8116df26cacSmrg
8126df26cacSmrg    cmdSetRegs.cmd = SVGA_CMD_ESCAPE;
8136df26cacSmrg    cmdSetRegs.nsid = SVGA_ESCAPE_NSID_VMWARE;
8146df26cacSmrg    cmdSetRegs.size = sizeof(cmdSetRegs.body);
8156df26cacSmrg    cmdSetRegs.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
8166df26cacSmrg    cmdSetRegs.body.streamId = pVid->streamId;
8176df26cacSmrg
8186df26cacSmrg    items = cmdSetRegs.body.items;
8196df26cacSmrg    for (i = SVGA_VIDEO_ENABLED; i < SVGA_VIDEO_NUM_REGS; i++) {
8206df26cacSmrg        items[i].regId = i;
8216df26cacSmrg    }
8226df26cacSmrg
8236df26cacSmrg    items[SVGA_VIDEO_ENABLED].value = TRUE;
8246df26cacSmrg    items[SVGA_VIDEO_DATA_OFFSET].value =
8256df26cacSmrg        pVid->bufs[pVid->currBuf].dataOffset;
8266df26cacSmrg    items[SVGA_VIDEO_SIZE].value = pVid->size;
8276df26cacSmrg    items[SVGA_VIDEO_FORMAT].value = format;
82816fd1166Smrg    items[SVGA_VIDEO_WIDTH].value = w;
82916fd1166Smrg    items[SVGA_VIDEO_HEIGHT].value = h;
8306df26cacSmrg    items[SVGA_VIDEO_SRC_X].value = src_x;
8316df26cacSmrg    items[SVGA_VIDEO_SRC_Y].value = src_y;
8326df26cacSmrg    items[SVGA_VIDEO_SRC_WIDTH].value = src_w;
8336df26cacSmrg    items[SVGA_VIDEO_SRC_HEIGHT].value = src_h;
8346df26cacSmrg    items[SVGA_VIDEO_DST_X].value = drw_x;
8356df26cacSmrg    items[SVGA_VIDEO_DST_Y].value = drw_y;
8366df26cacSmrg    items[SVGA_VIDEO_DST_WIDTH]. value = drw_w;
8376df26cacSmrg    items[SVGA_VIDEO_DST_HEIGHT].value = drw_h;
8386df26cacSmrg    items[SVGA_VIDEO_COLORKEY].value = pVid->colorKey;
8396df26cacSmrg    items[SVGA_VIDEO_FLAGS].value = pVid->flags;
8406df26cacSmrg
8416df26cacSmrg    for (i = 0, regId = SVGA_VIDEO_PITCH_1; i < 3; i++, regId++) {
84216fd1166Smrg        items[regId].value = fmtData->pitches[i];
8436df26cacSmrg    }
8446df26cacSmrg
8456df26cacSmrg    fifoItem = (uint32 *) &cmdSetRegs;
8466df26cacSmrg    for (i = 0; i <  sizeof(cmdSetRegs) / sizeof(uint32); i++) {
8476df26cacSmrg        vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]);
8486df26cacSmrg    }
8496df26cacSmrg
85016fd1166Smrg    /*
85116fd1166Smrg     *  Update the clipList and paint the colorkey, if required.
85216fd1166Smrg     */
85316fd1166Smrg    if (!vmwareIsRegionEqual(&pVid->clipBoxes, clipBoxes)) {
85416fd1166Smrg        REGION_COPY(pScrn->pScreen, &pVid->clipBoxes, clipBoxes);
85516fd1166Smrg        if (pVid->isAutoPaintColorkey) {
856a241306cSmrg	    BoxPtr boxes = REGION_RECTS(&pVid->clipBoxes);
857a241306cSmrg	    int nBoxes = REGION_NUM_RECTS(&pVid->clipBoxes);
858a241306cSmrg
85916fd1166Smrg            xf86XVFillKeyHelper(pScrn->pScreen, pVid->colorKey, clipBoxes);
860a241306cSmrg
861a241306cSmrg	    /**
862a241306cSmrg	     * Force update to paint the colorkey before the overlay flush.
863a241306cSmrg	     */
864a241306cSmrg
865a241306cSmrg	    while(nBoxes--)
866a241306cSmrg		vmwareSendSVGACmdUpdate(pVMWARE, boxes++);
867a241306cSmrg
86816fd1166Smrg        }
86916fd1166Smrg    }
87016fd1166Smrg
8716df26cacSmrg    vmwareVideoFlush(pVMWARE, pVid->streamId);
8726df26cacSmrg
8736df26cacSmrg    pVid->currBuf = ++pVid->currBuf & (VMWARE_VID_NUM_BUFFERS - 1);
87416fd1166Smrg
8756df26cacSmrg    return Success;
8766df26cacSmrg}
8776df26cacSmrg
8786df26cacSmrg
8796df26cacSmrg/*
8806df26cacSmrg *-----------------------------------------------------------------------------
8816df26cacSmrg *
8826df26cacSmrg * vmwareVideoFlush --
8836df26cacSmrg *
8846df26cacSmrg *    Sends the VIDEO_FLUSH command (FIFO ESCAPE mechanism) asking the host
8856df26cacSmrg *    to play the video stream or end it.
8866df26cacSmrg *
8876df26cacSmrg * Results:
8886df26cacSmrg *    None.
8896df26cacSmrg *
8906df26cacSmrg * Side effects:
8916df26cacSmrg *    None.
8926df26cacSmrg *
8936df26cacSmrg *-----------------------------------------------------------------------------
8946df26cacSmrg */
8956df26cacSmrg
89616fd1166Smrgstatic void
89716fd1166SmrgvmwareVideoFlush(VMWAREPtr pVMWARE, uint32 streamId)
8986df26cacSmrg{
8996df26cacSmrg    struct PACKED _body {
9006df26cacSmrg        uint32 escape;
9016df26cacSmrg        uint32 streamId;
9026df26cacSmrg    };
9036df26cacSmrg
9046df26cacSmrg    struct PACKED _cmdFlush {
9056df26cacSmrg        uint32 cmd;
9066df26cacSmrg        uint32 nsid;
9076df26cacSmrg        uint32 size;
9086df26cacSmrg        struct _body body;
9096df26cacSmrg    };
9106df26cacSmrg
9116df26cacSmrg    struct _cmdFlush cmdFlush;
9126df26cacSmrg    uint32 *fifoItem;
9136df26cacSmrg    int i;
9146df26cacSmrg
9156df26cacSmrg    cmdFlush.cmd = SVGA_CMD_ESCAPE;
9166df26cacSmrg    cmdFlush.nsid = SVGA_ESCAPE_NSID_VMWARE;
9176df26cacSmrg    cmdFlush.size = sizeof(cmdFlush.body);
9186df26cacSmrg    cmdFlush.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_FLUSH;
9196df26cacSmrg    cmdFlush.body.streamId = streamId;
9206df26cacSmrg
9216df26cacSmrg    fifoItem = (uint32 *) &cmdFlush;
9226df26cacSmrg    for (i = 0; i < sizeof(cmdFlush) / sizeof(uint32); i++) {
9236df26cacSmrg        vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]);
9246df26cacSmrg    }
9256df26cacSmrg}
9266df26cacSmrg
9276df26cacSmrg
9286df26cacSmrg/*
9296df26cacSmrg *-----------------------------------------------------------------------------
9306df26cacSmrg *
9316df26cacSmrg * vmwareVideoSetOneReg --
9326df26cacSmrg *
9336df26cacSmrg *    Sets one video register using the FIFO ESCAPE mechanidm.
9346df26cacSmrg *
9356df26cacSmrg * Results:
9366df26cacSmrg *    None.
9376df26cacSmrg *
9386df26cacSmrg * Side effects:
9396df26cacSmrg *    None.
9406df26cacSmrg *-----------------------------------------------------------------------------
9416df26cacSmrg */
9426df26cacSmrg
94316fd1166Smrgstatic void
94416fd1166SmrgvmwareVideoSetOneReg(VMWAREPtr pVMWARE, uint32 streamId,
94516fd1166Smrg                     uint32 regId, uint32 value)
9466df26cacSmrg{
9476df26cacSmrg    struct PACKED _item {
9486df26cacSmrg        uint32 regId;
9496df26cacSmrg        uint32 value;
9506df26cacSmrg    };
9516df26cacSmrg
9526df26cacSmrg    struct PACKED _body {
9536df26cacSmrg        uint32 escape;
9546df26cacSmrg        uint32 streamId;
9556df26cacSmrg        struct _item item;
9566df26cacSmrg    };
9576df26cacSmrg
9586df26cacSmrg    struct PACKED _cmdSetRegs {
9596df26cacSmrg        uint32 cmd;
9606df26cacSmrg        uint32 nsid;
9616df26cacSmrg        uint32 size;
9626df26cacSmrg        struct _body body;
9636df26cacSmrg    };
9646df26cacSmrg
9656df26cacSmrg    struct _cmdSetRegs cmdSetRegs;
9666df26cacSmrg    int i;
9676df26cacSmrg    uint32 *fifoItem;
9686df26cacSmrg
9696df26cacSmrg    cmdSetRegs.cmd = SVGA_CMD_ESCAPE;
9706df26cacSmrg    cmdSetRegs.nsid = SVGA_ESCAPE_NSID_VMWARE;
9716df26cacSmrg    cmdSetRegs.size = sizeof(cmdSetRegs.body);
9726df26cacSmrg    cmdSetRegs.body.escape = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
9736df26cacSmrg    cmdSetRegs.body.streamId = streamId;
9746df26cacSmrg    cmdSetRegs.body.item.regId = regId;
9756df26cacSmrg    cmdSetRegs.body.item.value = value;
9766df26cacSmrg
9776df26cacSmrg    fifoItem = (uint32 *) &cmdSetRegs;
9786df26cacSmrg    for (i = 0; i < sizeof(cmdSetRegs) / sizeof(uint32); i++) {
9796df26cacSmrg        vmwareWriteWordToFIFO(pVMWARE, fifoItem[i]);
9806df26cacSmrg    }
9816df26cacSmrg}
9826df26cacSmrg
9836df26cacSmrg
9846df26cacSmrg/*
9856df26cacSmrg *-----------------------------------------------------------------------------
9866df26cacSmrg *
9876df26cacSmrg * vmwareVideoEndStream --
9886df26cacSmrg *
9896df26cacSmrg *    Frees up all resources (if any) taken by a video stream.
9906df26cacSmrg *
9916df26cacSmrg * Results:
9926df26cacSmrg *    None.
9936df26cacSmrg *
9946df26cacSmrg * Side effects:
9956df26cacSmrg *    Same as above.
9966df26cacSmrg *
9976df26cacSmrg *-----------------------------------------------------------------------------
9986df26cacSmrg */
9996df26cacSmrg
100016fd1166Smrgstatic void
100116fd1166SmrgvmwareVideoEndStream(ScrnInfoPtr pScrn, VMWAREVideoPtr pVid)
10026df26cacSmrg{
10036df26cacSmrg    uint32 id, colorKey, flags;
100416fd1166Smrg    Bool isAutoPaintColorkey;
10056df26cacSmrg
10066df26cacSmrg    if (pVid->fmt_priv) {
10076df26cacSmrg        free(pVid->fmt_priv);
10086df26cacSmrg    }
10096df26cacSmrg
10106df26cacSmrg    if (pVid->fbarea) {
10116df26cacSmrg        vmwareOffscreenFree(pVid->fbarea);
10126df26cacSmrg        pVid->fbarea =  NULL;
10136df26cacSmrg    }
10146df26cacSmrg
10156df26cacSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10166df26cacSmrg               "Terminating Xv video-stream id:%d\n", pVid->streamId);
10176df26cacSmrg    /*
10186df26cacSmrg     * reset stream for next video
10196df26cacSmrg     */
10206df26cacSmrg    id = pVid->streamId;
10216df26cacSmrg    colorKey = pVid->colorKey;
10226df26cacSmrg    flags = pVid->flags;
102316fd1166Smrg    isAutoPaintColorkey = pVid->isAutoPaintColorkey;
102416fd1166Smrg
10256df26cacSmrg    memset(pVid, 0, sizeof(*pVid));
102616fd1166Smrg
10276df26cacSmrg    pVid->streamId = id;
10286df26cacSmrg    pVid->play = vmwareVideoInitStream;
10296df26cacSmrg    pVid->colorKey = colorKey;
10306df26cacSmrg    pVid->flags = flags;
103116fd1166Smrg    pVid->isAutoPaintColorkey = isAutoPaintColorkey;
10326df26cacSmrg}
10336df26cacSmrg
10346df26cacSmrg
10356df26cacSmrg/*
10366df26cacSmrg *-----------------------------------------------------------------------------
10376df26cacSmrg *
10386df26cacSmrg * vmwareXvPutImage --
10396df26cacSmrg *
10406df26cacSmrg *    Main video playback function. It copies the passed data which is in
10416df26cacSmrg *    the specified format (e.g. FOURCC_YV12) into the overlay.
10426df26cacSmrg *
10436df26cacSmrg *    If sync is TRUE the driver should not return from this
10446df26cacSmrg *    function until it is through reading the data from buf.
10456df26cacSmrg *
10466df26cacSmrg *    There are two function prototypes to cope with the API change in X.org
10476df26cacSmrg *    7.1
10486df26cacSmrg *
10496df26cacSmrg * Results:
10506df26cacSmrg *    Success or XvBadAlloc on failure
10516df26cacSmrg *
10526df26cacSmrg * Side effects:
10536df26cacSmrg *    Video stream will be played(initialized if 1st frame) on success
10546df26cacSmrg *    or will fail on error.
10556df26cacSmrg *
10566df26cacSmrg *-----------------------------------------------------------------------------
10576df26cacSmrg */
10586df26cacSmrg
105916fd1166Smrg#ifdef HAVE_XORG_SERVER_1_0_99_901
106016fd1166Smrgstatic int
106116fd1166SmrgvmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
106216fd1166Smrg                 short drw_x, short drw_y, short src_w, short src_h,
106316fd1166Smrg                 short drw_w, short drw_h, int format,
106416fd1166Smrg                 unsigned char *buf, short width, short height,
106516fd1166Smrg                 Bool sync, RegionPtr clipBoxes, pointer data,
106616fd1166Smrg                 DrawablePtr dst)
10676df26cacSmrg#else
106816fd1166Smrgstatic int
106916fd1166SmrgvmwareXvPutImage(ScrnInfoPtr pScrn, short src_x, short src_y,
107016fd1166Smrg                 short drw_x, short drw_y, short src_w, short src_h,
107116fd1166Smrg                 short drw_w, short drw_h, int format,
107216fd1166Smrg                 unsigned char *buf, short width, short height,
107316fd1166Smrg                 Bool sync, RegionPtr clipBoxes, pointer data)
10746df26cacSmrg#endif
10756df26cacSmrg{
10766df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
10776df26cacSmrg    VMWAREVideoPtr pVid = data;
10786df26cacSmrg
10796df26cacSmrg    TRACEPOINT
10806df26cacSmrg
10816df26cacSmrg    if (!vmwareVideoEnabled(pVMWARE)) {
10826df26cacSmrg        return XvBadAlloc;
10836df26cacSmrg    }
10846df26cacSmrg
10856df26cacSmrg    return pVid->play(pScrn, pVid, src_x, src_y, drw_x, drw_y, src_w, src_h,
108616fd1166Smrg                      drw_w, drw_h, format, buf, width, height, clipBoxes);
10876df26cacSmrg}
10886df26cacSmrg
10896df26cacSmrg
10906df26cacSmrg/*
10916df26cacSmrg *-----------------------------------------------------------------------------
10926df26cacSmrg *
10936df26cacSmrg * vmwareStopVideo --
10946df26cacSmrg *
10956df26cacSmrg *    Called when we should stop playing video for a particular stream. If
10966df26cacSmrg *    Cleanup is FALSE, the "stop" operation is only temporary, and thus we
10976df26cacSmrg *    don't do anything. If Cleanup is TRUE we kill the video stream by
10986df26cacSmrg *    sending a message to the host and freeing up the stream.
10996df26cacSmrg *
11006df26cacSmrg * Results:
11016df26cacSmrg *    None.
11026df26cacSmrg *
11036df26cacSmrg * Side effects:
11046df26cacSmrg *    See above.
11056df26cacSmrg *
11066df26cacSmrg *-----------------------------------------------------------------------------
11076df26cacSmrg */
11086df26cacSmrg
110916fd1166Smrgstatic void
111016fd1166SmrgvmwareStopVideo(ScrnInfoPtr pScrn, pointer data, Bool Cleanup)
11116df26cacSmrg{
11126df26cacSmrg    VMWAREVideoPtr pVid = data;
11136df26cacSmrg    VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
11146df26cacSmrg    TRACEPOINT
11156df26cacSmrg
11166df26cacSmrg    if (!vmwareVideoEnabled(pVMWARE)) {
11176df26cacSmrg        return;
11186df26cacSmrg    }
1119a241306cSmrg
1120a241306cSmrg    REGION_EMPTY(pScrn->pScreen, &pVid->clipBoxes);
1121a241306cSmrg
11226df26cacSmrg    if (!Cleanup) {
112316fd1166Smrg        VmwareLog(("vmwareStopVideo: Cleanup is FALSE.\n"));
11246df26cacSmrg        return;
11256df26cacSmrg    }
11266df26cacSmrg    vmwareVideoSetOneReg(pVMWARE, pVid->streamId,
11276df26cacSmrg                         SVGA_VIDEO_ENABLED, FALSE);
11286df26cacSmrg
11296df26cacSmrg    vmwareVideoFlush(pVMWARE, pVid->streamId);
11306df26cacSmrg    vmwareVideoEndStream(pScrn, pVid);
11316df26cacSmrg
11326df26cacSmrg}
11336df26cacSmrg
11346df26cacSmrg
11356df26cacSmrg/*
11366df26cacSmrg *-----------------------------------------------------------------------------
11376df26cacSmrg *
11386df26cacSmrg * vmwareQueryImageAttributes --
11396df26cacSmrg *
11406df26cacSmrg *    From the spec: This function is called to let the driver specify how data
11416df26cacSmrg *    for a particular image of size width by height should be stored.
11426df26cacSmrg *    Sometimes only the size and corrected width and height are needed. In
11436df26cacSmrg *    that case pitches and offsets are NULL.
11446df26cacSmrg *
11456df26cacSmrg * Results:
11466df26cacSmrg *    The size of the memory required for the image, or -1 on error.
11476df26cacSmrg *
11486df26cacSmrg * Side effects:
11496df26cacSmrg *    None.
11506df26cacSmrg *
11516df26cacSmrg *-----------------------------------------------------------------------------
11526df26cacSmrg */
11536df26cacSmrg
115416fd1166Smrgstatic int
115516fd1166SmrgvmwareQueryImageAttributes(ScrnInfoPtr pScrn, int format,
115616fd1166Smrg                           unsigned short *width, unsigned short *height,
115716fd1166Smrg                           int *pitches, int *offsets)
11586df26cacSmrg{
11596df26cacSmrg    INT32 size, tmp;
11606df26cacSmrg
11616df26cacSmrg    TRACEPOINT
11626df26cacSmrg
11636df26cacSmrg    if (*width > VMWARE_VID_MAX_WIDTH) {
11646df26cacSmrg        *width = VMWARE_VID_MAX_WIDTH;
11656df26cacSmrg    }
11666df26cacSmrg    if (*height > VMWARE_VID_MAX_HEIGHT) {
11676df26cacSmrg        *height = VMWARE_VID_MAX_HEIGHT;
11686df26cacSmrg    }
11696df26cacSmrg
11706df26cacSmrg    *width = (*width + 1) & ~1;
11716df26cacSmrg    if (offsets != NULL) {
11726df26cacSmrg        offsets[0] = 0;
11736df26cacSmrg    }
11746df26cacSmrg
11756df26cacSmrg    switch (format) {
11766df26cacSmrg       case FOURCC_YV12:
11776df26cacSmrg           *height = (*height + 1) & ~1;
11786df26cacSmrg           size = (*width + 3) & ~3;
11796df26cacSmrg           if (pitches) {
11806df26cacSmrg               pitches[0] = size;
11816df26cacSmrg           }
11826df26cacSmrg           size *= *height;
11836df26cacSmrg           if (offsets) {
11846df26cacSmrg               offsets[1] = size;
11856df26cacSmrg           }
11866df26cacSmrg           tmp = ((*width >> 1) + 3) & ~3;
11876df26cacSmrg           if (pitches) {
11886df26cacSmrg                pitches[1] = pitches[2] = tmp;
11896df26cacSmrg           }
11906df26cacSmrg           tmp *= (*height >> 1);
11916df26cacSmrg           size += tmp;
11926df26cacSmrg           if (offsets) {
11936df26cacSmrg               offsets[2] = size;
11946df26cacSmrg           }
11956df26cacSmrg           size += tmp;
11966df26cacSmrg           break;
119716fd1166Smrg       case FOURCC_UYVY:
11986df26cacSmrg       case FOURCC_YUY2:
11996df26cacSmrg           size = *width * 2;
12006df26cacSmrg           if (pitches) {
12016df26cacSmrg               pitches[0] = size;
12026df26cacSmrg           }
12036df26cacSmrg           size *= *height;
12046df26cacSmrg           break;
12056df26cacSmrg       default:
12066df26cacSmrg           VmwareLog(("Query for invalid video format %d\n", format));
12076df26cacSmrg           return -1;
12086df26cacSmrg    }
12096df26cacSmrg    return size;
12106df26cacSmrg}
12116df26cacSmrg
12126df26cacSmrg
12136df26cacSmrg/*
12146df26cacSmrg *-----------------------------------------------------------------------------
12156df26cacSmrg *
12166df26cacSmrg * vmwareSetPortAttribute --
12176df26cacSmrg *
12186df26cacSmrg *    From the spec: A port may have particular attributes such as colorKey, hue,
12196df26cacSmrg *    saturation, brightness or contrast. Xv clients set these
12206df26cacSmrg *    attribute values by sending attribute strings (Atoms) to the server.
12216df26cacSmrg *
12226df26cacSmrg * Results:
12236df26cacSmrg *    Success if the attribute exists and XvBadAlloc otherwise.
12246df26cacSmrg *
12256df26cacSmrg * Side effects:
12266df26cacSmrg *    The respective attribute gets the new value.
12276df26cacSmrg *
12286df26cacSmrg *-----------------------------------------------------------------------------
12296df26cacSmrg */
12306df26cacSmrg
123116fd1166Smrgstatic int
123216fd1166SmrgvmwareSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
123316fd1166Smrg                       INT32 value, pointer data)
12346df26cacSmrg{
12356df26cacSmrg    VMWAREVideoPtr pVid = (VMWAREVideoPtr) data;
12366df26cacSmrg    Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
123716fd1166Smrg    Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
12386df26cacSmrg
12396df26cacSmrg    if (attribute == xvColorKey) {
124016fd1166Smrg        VmwareLog(("Set colorkey:0x%x\n", value));
12416df26cacSmrg        pVid->colorKey = value;
124216fd1166Smrg    } else if (attribute == xvAutoPaint) {
124316fd1166Smrg        VmwareLog(("Set autoPaint: %s\n", value? "TRUE": "FALSE"));
124416fd1166Smrg        pVid->isAutoPaintColorkey = value;
12456df26cacSmrg    } else {
12466df26cacSmrg        return XvBadAlloc;
12476df26cacSmrg    }
124816fd1166Smrg
12496df26cacSmrg    return Success;
12506df26cacSmrg}
12516df26cacSmrg
12526df26cacSmrg
12536df26cacSmrg/*
12546df26cacSmrg *-----------------------------------------------------------------------------
12556df26cacSmrg *
12566df26cacSmrg * vmwareGetPortAttribute --
12576df26cacSmrg *
12586df26cacSmrg *    From the spec: A port may have particular attributes such as hue,
12596df26cacSmrg *    saturation, brightness or contrast. Xv clients get these
12606df26cacSmrg *    attribute values by sending attribute strings (Atoms) to the server
12616df26cacSmrg *
12626df26cacSmrg * Results:
12636df26cacSmrg *    Success if the attribute exists and XvBadAlloc otherwise.
12646df26cacSmrg *
12656df26cacSmrg * Side effects:
12666df26cacSmrg *    "value" contains the requested attribute on success.
12676df26cacSmrg *
12686df26cacSmrg *-----------------------------------------------------------------------------
12696df26cacSmrg */
12706df26cacSmrg
127116fd1166Smrgstatic int
127216fd1166SmrgvmwareGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
127316fd1166Smrg                       INT32 *value, pointer data)
12746df26cacSmrg{
12756df26cacSmrg    VMWAREVideoPtr pVid = (VMWAREVideoPtr) data;
12766df26cacSmrg    Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
127716fd1166Smrg    Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
12786df26cacSmrg
12796df26cacSmrg    if (attribute == xvColorKey) {
12806df26cacSmrg        *value = pVid->colorKey;
128116fd1166Smrg    } else if (attribute == xvAutoPaint) {
128216fd1166Smrg        *value = pVid->isAutoPaintColorkey;
12836df26cacSmrg    } else {
12846df26cacSmrg        return XvBadAlloc;
12856df26cacSmrg    }
128616fd1166Smrg
12876df26cacSmrg    return Success;
12886df26cacSmrg}
12896df26cacSmrg
12906df26cacSmrg
12916df26cacSmrg/*
12926df26cacSmrg *-----------------------------------------------------------------------------
12936df26cacSmrg *
12946df26cacSmrg * vmwareQueryBestSize --
12956df26cacSmrg *
12966df26cacSmrg *    From the spec: QueryBestSize provides the client with a way to query what
12976df26cacSmrg *    the destination dimensions would end up being if they were to request
12986df26cacSmrg *    that an area vid_w by vid_h from the video stream be scaled to rectangle
12996df26cacSmrg *    of drw_w by drw_h on the screen. Since it is not expected that all
13006df26cacSmrg *    hardware will be able to get the target dimensions exactly, it is
13016df26cacSmrg *    important that the driver provide this function.
13026df26cacSmrg *
13036df26cacSmrg *    This function seems to never be called, but to be on the safe side
13046df26cacSmrg *    we apply the same logic that QueryImageAttributes has for width
13056df26cacSmrg *    and height
13066df26cacSmrg *
13076df26cacSmrg * Results:
13086df26cacSmrg *    None.
13096df26cacSmrg *
13106df26cacSmrg * Side effects:
13116df26cacSmrg *    None
13126df26cacSmrg *
13136df26cacSmrg *-----------------------------------------------------------------------------
13146df26cacSmrg */
13156df26cacSmrg
131616fd1166Smrgstatic void
131716fd1166SmrgvmwareQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
131816fd1166Smrg                    short vid_w, short vid_h, short drw_w,
131916fd1166Smrg                    short drw_h, unsigned int *p_w,
132016fd1166Smrg                    unsigned int *p_h, pointer data)
13216df26cacSmrg{
13226df26cacSmrg    *p_w = (drw_w + 1) & ~1;
13236df26cacSmrg    *p_h = drw_h;
13246df26cacSmrg
13256df26cacSmrg    return;
13266df26cacSmrg}
13276df26cacSmrg
1328