Home | History | Annotate | Download | only in x11
      1 /*
      2  * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the
      6  * "Software"), to deal in the Software without restriction, including
      7  * without limitation the rights to use, copy, modify, merge, publish,
      8  * distribute, sub license, and/or sell copies of the Software, and to
      9  * permit persons to whom the Software is furnished to do so, subject to
     10  * the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the
     13  * next paragraph) shall be included in all copies or substantial portions
     14  * of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
     20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Shengquan Yuan  <shengquan.yuan (at) intel.com>
     26  *    Zhaohan Ren  <zhaohan.ren (at) intel.com>
     27  *
     28  */
     29 
     30 
     31 #include <va/va_backend.h>
     32 #include "psb_surface.h"
     33 #include "psb_output.h"
     34 #include "psb_surface_ext.h"
     35 #include "psb_x11.h"
     36 #include "psb_xrandr.h"
     37 #include "psb_drv_debug.h"
     38 
     39 #include <X11/extensions/dpms.h>
     40 
     41 #include <wsbm/wsbm_manager.h>
     42 
     43 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
     44 #define INIT_OUTPUT_PRIV    psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
     45 
     46 #define SURFACE(id)     ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
     47 
     48 static int psb_CheckDrawable(VADriverContextP ctx, Drawable draw);
     49 
     50 int (*oldHandler)(Display *, XErrorEvent *) = 0;
     51 static int XErrorFlag = 1;
     52 static int psb_XErrorHandler(Display *dpy, XErrorEvent *event)
     53 {
     54     drv_debug_msg(VIDEO_DEBUG_GENERAL, "XErrorEvent caught in psb_XErrorHandler in psb_xvva.c\n");
     55     if (event->type == 0 && event->request_code == 132 && event->error_code == 11 /* BadAlloc */) {
     56         XErrorFlag = 1;
     57         return 0;
     58     }
     59     return oldHandler(dpy, event);
     60 }
     61 
     62 static int GetPortId(VADriverContextP ctx, psb_x11_output_p output)
     63 {
     64     int i, j, k;
     65     unsigned int numAdapt;
     66     int numImages;
     67     XvImageFormatValues *formats;
     68     XvAdaptorInfo *info;
     69     int ret, grab_ret;
     70     Display *dpy = (Display *)ctx->native_dpy;
     71 
     72     ret = XvQueryAdaptors(dpy, DefaultRootWindow(dpy), &numAdapt, &info);
     73     /*Force overlay port num equal to one. OverlayC can't be used independently now.*/
     74     /* check for numAdapt before modifying the info[1]. Without this check
     75      * it will cause a memory corruption leading to segfaults */
     76     if (numAdapt > 1)
     77         info[1].num_ports = 1;
     78 
     79     if (Success != ret) {
     80         drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't find Xvideo adaptor\n");
     81         return -1;
     82     }
     83 
     84     grab_ret = XGrabServer(ctx->native_dpy);
     85     for (i = 0; i < numAdapt; i++) {
     86         if ((info[i].type & XvImageMask) == 0)
     87             continue;
     88 
     89         formats = XvListImageFormats(dpy, info[i].base_id, &numImages);
     90         for (j = 0; j < numImages; j++) {
     91             if (formats[j].id != FOURCC_XVVA) continue;
     92             for (k = 0; k < info[i].num_ports; k++) {
     93                 int ret = XvGrabPort(dpy, info[i].base_id + k, CurrentTime);
     94 
     95                 if (Success == ret) {
     96                     /* for textured adaptor 0 */
     97                     if (i == 0)
     98                         output->textured_portID = info[i].base_id + k;
     99                     /* for overlay adaptor 1 */
    100                     if (i == 1)
    101                         output->overlay_portID = info[i].base_id + k;
    102                     break;
    103                 }
    104             }
    105         }
    106         XFree(formats);
    107     }
    108 
    109     if (grab_ret != 0)
    110         XUngrabServer(ctx->native_dpy);
    111 
    112     if ((output->textured_portID == 0) && (output->overlay_portID == 0)) {
    113         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Can't detect any usable Xv XVVA port\n");
    114         return -1;
    115     }
    116 
    117     return 0;
    118 }
    119 
    120 
    121 VAStatus psb_init_xvideo(VADriverContextP ctx, psb_x11_output_p output)
    122 {
    123 #ifdef _FOR_FPGA_
    124     return VA_STATUS_SUCCESS;
    125 #endif
    126 
    127     INIT_DRIVER_DATA;
    128     int dummy, ret;
    129 
    130     output->textured_portID = output->overlay_portID = 0;
    131     if (GetPortId(ctx, output)) {
    132         drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab Xvideo port failed, fallback to software vaPutSurface.\n");
    133         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    134     }
    135 
    136     if (output->textured_portID)
    137         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected textured Xvideo port_id = %d.\n", (unsigned int)output->textured_portID);
    138     if (output->overlay_portID)
    139         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected overlay  Xvideo port_id = %d.\n", (unsigned int)output->overlay_portID);
    140 
    141     output->sprite_enabled = 0;
    142     if (getenv("PSB_SPRITE_ENABLE")) {
    143         drv_debug_msg(VIDEO_DEBUG_GENERAL, "use sprite plane to playback rotated protected video\n");
    144         output->sprite_enabled = 1;
    145     }
    146 
    147     output->ignore_dpm = 1;
    148     if (getenv("PSB_VIDEO_DPMS_HACK")) {
    149         if (DPMSQueryExtension((Display *)ctx->native_dpy, &dummy, &dummy)
    150             && DPMSCapable((Display *)ctx->native_dpy)) {
    151             BOOL onoff;
    152             CARD16 state;
    153 
    154             DPMSInfo((Display *)ctx->native_dpy, &state, &onoff);
    155             drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is %s, monitor state=%s\n", onoff ? "enabled" : "disabled",
    156                                      (state == DPMSModeOn) ? "on" : (
    157                                          (state == DPMSModeOff) ? "off" : (
    158                                              (state == DPMSModeStandby) ? "standby" : (
    159                                                  (state == DPMSModeSuspend) ? "suspend" : "unknow"))));
    160             if (onoff)
    161                 output->ignore_dpm = 0;
    162         }
    163     }
    164 
    165     /* by default, overlay Xv */
    166     if (output->textured_portID)
    167         driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
    168     if (output->overlay_portID)
    169         driver_data->output_method = PSB_PUTSURFACE_OVERLAY;
    170 
    171     ret = psb_xrandr_init(ctx);
    172     if (ret != 0) {
    173         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to initialize psb xrandr error # %d\n", __func__, ret);
    174         return VA_STATUS_ERROR_UNKNOWN;
    175     }
    176 
    177     return VA_STATUS_SUCCESS;
    178 }
    179 
    180 
    181 VAStatus psb_deinit_xvideo(VADriverContextP ctx)
    182 {
    183     INIT_DRIVER_DATA;
    184     INIT_OUTPUT_PRIV;
    185 
    186     if (output->gc) {
    187         XFreeGC((Display *)ctx->native_dpy, output->gc);
    188         output->gc = NULL;
    189     }
    190 
    191     if (output->extend_gc) {
    192         XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
    193         output->extend_gc = NULL;
    194     }
    195 
    196     if (output->textured_xvimage) {
    197         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Destroy XvImage for texture Xv\n");
    198         XFree(output->textured_xvimage);
    199         output->textured_xvimage = NULL;
    200     }
    201 
    202     if (output->overlay_xvimage) {
    203         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Destroy XvImage for overlay  Xv\n");
    204         XFree(output->overlay_xvimage);
    205         output->textured_xvimage = NULL;
    206     }
    207 
    208     if (output->textured_portID) {
    209         if ((output->using_port == USING_TEXTURE_PORT) && output->output_drawable
    210             && (psb_CheckDrawable(ctx, output->output_drawable) == 0)) {
    211             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: stop textured Xvideo\n");
    212             XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, output->output_drawable);
    213         }
    214 
    215         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: ungrab textured Xvideo port\n");
    216         XvUngrabPort((Display *)ctx->native_dpy, output->textured_portID, CurrentTime);
    217         output->textured_portID = 0;
    218     }
    219 
    220     if (output->overlay_portID) {
    221         if ((output->using_port == USING_OVERLAY_PORT) && output->output_drawable
    222             && (psb_CheckDrawable(ctx, output->output_drawable) == 0)) {
    223             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: stop overlay Xvideo\n");
    224             XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, output->output_drawable);
    225         }
    226 
    227         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: ungrab overlay Xvideo port\n");
    228         XvUngrabPort((Display *)ctx->native_dpy, output->overlay_portID, CurrentTime);
    229         output->overlay_portID = 0;
    230     }
    231 
    232     if (driver_data->use_xrandr_thread && driver_data->xrandr_thread_id) {
    233         psb_xrandr_thread_exit();
    234         pthread_join(driver_data->xrandr_thread_id, NULL);
    235         driver_data->xrandr_thread_id = 0;
    236     }
    237     psb_xrandr_deinit();
    238 
    239     output->using_port = 0;
    240     output->output_drawable = 0;
    241     output->extend_drawable = 0;
    242 #ifndef _FOR_FPGA_
    243     XSync((Display *)ctx->native_dpy, False);
    244 #endif
    245     return VA_STATUS_SUCCESS;
    246 }
    247 
    248 
    249 static void psb_surface_init(
    250     psb_driver_data_p driver_data,
    251     PsbVASurfaceRec *srf,
    252     int fourcc, int bpp, int w, int h, int stride, int size, unsigned int pre_add,
    253     struct _WsbmBufferObject *bo, int flags
    254 )
    255 {
    256     memset(srf, 0, sizeof(*srf));
    257 
    258     srf->fourcc = fourcc;
    259     srf->bo = bo;
    260     if (bo != NULL) {
    261         srf->bufid = wsbmKBufHandle(wsbmKBuf(bo));
    262         srf->pl_flags = wsbmBOPlacementHint(bo);
    263     }
    264 
    265 /*
    266     if (srf->pl_flags & DRM_PSB_FLAG_MEM_CI)
    267         srf->reserved_phyaddr = driver_data->camera_phyaddr;
    268     if (srf->pl_flags & DRM_PSB_FLAG_MEM_RAR)
    269         srf->reserved_phyaddr = driver_data->rar_phyaddr;
    270 */
    271     srf->bytes_pp = bpp;
    272 
    273     srf->width = w;
    274     srf->pre_add = pre_add;
    275     if ((flags == VA_TOP_FIELD) || (flags == VA_BOTTOM_FIELD)) {
    276         if (driver_data->output_method ==  PSB_PUTSURFACE_FORCE_OVERLAY
    277             || driver_data->output_method == PSB_PUTSURFACE_OVERLAY) {
    278             srf->height = h;
    279             srf->stride = stride;
    280         } else {
    281             srf->height = h / 2;
    282             srf->stride = stride * 2;
    283         }
    284         if (flags == VA_BOTTOM_FIELD)
    285             srf->pre_add += stride;
    286     } else {
    287         srf->height = h;
    288         srf->stride = stride;
    289     }
    290 
    291     srf->size = size;
    292 
    293     if (flags == VA_CLEAR_DRAWABLE) {
    294         srf->clear_color = driver_data->clear_color; /* color */
    295         return;
    296     }
    297 }
    298 
    299 #if 0
    300 
    301 #define WINDOW 1
    302 #define PIXMAP 0
    303 
    304 /* return 0 for no rotation, 1 for rotation occurs */
    305 /* XRRGetScreenInfo has significant performance drop */
    306 static int  psb__CheckCurrentRotation(VADriverContextP ctx)
    307 {
    308     Rotation current_rotation;
    309     XRRScreenConfiguration *scrn_cfg;
    310     scrn_cfg = XRRGetScreenInfo((Display *)ctx->native_dpy, DefaultRootWindow((Display *)ctx->native_dpy));
    311     XRRConfigCurrentConfiguration(scrn_cfg, &current_rotation);
    312     XRRFreeScreenConfigInfo(scrn_cfg);
    313     return (current_rotation & 0x0f);
    314 }
    315 
    316 /* Check drawable type, 1 for window, 0 for pixmap
    317  * Have significant performance drop in XFCE environment
    318  */
    319 static void psb__CheckDrawableType(Display *dpy, Window win, Drawable draw, int *type_ret)
    320 {
    321 
    322     unsigned int child_num;
    323     Window root_return;
    324     Window parent_return;
    325     Window *child_return;
    326     int i;
    327 
    328     if (win == draw) {
    329         *type_ret = 1;
    330         return;
    331     }
    332 
    333     XQueryTree(dpy, win, &root_return, &parent_return, &child_return, &child_num);
    334 
    335     if (!child_num)
    336         return;
    337 
    338     for (i = 0; i < child_num; i++)
    339         psb__CheckDrawableType(dpy, child_return[i], draw, type_ret);
    340 }
    341 #endif
    342 
    343 
    344 static int psb_CheckDrawable(VADriverContextP ctx, Drawable draw)
    345 {
    346     INIT_DRIVER_DATA;
    347     INIT_OUTPUT_PRIV;
    348     Atom xvDrawable = XInternAtom((Display *)ctx->native_dpy, "XV_DRAWABLE", 0);
    349     int val = 0;
    350 
    351     driver_data->drawable_info = 0;
    352     if (output->overlay_portID) {
    353         XvSetPortAttribute((Display *)ctx->native_dpy, output->overlay_portID, xvDrawable, draw);
    354         XvGetPortAttribute((Display *)ctx->native_dpy, output->overlay_portID, xvDrawable, &val);
    355     } else if (output->textured_portID) {
    356         XvSetPortAttribute((Display *)ctx->native_dpy, output->textured_portID, xvDrawable, draw);
    357         XvGetPortAttribute((Display *)ctx->native_dpy, output->textured_portID, xvDrawable, &val);
    358     }
    359     driver_data->drawable_info = val;
    360 
    361     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Get xvDrawable = 0x%08x\n", val);
    362 
    363     if (driver_data->drawable_info == XVDRAWABLE_INVALID_DRAWABLE)
    364         return -1;
    365 
    366     return 0;
    367 }
    368 
    369 static int psb__CheckPutSurfaceXvPort(
    370     VADriverContextP ctx,
    371     VASurfaceID surface,
    372     Drawable draw, /* X Drawable */
    373     short srcx,
    374     short srcy,
    375     unsigned short srcw,
    376     unsigned short srch,
    377     short destx,
    378     short desty,
    379     unsigned short destw,
    380     unsigned short desth,
    381     VARectangle *cliprects, /* client supplied clip list */
    382     unsigned int number_cliprects, /* number of clip rects in the clip list */
    383     unsigned int flags /* de-interlacing flags */
    384 )
    385 {
    386     INIT_DRIVER_DATA;
    387     INIT_OUTPUT_PRIV;
    388     object_surface_p obj_surface = SURFACE(surface);
    389     uint32_t buf_pl;
    390 
    391     /* silent klockwork */
    392     if (obj_surface && obj_surface->psb_surface)
    393         buf_pl = obj_surface->psb_surface->buf.pl_flags;
    394     else
    395         return -1;
    396 
    397     if (flags & VA_CLEAR_DRAWABLE)
    398         return 0;
    399 
    400     if (output->overlay_portID == 0) { /* no overlay usable */
    401         driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
    402         return 0;
    403     }
    404 
    405     if (driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY) {
    406         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force Overlay Xvideo for PutSurface\n");
    407         return 0;
    408     }
    409 
    410     if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXTURE)) {
    411         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force Textured Xvideo for PutSurface\n");
    412         return 0;
    413     }
    414 
    415     if (((buf_pl & (WSBM_PL_FLAG_TT)) == 0) /* buf not in TT/RAR or CI */
    416         || (obj_surface->width > 1920)  /* overlay have isue to support >1920xXXX resolution */
    417         || (obj_surface->subpic_count > 0)  /* overlay can't support subpicture */
    418         /*    || (flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD))*/
    419        ) {
    420         driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
    421         return 0;
    422     }
    423 
    424 
    425     /* Here should be overlay XV by defaut after overlay is stable */
    426     driver_data->output_method = PSB_PUTSURFACE_OVERLAY;
    427     /* driver_data->output_method = PSB_PUTSURFACE_TEXTURE; */
    428 
    429     /*
    430      *Query Overlay Adaptor by XvDrawable Attribute to know current
    431      * Xrandr information:rotation/downscaling
    432      * also set target drawable(window vs pixmap) into XvDrawable
    433      * to levage Xserver to determiate it is Pixmap or Window
    434      */
    435     /*
    436      *ROTATE_90: 0x2, ROTATE_180: 0x4, ROTATE_270:0x8
    437      *Overlay adopator can support video rotation,
    438      *but its performance is lower than texture video path.
    439      *When video protection and rotation are required (use RAR buffer),
    440      *only overlay adaptor will be used.
    441      *other attribute like down scaling and pixmap, use texture adaptor
    442      */
    443     if (driver_data->drawable_info
    444         & (XVDRAWABLE_ROTATE_180 | XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270)) {
    445             driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
    446     }
    447 
    448     if (driver_data->drawable_info & (XVDRAWABLE_PIXMAP | XVDRAWABLE_REDIRECT_WINDOW))
    449         driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
    450 
    451     if (srcw >= destw * 8 || srch >= desth * 8)
    452         driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
    453 
    454     return 0;
    455 }
    456 
    457 
    458 static int psb__CheckGCXvImage(
    459     VADriverContextP ctx,
    460     VASurfaceID surface,
    461     Drawable draw,
    462     XvImage **xvImage,
    463     XvPortID *port_id,
    464     unsigned int flags /* de-interlacing flags */
    465 )
    466 {
    467     INIT_DRIVER_DATA;
    468     INIT_OUTPUT_PRIV;
    469     object_surface_p obj_surface = SURFACE(surface); /* surface already checked */
    470 
    471     if (output->output_drawable != draw) {
    472         if (output->gc)
    473             XFreeGC((Display *)ctx->native_dpy, output->gc);
    474         output->gc = XCreateGC((Display *)ctx->native_dpy, draw, 0, NULL);
    475         output->output_drawable = draw;
    476     }
    477 
    478     if (flags & VA_CLEAR_DRAWABLE) {
    479         if (output->textured_portID && (output->using_port == USING_TEXTURE_PORT)) {
    480             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clear drawable, and stop textured Xvideo\n");
    481             XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, draw);
    482         }
    483 
    484         if (output->overlay_portID && (output->using_port == USING_OVERLAY_PORT)) {
    485             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clear drawable, and stop overlay Xvideo\n");
    486             XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, draw);
    487         }
    488 
    489         output->using_port = 0;
    490 
    491         XSetForeground((Display *)ctx->native_dpy, output->gc, driver_data->clear_color);
    492 
    493         return 0;
    494     }
    495 
    496     if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY) ||
    497         (driver_data->output_method == PSB_PUTSURFACE_OVERLAY)) {
    498         /* use OVERLAY XVideo */
    499         if (obj_surface &&
    500             ((output->output_width != obj_surface->width) ||
    501              (output->output_height != obj_surface->height) ||
    502              (!output->overlay_xvimage))) {
    503 
    504             if (output->overlay_xvimage)
    505                 XFree(output->overlay_xvimage);
    506 
    507             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create new XvImage for overlay\n");
    508             output->overlay_xvimage = XvCreateImage((Display *)ctx->native_dpy, output->overlay_portID,
    509                                                     FOURCC_XVVA, 0,
    510                                                     obj_surface->width, obj_surface->height);
    511 
    512             output->overlay_xvimage->data = (char *) & output->imgdata_vasrf;
    513             output->output_width = obj_surface->width;
    514             output->output_height = obj_surface->height;
    515         }
    516         *xvImage = output->overlay_xvimage;
    517         *port_id = output->overlay_portID;
    518 
    519         if ((output->textured_portID) && (output->using_port == USING_TEXTURE_PORT)) { /* stop texture port */
    520             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using overlay xvideo, stop textured xvideo\n");
    521             XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, draw);
    522             XSync((Display *)ctx->native_dpy, False);
    523         }
    524         output->using_port = USING_OVERLAY_PORT;
    525 
    526         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using Overlay Xvideo (%d) for PutSurface\n", output->textured_portID);
    527 
    528         return 0;
    529     }
    530 
    531     if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXTURE) ||
    532         (driver_data->output_method == PSB_PUTSURFACE_TEXTURE)) {
    533         /* use Textured XVideo */
    534         if (obj_surface &&
    535             ((output->output_width != obj_surface->width) ||
    536              (output->output_height != obj_surface->height ||
    537               (!output->textured_xvimage)))) {
    538             if (output->textured_xvimage)
    539                 XFree(output->textured_xvimage);
    540 
    541             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create new XvImage for overlay\n");
    542             output->textured_xvimage = XvCreateImage((Display *)ctx->native_dpy, output->textured_portID, FOURCC_XVVA, 0,
    543                                        obj_surface->width, obj_surface->height);
    544             output->textured_xvimage->data = (char *) & output->imgdata_vasrf;
    545             output->output_width = obj_surface->width;
    546             output->output_height = obj_surface->height;
    547 
    548         }
    549 
    550         *xvImage = output->textured_xvimage;
    551         *port_id = output->textured_portID;
    552 
    553         if ((output->overlay_portID) && (output->using_port == USING_OVERLAY_PORT)) { /* stop overlay port */
    554             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using textured xvideo, stop Overlay xvideo\n");
    555             XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, draw);
    556             XSync((Display *)ctx->native_dpy, False);
    557 
    558             output->using_port = USING_TEXTURE_PORT;
    559         }
    560 
    561         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using Texture Xvideo (%d) for PutSurface\n", output->textured_portID);
    562 
    563         return 0;
    564     }
    565 
    566     return 0;
    567 }
    568 
    569 static int psb_force_dpms_on(VADriverContextP ctx)
    570 {
    571     BOOL onoff;
    572     CARD16 state;
    573 
    574     DPMSInfo((Display *)ctx->native_dpy, &state, &onoff);
    575     drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is %s, monitor state=%s\n", onoff ? "enabled" : "disabled",
    576                              (state == DPMSModeOn) ? "on" : (
    577                                  (state == DPMSModeOff) ? "off" : (
    578                                      (state == DPMSModeStandby) ? "standby" : (
    579                                          (state == DPMSModeSuspend) ? "suspend" : "unknow"))));
    580     if (onoff && (state != DPMSModeOn)) {
    581         drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is enabled, and monitor isn't DPMSModeOn, force it on\n");
    582         DPMSForceLevel((Display *)ctx->native_dpy, DPMSModeOn);
    583     }
    584 
    585     return 0;
    586 }
    587 
    588 VAStatus psb_check_rotatesurface(
    589     VADriverContextP ctx,
    590     unsigned short rotate_width,
    591     unsigned short rotate_height,
    592     unsigned int protected,
    593     int fourcc
    594 )
    595 {
    596     INIT_DRIVER_DATA;
    597     INIT_OUTPUT_PRIV;
    598     VAStatus vaStatus = VA_STATUS_SUCCESS;
    599     object_surface_p obj_rotate_surface;
    600     unsigned int flags = protected? IS_PROTECTED : 0;
    601 
    602     if (output->rotate_surface) {
    603         obj_rotate_surface = SURFACE(output->rotate_surfaceID);
    604         if (obj_rotate_surface &&
    605             ((obj_rotate_surface->width != rotate_width)
    606              || (obj_rotate_surface->height != rotate_height))) {
    607             psb_surface_destroy(output->rotate_surface);
    608             free(output->rotate_surface);
    609             object_heap_free(&driver_data->surface_heap, (object_base_p)obj_rotate_surface);
    610             output->rotate_surface = NULL;
    611         }
    612     }
    613     if (output->rotate_surface == NULL) {
    614         output->rotate_surfaceID = object_heap_allocate(&driver_data->surface_heap);
    615         obj_rotate_surface = SURFACE(output->rotate_surfaceID);
    616         if (NULL == obj_rotate_surface) {
    617             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    618             DEBUG_FAILURE;
    619 
    620             return VA_STATUS_ERROR_ALLOCATION_FAILED;
    621         }
    622 
    623         obj_rotate_surface->surface_id = output->rotate_surfaceID;
    624         obj_rotate_surface->context_id = -1;
    625         obj_rotate_surface->width = rotate_width;
    626         obj_rotate_surface->height = rotate_height;
    627         obj_rotate_surface->subpictures = NULL;
    628         obj_rotate_surface->subpic_count = 0;
    629         obj_rotate_surface->derived_imgcnt = 0;
    630         output->rotate_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
    631         if (NULL == output->rotate_surface) {
    632             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_rotate_surface);
    633             obj_rotate_surface->surface_id = VA_INVALID_SURFACE;
    634 
    635             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    636 
    637             DEBUG_FAILURE;
    638 
    639             return VA_STATUS_ERROR_ALLOCATION_FAILED;
    640         }
    641 
    642         flags |= IS_ROTATED;
    643         vaStatus = psb_surface_create(driver_data, rotate_width, rotate_height,
    644                                       fourcc, flags, output->rotate_surface);
    645         if (VA_STATUS_SUCCESS != vaStatus) {
    646             free(obj_rotate_surface->psb_surface);
    647             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_rotate_surface);
    648             obj_rotate_surface->surface_id = VA_INVALID_SURFACE;
    649 
    650             DEBUG_FAILURE;
    651             return vaStatus;
    652         }
    653         obj_rotate_surface->psb_surface = output->rotate_surface;
    654     }
    655     return vaStatus;
    656 }
    657 
    658 VAStatus psb_putsurface_xvideo(
    659     VADriverContextP ctx,
    660     VASurfaceID surface,
    661     Drawable draw,
    662     short srcx,
    663     short srcy,
    664     unsigned short srcw,
    665     unsigned short srch,
    666     short destx,
    667     short desty,
    668     unsigned short destw,
    669     unsigned short desth,
    670     VARectangle *cliprects, /* client supplied clip list */
    671     unsigned int number_cliprects, /* number of clip rects in the clip list */
    672     unsigned int flags /* de-interlacing flags */
    673 )
    674 {
    675     INIT_DRIVER_DATA;
    676     INIT_OUTPUT_PRIV;
    677     VAStatus vaStatus = VA_STATUS_SUCCESS;
    678     PsbVASurfaceRec *subpic_surface;
    679     PsbXvVAPutSurfacePtr vaPtr;
    680     XvPortID    portID = 0;
    681     XvImage *xvImage = NULL;
    682     object_surface_p obj_surface = SURFACE(surface);
    683     psb_surface_p psb_surface;
    684     int i = 0, j;
    685 
    686 
    687     if (obj_surface) /* silent klockwork, we already check it */
    688         psb_surface = obj_surface->psb_surface;
    689     else
    690         return VA_STATUS_ERROR_UNKNOWN;
    691 
    692     /* Catch X protocol errors with our own error handler */
    693     if (oldHandler == 0)
    694         oldHandler = XSetErrorHandler(psb_XErrorHandler);
    695 
    696     if (XErrorFlag == 1) {
    697         if (psb_CheckDrawable(ctx, draw) != 0) {
    698             drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: invalidate drawable\n");
    699             return VA_STATUS_ERROR_UNKNOWN;
    700         }
    701 
    702         drv_debug_msg(VIDEO_DEBUG_GENERAL, "ran psb_CheckDrawable the first time!\n");
    703         XErrorFlag = 0;
    704     }
    705 
    706     /* check display configuration for every 100 frames */
    707     if ((driver_data->frame_count % 100) == 0) {
    708         if (psb_CheckDrawable(ctx, draw) != 0) {
    709             drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: invalidate drawable\n");
    710             return VA_STATUS_ERROR_UNKNOWN;
    711         }
    712         drv_debug_msg(VIDEO_DEBUG_GENERAL, "ran psb_CheckDrawable the first time!\n");
    713     }
    714 
    715 
    716 
    717     psb__CheckPutSurfaceXvPort(ctx, surface, draw,
    718                                srcx, srcy, srcw, srch,
    719                                destx, desty, destw, desth,
    720                                cliprects, number_cliprects, flags);
    721     psb__CheckGCXvImage(ctx, surface, draw, &xvImage, &portID, flags);
    722 
    723     if (flags & VA_CLEAR_DRAWABLE) {
    724         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clean draw with color 0x%08x\n", driver_data->clear_color);
    725 
    726         XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, destx, desty, destw, desth);
    727         XSync((Display *)ctx->native_dpy, False);
    728 
    729         XFreeGC((Display *)ctx->native_dpy, output->gc);
    730         output->gc = NULL;
    731         output->output_drawable = 0;
    732 
    733         XSync((Display *)ctx->native_dpy, False);
    734 
    735         driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
    736         driver_data->last_displaying_surface = VA_INVALID_SURFACE;
    737         obj_surface->display_timestamp = 0;
    738 
    739 
    740         return vaStatus;
    741     }
    742 
    743     vaPtr = (PsbXvVAPutSurfacePtr)xvImage->data;
    744     vaPtr->flags = flags;
    745     vaPtr->num_subpicture = obj_surface->subpic_count;
    746     vaPtr->num_clipbox = number_cliprects;
    747     for (j = 0; j < number_cliprects; j++) {
    748         vaPtr->clipbox[j].x = cliprects[j].x;
    749         vaPtr->clipbox[j].y = cliprects[j].y;
    750         vaPtr->clipbox[j].width = cliprects[j].width;
    751         vaPtr->clipbox[j].height = cliprects[j].height;
    752     }
    753 
    754     psb_surface_init(driver_data, &vaPtr->src_srf, VA_FOURCC_NV12, 2,
    755                      obj_surface->width, obj_surface->height,
    756                      psb_surface->stride, psb_surface->size,
    757                      psb_surface->buf.buffer_ofs, /* for surface created from RAR/camera device memory
    758                                                    * all surfaces share one BO but with different offset
    759                                                    * pass the offset as the "pre_add"
    760                                                    */
    761                      psb_surface->buf.drm_buf, flags);
    762 
    763     if ((driver_data->output_method == PSB_PUTSURFACE_OVERLAY)
    764         && (driver_data->drawable_info & (XVDRAWABLE_ROTATE_180 | XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270))) {
    765         unsigned int rotate_width, rotate_height;
    766         int fourcc;
    767         if (output->sprite_enabled)
    768             fourcc = VA_FOURCC_RGBA;
    769         else
    770             fourcc = VA_FOURCC_NV12;
    771         if (driver_data->drawable_info & (XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270)) {
    772             rotate_width = obj_surface->height;
    773             rotate_height = obj_surface->width;
    774         } else {
    775             rotate_width = obj_surface->width;
    776             rotate_height = obj_surface->height;
    777         }
    778         unsigned int protected = vaPtr->src_srf.pl_flags & 0;
    779 
    780         vaStatus = psb_check_rotatesurface(ctx, rotate_width, rotate_height, protected, fourcc);
    781         if (VA_STATUS_SUCCESS != vaStatus)
    782             return vaStatus;
    783 
    784         psb_surface_init(driver_data, &vaPtr->dst_srf, fourcc, 4,
    785                          rotate_width, rotate_height,
    786                          output->rotate_surface->stride, output->rotate_surface->size,
    787                          output->rotate_surface->buf.buffer_ofs, /* for surface created from RAR/camera device memory
    788                                                           * all surfaces share one BO but with different offset
    789                                                           * pass the offset as the "pre_add"
    790                                                           */
    791                          output->rotate_surface->buf.drm_buf, 0);
    792     }
    793     subpic_surface = obj_surface->subpictures;
    794     while (subpic_surface) {
    795         PsbVASurfaceRec *tmp = &vaPtr->subpic_srf[i++];
    796 
    797         memcpy(tmp, subpic_surface, sizeof(*tmp));
    798 
    799         /* reload palette for paletted subpicture
    800          * palete_ptr point to image palette
    801          */
    802         if (subpic_surface->palette_ptr)
    803             memcpy(&tmp->palette[0], subpic_surface->palette_ptr, 16 * sizeof(PsbAYUVSample8));
    804 
    805         subpic_surface = subpic_surface->next;
    806     }
    807 
    808     if (output->ignore_dpm == 0)
    809         psb_force_dpms_on(ctx);
    810 
    811     XvPutImage((Display *)ctx->native_dpy, portID, draw, output->gc, xvImage,
    812                srcx, srcy, srcw, srch, destx, desty, destw, desth);
    813     XFlush((Display *)ctx->native_dpy);
    814     //XSync((Display *)ctx->native_dpy, False);
    815 
    816     if (portID == output->overlay_portID) {
    817         if (driver_data->cur_displaying_surface != VA_INVALID_SURFACE)
    818             driver_data->last_displaying_surface = driver_data->cur_displaying_surface;
    819         obj_surface->display_timestamp = GetTickCount();
    820         driver_data->cur_displaying_surface = surface;
    821     } else {
    822         driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
    823         driver_data->last_displaying_surface = VA_INVALID_SURFACE;
    824         obj_surface->display_timestamp = 0;
    825     }
    826 
    827 
    828     return vaStatus;
    829 }
    830 
    831