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  *    Jason Hu  <jason.hu (at) intel.com>
     26  *    Zhaohan Ren  <zhaohan.ren (at) intel.com>
     27  *    Shengquan Yuan  <shengquan.yuan (at) intel.com>
     28  *
     29  */
     30 
     31 #include <X11/Xutil.h>
     32 #include <X11/extensions/Xrandr.h>
     33 #include <va/va_backend.h>
     34 #include "psb_output.h"
     35 #include "psb_surface.h"
     36 #include "psb_buffer.h"
     37 #include "psb_x11.h"
     38 #include "psb_drv_debug.h"
     39 
     40 #include <stdio.h>
     41 #include <string.h>
     42 #include <stdarg.h>
     43 #include "psb_surface_ext.h"
     44 #include <wsbm/wsbm_manager.h>
     45 #include "psb_drv_video.h"
     46 #include "psb_xrandr.h"
     47 #include <sys/types.h>
     48 
     49 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
     50 #define INIT_OUTPUT_PRIV    psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
     51 #define SURFACE(id)     ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
     52 
     53 static int
     54 psb_x11_getWindowCoordinate(Display * display,
     55                             Window x11_window_id,
     56                             psb_x11_win_t * psX11Window,
     57                             int * pbIsVisible)
     58 {
     59     Window DummyWindow;
     60     Status status;
     61     XWindowAttributes sXWinAttrib;
     62 
     63     if ((status = XGetWindowAttributes(display,
     64                                        x11_window_id,
     65                                        &sXWinAttrib)) == 0) {
     66         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get X11 window coordinates - error %lu\n", __func__, (unsigned long)status);
     67         return -1;
     68     }
     69 
     70     psX11Window->i32Left = sXWinAttrib.x;
     71     psX11Window->i32Top = sXWinAttrib.y;
     72     psX11Window->ui32Width = sXWinAttrib.width;
     73     psX11Window->ui32Height = sXWinAttrib.height;
     74     *pbIsVisible = (sXWinAttrib.map_state == IsViewable);
     75 
     76     if (!*pbIsVisible)
     77         return 0;
     78 
     79     if (XTranslateCoordinates(display,
     80                               x11_window_id,
     81                               DefaultRootWindow(display),
     82                               0,
     83                               0,
     84                               &psX11Window->i32Left,
     85                               &psX11Window->i32Top,
     86                               &DummyWindow) == 0) {
     87         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to tranlate X coordinates - error %lu\n", __func__, (unsigned long)status);
     88         return -1;
     89     }
     90 
     91     psX11Window->i32Right  = psX11Window->i32Left + psX11Window->ui32Width - 1;
     92     psX11Window->i32Bottom = psX11Window->i32Top + psX11Window->ui32Height - 1;
     93 
     94     return 0;
     95 }
     96 static psb_x11_clip_list_t *
     97 psb_x11_createClipBoxNode(psb_x11_win_t *       pRect,
     98                           psb_x11_clip_list_t * pClipNext)
     99 {
    100     psb_x11_clip_list_t * pCurrent = NULL;
    101 
    102     pCurrent = (psb_x11_clip_list_t *)calloc(1, sizeof(psb_x11_clip_list_t));
    103     if (pCurrent) {
    104         pCurrent->rect = *pRect;
    105         pCurrent->next = pClipNext;
    106 
    107         return pCurrent;
    108     } else
    109         return pClipNext;
    110 }
    111 
    112 void
    113 psb_x11_freeWindowClipBoxList(psb_x11_clip_list_t * pHead)
    114 {
    115     psb_x11_clip_list_t * pNext = NULL;
    116 
    117     while (pHead) {
    118         pNext = pHead->next;
    119         free(pHead);
    120         pHead = pNext;
    121     }
    122 }
    123 
    124 #define IS_BETWEEN_RANGE(a,b,c) ((a<=b)&&(b<=c))
    125 
    126 static psb_x11_clip_list_t *
    127 psb_x11_substractRects(Display *             display,
    128                        psb_x11_clip_list_t * psRegion,
    129                        psb_x11_win_t *       psRect)
    130 {
    131     psb_x11_clip_list_t * psCur, * psPrev, * psFirst, * psNext;
    132     psb_x11_win_t sCreateRect;
    133     int display_width  = (int)(DisplayWidth(display, DefaultScreen(display))) - 1;
    134     int display_height = (int)(DisplayHeight(display, DefaultScreen(display))) - 1;
    135 
    136     psFirst = psb_x11_createClipBoxNode(psRect, NULL);
    137 
    138     if (psFirst->rect.i32Left < 0)
    139         psFirst->rect.i32Left = 0;
    140     else if (psFirst->rect.i32Left > display_width)
    141         psFirst->rect.i32Left = display_width;
    142 
    143     if (psFirst->rect.i32Right < 0)
    144         psFirst->rect.i32Right = 0;
    145     else if (psFirst->rect.i32Right > display_width)
    146         psFirst->rect.i32Right = display_width;
    147 
    148     if (psFirst->rect.i32Top < 0)
    149         psFirst->rect.i32Top = 0;
    150     else if (psFirst->rect.i32Top > display_height)
    151         psFirst->rect.i32Top = display_height;
    152 
    153     if (psFirst->rect.i32Bottom < 0)
    154         psFirst->rect.i32Bottom = 0;
    155     else if (psFirst->rect.i32Bottom > display_height)
    156         psFirst->rect.i32Bottom = display_height;
    157 
    158     while (psRegion) {
    159         psCur  = psFirst;
    160         psPrev = NULL;
    161 
    162         while (psCur) {
    163             psNext = psCur->next;
    164 
    165             if ((psRegion->rect.i32Left > psCur->rect.i32Left) &&
    166                 (psRegion->rect.i32Left <= psCur->rect.i32Right)) {
    167                 sCreateRect.i32Right = psRegion->rect.i32Left - 1;
    168 
    169                 sCreateRect.i32Left = psCur->rect.i32Left;
    170                 sCreateRect.i32Top = psCur->rect.i32Top;
    171                 sCreateRect.i32Bottom = psCur->rect.i32Bottom;
    172 
    173                 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
    174 
    175                 if (!psPrev)
    176                     psPrev = psFirst;
    177 
    178                 psCur->rect.i32Left = psRegion->rect.i32Left;
    179             }
    180 
    181             if ((psRegion->rect.i32Right >= psCur->rect.i32Left) &&
    182                 (psRegion->rect.i32Right < psCur->rect.i32Right))
    183 
    184             {
    185                 sCreateRect.i32Left = psRegion->rect.i32Right + 1;
    186 
    187                 sCreateRect.i32Right = psCur->rect.i32Right;
    188                 sCreateRect.i32Top = psCur->rect.i32Top;
    189                 sCreateRect.i32Bottom = psCur->rect.i32Bottom;
    190 
    191                 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
    192 
    193                 if (!psPrev)
    194                     psPrev = psFirst;
    195 
    196                 psCur->rect.i32Right = psRegion->rect.i32Right;
    197             }
    198 
    199             if ((psRegion->rect.i32Top > psCur->rect.i32Top) &&
    200                 (psRegion->rect.i32Top <= psCur->rect.i32Bottom)) {
    201                 sCreateRect.i32Bottom = psRegion->rect.i32Top - 1;
    202 
    203                 sCreateRect.i32Left   = psCur->rect.i32Left;
    204                 sCreateRect.i32Right  = psCur->rect.i32Right;
    205                 sCreateRect.i32Top    = psCur->rect.i32Top;
    206 
    207                 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
    208 
    209                 if (!psPrev)
    210                     psPrev = psFirst;
    211 
    212                 psCur->rect.i32Top = psRegion->rect.i32Top;
    213             }
    214 
    215             if ((psRegion->rect.i32Bottom >= psCur->rect.i32Top) &&
    216                 (psRegion->rect.i32Bottom <  psCur->rect.i32Bottom)) {
    217                 sCreateRect.i32Top    = psRegion->rect.i32Bottom + 1;
    218                 sCreateRect.i32Left   = psCur->rect.i32Left;
    219                 sCreateRect.i32Right  = psCur->rect.i32Right;
    220                 sCreateRect.i32Bottom = psCur->rect.i32Bottom;
    221 
    222                 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst);
    223 
    224                 if (!psPrev)
    225                     psPrev = psFirst;
    226 
    227                 psCur->rect.i32Bottom = psRegion->rect.i32Bottom;
    228             }
    229 
    230             if ((IS_BETWEEN_RANGE(psRegion->rect.i32Left, psCur->rect.i32Left,   psRegion->rect.i32Right)) &&
    231                 (IS_BETWEEN_RANGE(psRegion->rect.i32Left, psCur->rect.i32Right,  psRegion->rect.i32Right)) &&
    232                 (IS_BETWEEN_RANGE(psRegion->rect.i32Top,  psCur->rect.i32Top,    psRegion->rect.i32Bottom)) &&
    233                 (IS_BETWEEN_RANGE(psRegion->rect.i32Top,  psCur->rect.i32Bottom, psRegion->rect.i32Bottom))) {
    234                 if (psPrev) {
    235                     psPrev->next = psCur->next;
    236                     free(psCur);
    237                     psCur = psPrev;
    238                 } else {
    239                     free(psCur);
    240                     psCur = NULL;
    241                     psFirst = psNext;
    242                 }
    243             }
    244             psPrev = psCur;
    245             psCur  = psNext;
    246         }//while(psCur)
    247         psRegion = psRegion->next;
    248     }//while(psRegion)
    249 
    250     return psFirst;
    251 }
    252 
    253 static int
    254 psb_x11_createWindowClipBoxList(Display *              display,
    255                                 Window                 x11_window_id,
    256                                 psb_x11_clip_list_t ** ppWindowClipBoxList,
    257                                 unsigned int *         pui32NumClipBoxList)
    258 {
    259     Window CurrentWindow = x11_window_id;
    260     Window RootWindow, ParentWindow, ChildWindow;
    261     Window * pChildWindow;
    262     Status XResult;
    263     unsigned int i32NumChildren, i;
    264     int bIsVisible;
    265     unsigned int ui32NumRects = 0;
    266     psb_x11_clip_list_t *psRegions = NULL;
    267     psb_x11_win_t sRect;
    268 
    269     if (!display || (!ppWindowClipBoxList) || (!pui32NumClipBoxList))
    270         return -1;
    271 
    272     XResult = XQueryTree(display,
    273                          CurrentWindow,
    274                          &RootWindow,
    275                          &ParentWindow,
    276                          &pChildWindow,
    277                          &i32NumChildren);
    278     if (XResult == 0)
    279         return -2;
    280 
    281     if (i32NumChildren) {
    282         for (i = 0; i < i32NumChildren; i++) {
    283 
    284             psb_x11_getWindowCoordinate(display, x11_window_id, &sRect, &bIsVisible);
    285             if (bIsVisible) {
    286                 psRegions = psb_x11_createClipBoxNode(&sRect, psRegions);
    287                 ui32NumRects++;
    288             }
    289         }
    290         XFree(pChildWindow);
    291         i32NumChildren = 0;
    292     }
    293 
    294     while (CurrentWindow != RootWindow) {
    295         ChildWindow   = CurrentWindow;
    296         CurrentWindow = ParentWindow;
    297 
    298         XResult = XQueryTree(display,
    299                              CurrentWindow,
    300                              &RootWindow,
    301                              &ParentWindow,
    302                              &pChildWindow,
    303                              &i32NumChildren);
    304         if (XResult == 0) {
    305             if (i32NumChildren)
    306                 XFree(pChildWindow);
    307 
    308             psb_x11_freeWindowClipBoxList(psRegions);
    309             return -3;
    310         }
    311 
    312         if (i32NumChildren) {
    313             unsigned int iStartWindow = 0;
    314 
    315             for (i = 0; i < i32NumChildren; i++) {
    316                 if (pChildWindow[i] == ChildWindow) {
    317                     iStartWindow = i;
    318                     break;
    319                 }
    320             }
    321 
    322             if (i == i32NumChildren) {
    323                 XFree(pChildWindow);
    324                 psb_x11_freeWindowClipBoxList(psRegions);
    325                 return -4;
    326             }
    327 
    328             for (i = iStartWindow + 1; i < i32NumChildren; i++) {
    329                 psb_x11_getWindowCoordinate(display, pChildWindow[i], &sRect, &bIsVisible);
    330                 if (bIsVisible) {
    331                     psRegions = psb_x11_createClipBoxNode(&sRect, psRegions);
    332                     ui32NumRects++;
    333                 }
    334             }
    335 
    336             XFree(pChildWindow);
    337         }
    338     }
    339 
    340     ui32NumRects = 0;
    341 
    342     if (psRegions) {
    343         psb_x11_getWindowCoordinate(display, x11_window_id, &sRect, &bIsVisible);
    344         *ppWindowClipBoxList = psb_x11_substractRects(display, psRegions, &sRect);
    345         psb_x11_freeWindowClipBoxList(psRegions);
    346 
    347         psRegions = *ppWindowClipBoxList;
    348 
    349         while (psRegions) {
    350             ui32NumRects++;
    351             psRegions = psRegions->next;
    352         }
    353     } else {
    354         *ppWindowClipBoxList = psb_x11_substractRects(display, NULL, &sRect);
    355         ui32NumRects = 1;
    356     }
    357 
    358     *pui32NumClipBoxList = ui32NumRects;
    359 
    360     return 0;
    361 }
    362 
    363 static int psb_cleardrawable_stopoverlay(
    364     VADriverContextP ctx,
    365     Drawable draw, /* X Drawable */
    366     short destx,
    367     short desty,
    368     unsigned short destw,
    369     unsigned short desth
    370 )
    371 {
    372     INIT_DRIVER_DATA;
    373     INIT_OUTPUT_PRIV;
    374 
    375     XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, destx, desty, destw, desth);
    376     XSync((Display *)ctx->native_dpy, False);
    377 
    378     driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
    379     driver_data->last_displaying_surface = VA_INVALID_SURFACE;
    380 
    381     return 0;
    382 }
    383 
    384 static VAStatus psb_DisplayRGBASubpicture(
    385     PsbVASurfaceRec *subpicture,
    386     VADriverContextP ctx,
    387     int win_width,
    388     int win_height,
    389     int surface_x,
    390     int surface_y,
    391     int surface_w,
    392     int surface_h,
    393     psb_extvideo_subtitle subtitle
    394 )
    395 {
    396     INIT_DRIVER_DATA;
    397     INIT_OUTPUT_PRIV;
    398     XImage *ximg = NULL;
    399     Visual *visual;
    400     PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
    401     struct _WsbmBufferObject *bo = subpicture->bo;
    402     int image_width, image_height, width, height, size;
    403     int srcx, srcy, srcw, srch;
    404     int destx, desty, destw, desth;
    405     int depth, i;
    406 
    407     if (subpicture->fourcc != VA_FOURCC_RGBA) {
    408         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid image format, ONLY support RGBA subpicture now.\n", __func__);
    409         return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
    410     }
    411 
    412     for (i = 0; subpicture != NULL; subpicture = subpicture->next, i++) {
    413         srcx = subpicture->subpic_srcx;
    414         srcy = subpicture->subpic_srcy;
    415         srcw = subpicture->subpic_srcw;
    416         srch = subpicture->subpic_srch;
    417 
    418         destx = subpicture->subpic_dstx + surface_x;
    419         desty = subpicture->subpic_dsty + surface_y;
    420         destw = subpicture->subpic_dstw;
    421         desth = subpicture->subpic_dsth;
    422 
    423         image_width = subpicture->width;
    424         image_height = subpicture->height;
    425         size = subpicture->size;
    426 
    427         //clip in image region
    428         if (srcx < 0) {
    429             srcw += srcx;
    430             srcx = 0;
    431         }
    432 
    433         if (srcy < 0) {
    434             srch += srcy;
    435             srcy = 0;
    436         }
    437 
    438         if ((srcx + srcw) > image_width)
    439             srcw = image_width - srcx;
    440         if ((srcy + srch) > image_height)
    441             srch = image_height - srcy;
    442 
    443         //clip in drawable region
    444         if (destx < 0) {
    445             destw += destx;
    446             destx = 0;
    447         }
    448 
    449         if (desty < 0) {
    450             desth += desty;
    451             desty = 0;
    452         }
    453 
    454         if ((destx + destw) > surface_w)
    455             destw = surface_w - destx;
    456         if ((desty + desth) > surface_h)
    457             desth = surface_h - desty;
    458 
    459         if (srcw <= destw)
    460             width = srcw;
    461         else
    462             width = destw;
    463 
    464         if (srch <= desth)
    465             height = srch;
    466         else
    467             height = desth;
    468 
    469         visual = DefaultVisual(ctx->native_dpy, 0);
    470         depth = DefaultDepth(ctx->native_dpy, 0);
    471 
    472         ximg = XCreateImage(ctx->native_dpy, visual, depth, ZPixmap, 0, NULL, image_width, image_height, 32, 0);
    473 
    474         if (NULL == ximg) {
    475             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: XCreateImage failed! at L%d\n", __func__, __LINE__);
    476             return VA_STATUS_ERROR_UNKNOWN;
    477         }
    478 
    479         ximg->data = wsbmBOMap(bo, WSBM_ACCESS_READ);
    480         if (NULL == ximg->data) {
    481             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to map to ximg->data.\n", __func__);
    482             return VA_STATUS_ERROR_ALLOCATION_FAILED;
    483         }
    484 
    485         pPriv->clear_key[i].subpic_dstx = destx;
    486         pPriv->clear_key[i].subpic_dsty = desty;
    487         pPriv->clear_key[i].subpic_dstw = destw;
    488         pPriv->clear_key[i].subpic_dsth = desth;
    489         if (psb_xrandr_extvideo_mode()) {
    490             /*It is a HACK: Adjust subtitle to proper position.*/
    491             float xScale, yScale;
    492 
    493             xScale = win_width * 1.0 / surface_w;
    494             yScale = win_height * 1.0 / surface_h;
    495             destx = subpicture->subpic_dstx * xScale;
    496             desty = subpicture->subpic_dsty * yScale;
    497         }
    498         XPutImage(ctx->native_dpy, output->output_drawable, output->gc, ximg, srcx, srcy, destx, desty, width, height);
    499         XSync((Display *)ctx->native_dpy, False);
    500 
    501         if (psb_xrandr_extvideo_mode() &&
    502             (subtitle == ONLY_HDMI || subtitle == BOTH)) {
    503             float xScale, yScale;
    504 
    505             xScale = pPriv->extend_display_width * 1.0 / surface_w;
    506             yScale = pPriv->extend_display_height * 1.0 / surface_h;
    507 
    508             destx = subpicture->subpic_dstx * xScale;
    509             desty = subpicture->subpic_dsty * yScale;
    510 
    511             XPutImage(ctx->native_dpy, output->extend_drawable, output->extend_gc, ximg,
    512                       srcx, srcy, destx, desty, destw, desth);
    513             XSync((Display *)ctx->native_dpy, False);
    514         }
    515 
    516         pPriv->subpic_clear_flag = 0;
    517         ximg->data = NULL;
    518         wsbmBOUnmap(bo);
    519         if (NULL != ximg)
    520             XDestroyImage(ximg);
    521     }
    522     return VA_STATUS_SUCCESS;
    523 }
    524 
    525 static VAStatus psb_repaint_colorkey(
    526     VADriverContextP ctx,
    527     Drawable draw, /* X Drawable */
    528     VASurfaceID surface,
    529     int x11_window_width,
    530     int x11_window_height
    531 )
    532 {
    533     INIT_DRIVER_DATA;
    534     INIT_OUTPUT_PRIV;
    535     int i, ret;
    536     psb_x11_clip_list_t *pClipNext = NULL;
    537     VARectangle *pVaWindowClipRects = NULL;
    538     object_surface_p obj_surface = SURFACE(surface);
    539     PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
    540 
    541     if (output->frame_count % 500 == 0 || driver_data->xrandr_update) {
    542         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Repaint color key.\n");
    543         if (output->pClipBoxList)
    544             psb_x11_freeWindowClipBoxList(output->pClipBoxList);
    545         /* get window clipbox */
    546         ret = psb_x11_createWindowClipBoxList(ctx->native_dpy, draw, &output->pClipBoxList, &output->ui32NumClipBoxList);
    547         if (ret != 0) {
    548             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: get window clip boxes error # %d\n", __func__, ret);
    549             return VA_STATUS_ERROR_UNKNOWN;
    550         }
    551         if (output->frame_count == 500)
    552             output->frame_count = 0;
    553 
    554         driver_data->xrandr_update = 0;
    555     }
    556 
    557     pVaWindowClipRects = (VARectangle *)calloc(1, sizeof(VARectangle) * output->ui32NumClipBoxList);
    558     if (!pVaWindowClipRects) {
    559         psb_x11_freeWindowClipBoxList(output->pClipBoxList);
    560         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    561     }
    562 
    563     memset(pVaWindowClipRects, 0, sizeof(VARectangle)*output->ui32NumClipBoxList);
    564     pClipNext = output->pClipBoxList;
    565 #ifdef CLIP_DEBUG
    566     drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Total %d clip boxes\n", __func__, output->ui32NumClipBoxList);
    567 #endif
    568     for (i = 0; i < output->ui32NumClipBoxList; i++) {
    569         pVaWindowClipRects[i].x      = pClipNext->rect.i32Left;
    570         pVaWindowClipRects[i].y      = pClipNext->rect.i32Top;
    571         pVaWindowClipRects[i].width  = pClipNext->rect.i32Right - pClipNext->rect.i32Left;
    572         pVaWindowClipRects[i].height = pClipNext->rect.i32Bottom - pClipNext->rect.i32Top;
    573 #ifdef CLIP_DEBUG
    574         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: clip boxes Left Top (%d, %d) Right Bottom (%d, %d) width %d height %d\n", __func__,
    575                            pClipNext->rect.i32Left, pClipNext->rect.i32Top,
    576                            pClipNext->rect.i32Right, pClipNext->rect.i32Bottom,
    577                            pVaWindowClipRects[i].width, pVaWindowClipRects[i].height);
    578 #endif
    579         pClipNext = pClipNext->next;
    580     }
    581 
    582     /* repaint the color key when window size changed*/
    583     if (!obj_surface->subpictures &&
    584         ((pPriv->x11_window_width != x11_window_width) ||
    585          (pPriv->x11_window_height != x11_window_height))) {
    586         pPriv->x11_window_width = x11_window_width;
    587         pPriv->x11_window_height = x11_window_height;
    588         XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
    589         XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
    590         XSync((Display *)ctx->native_dpy, False);
    591     }
    592 
    593 
    594     if ((!obj_surface->subpictures) &&
    595         ((output->ui32NumClipBoxList != pPriv->last_num_clipbox) ||
    596          (memcmp(&pVaWindowClipRects[0], &(pPriv->last_clipbox[0]), (output->ui32NumClipBoxList > 16 ? 16 : output->ui32NumClipBoxList)*sizeof(VARectangle)) != 0))) {
    597         pPriv->last_num_clipbox = output->ui32NumClipBoxList;
    598         memcpy(&pPriv->last_clipbox[0], &pVaWindowClipRects[0], (output->ui32NumClipBoxList > 16 ? 16 : output->ui32NumClipBoxList)*sizeof(VARectangle));
    599         XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
    600         XSync((Display *)ctx->native_dpy, False);
    601     }
    602 
    603     free(pVaWindowClipRects);
    604 
    605     return VA_STATUS_SUCCESS;
    606 }
    607 
    608 static VAStatus psb_extendMode_getCoordinate(
    609     PsbPortPrivPtr pPriv,
    610     psb_xrandr_location extend_location,
    611     short destx,
    612     short desty,
    613     short srcx,
    614     short srcy,
    615     float xScaleFactor,
    616     float yScaleFactor,
    617     int *x11_window_width,
    618     int *x11_window_height,
    619     psb_overlay_rect_p local_rect,
    620     psb_overlay_rect_p extend_rect,
    621     enum overlay_id_t *extend_overlay
    622 )
    623 {
    624     switch (extend_location) {
    625     case LEFT_OF:
    626         if ((destx + *x11_window_width) > (pPriv->display_width + pPriv->extend_display_width)) {
    627             *x11_window_width = pPriv->display_width + pPriv->extend_display_width - destx;
    628         }
    629         if (((desty + *x11_window_height) < pPriv->display_height) &&
    630             ((desty + *x11_window_height) < pPriv->extend_display_height))
    631             local_rect->dHeight = extend_rect->dHeight = *x11_window_height;
    632         else if (pPriv->display_height < pPriv->extend_display_height) {
    633             local_rect->dHeight = pPriv->display_height - desty;
    634             if ((desty + *x11_window_height) > pPriv->extend_display_height)
    635                 extend_rect->dHeight = *x11_window_height = pPriv->extend_display_height - desty;
    636             else
    637                 extend_rect->dHeight = *x11_window_height;
    638         } else {
    639             extend_rect->dHeight = pPriv->extend_display_height - desty;
    640             if ((desty + *x11_window_height) > pPriv->display_height)
    641                 local_rect->dHeight = *x11_window_height = pPriv->display_height - desty;
    642             else
    643                 local_rect->dHeight = *x11_window_height;
    644         }
    645 
    646         if ((destx < pPriv->extend_display_width) && ((destx + *x11_window_width) < pPriv->extend_display_width)) {
    647             local_rect->dWidth = 0;
    648             extend_rect->dWidth = *x11_window_width;
    649             *extend_overlay = OVERLAY_A;
    650             local_rect->destx = 0;
    651         } else if ((destx < pPriv->extend_display_width) && ((destx + *x11_window_width) >= pPriv->extend_display_width)) {
    652             extend_rect->dWidth = pPriv->extend_display_width - destx;
    653             local_rect->dWidth = *x11_window_width - extend_rect->dWidth;
    654             local_rect->destx = 0;
    655         } else {
    656             local_rect->dWidth = *x11_window_width;
    657             extend_rect->dWidth = 0;
    658             local_rect->destx = destx - pPriv->extend_display_width;
    659         }
    660         local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
    661         local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
    662         extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
    663         extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
    664 
    665         local_rect->srcx = srcx + extend_rect->sWidth;
    666         extend_rect->srcx = srcx;
    667         local_rect->srcy = extend_rect->srcy = srcy;
    668 
    669         extend_rect->destx = destx;
    670         local_rect->desty = extend_rect->desty = desty;
    671         break;
    672     case RIGHT_OF:
    673         if ((destx + *x11_window_width) > (pPriv->display_width + pPriv->extend_display_width)) {
    674             *x11_window_width = pPriv->display_width + pPriv->extend_display_width - destx;
    675         }
    676         if (((desty + *x11_window_height) < pPriv->display_height) &&
    677             ((desty + *x11_window_height) < pPriv->extend_display_height))
    678             local_rect->dHeight = extend_rect->dHeight = *x11_window_height;
    679         else if (pPriv->display_height < pPriv->extend_display_height) {
    680             local_rect->dHeight = pPriv->display_height - desty;
    681             if ((desty + *x11_window_height) > pPriv->extend_display_height)
    682                 extend_rect->dHeight = *x11_window_height = pPriv->extend_display_height - desty;
    683             else
    684                 extend_rect->dHeight = *x11_window_height;
    685         } else {
    686             extend_rect->dHeight = pPriv->extend_display_height - desty;
    687             if ((desty + *x11_window_height) > pPriv->display_height)
    688                 local_rect->dHeight = *x11_window_height = pPriv->display_height - desty;
    689             else
    690                 local_rect->dHeight = *x11_window_height;
    691         }
    692 
    693         if ((destx < pPriv->display_width) && ((destx + *x11_window_width) < pPriv->display_width)) {
    694             local_rect->dWidth = *x11_window_width;
    695             extend_rect->dWidth = 0;
    696             extend_rect->destx = 0;
    697         } else if ((destx < pPriv->display_width) && ((destx + *x11_window_width) >= pPriv->display_width)) {
    698             local_rect->dWidth = pPriv->display_width - destx;
    699             extend_rect->dWidth = *x11_window_width - local_rect->dWidth;
    700             extend_rect->destx = 0;
    701         } else {
    702             local_rect->dWidth = 0;
    703             extend_rect->dWidth = *x11_window_width;
    704             *extend_overlay = OVERLAY_A;
    705             extend_rect->destx = destx - pPriv->display_width;
    706         }
    707         local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
    708         local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
    709         extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
    710         extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
    711 
    712         local_rect->srcx = srcx;
    713         extend_rect->srcx = srcx + local_rect->sWidth;
    714         local_rect->srcy = extend_rect->srcy = srcy;
    715 
    716         local_rect->destx = destx;
    717         local_rect->desty = extend_rect->desty = desty;
    718         break;
    719     case ABOVE:
    720         if (((destx + *x11_window_width) < pPriv->display_width) &&
    721             ((destx + *x11_window_width) < pPriv->extend_display_width))
    722             local_rect->dWidth = extend_rect->dWidth = *x11_window_width;
    723         else if (pPriv->display_width < pPriv->extend_display_width) {
    724             local_rect->dWidth = pPriv->display_width - destx;
    725             if ((destx + *x11_window_width) > pPriv->extend_display_width)
    726                 extend_rect->dWidth = *x11_window_width = pPriv->extend_display_width - destx;
    727             else
    728                 extend_rect->dWidth = *x11_window_width;
    729         } else {
    730             extend_rect->dWidth = pPriv->extend_display_width - destx;
    731             if ((destx + *x11_window_width) > pPriv->display_width)
    732                 local_rect->dWidth = *x11_window_width = pPriv->display_width - destx;
    733             else
    734                 local_rect->dWidth = *x11_window_width;
    735         }
    736 
    737         if ((desty + *x11_window_height) > (pPriv->display_height + pPriv->extend_display_height)) {
    738             *x11_window_height = pPriv->display_height + pPriv->extend_display_height - desty;
    739         }
    740 
    741         if ((desty < pPriv->extend_display_height) && ((desty + *x11_window_height) < pPriv->extend_display_height)) {
    742             local_rect->dHeight = 0;
    743             extend_rect->dHeight = *x11_window_height;
    744             *extend_overlay = OVERLAY_A;
    745             local_rect->desty = 0;
    746         } else if ((desty < pPriv->extend_display_height) && ((desty + *x11_window_height) >= pPriv->extend_display_height)) {
    747             extend_rect->dHeight = pPriv->extend_display_height - desty;
    748             local_rect->dHeight = *x11_window_height - extend_rect->dHeight;
    749             local_rect->desty = 0;
    750         } else {
    751             local_rect->dHeight = *x11_window_height;
    752             extend_rect->dHeight = 0;
    753             local_rect->desty = desty - pPriv->extend_display_height;
    754         }
    755         local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
    756         local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
    757         extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
    758         extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
    759 
    760         local_rect->srcy = srcy + extend_rect->sHeight;
    761         extend_rect->srcy = srcy;
    762         local_rect->srcx = extend_rect->srcx = srcx;
    763 
    764         extend_rect->desty = desty;
    765         local_rect->destx = extend_rect->destx = destx;
    766         break;
    767     case BELOW:
    768         if (((destx + *x11_window_width) < pPriv->display_width) &&
    769             ((destx + *x11_window_width) < pPriv->extend_display_width))
    770             local_rect->dWidth = extend_rect->dWidth = *x11_window_width;
    771         else if (pPriv->display_width < pPriv->extend_display_width) {
    772             local_rect->dWidth = pPriv->display_width - destx;
    773             if ((destx + *x11_window_width) > pPriv->extend_display_width)
    774                 extend_rect->dWidth = *x11_window_width = pPriv->extend_display_width - destx;
    775             else
    776                 extend_rect->dWidth = *x11_window_width;
    777         } else {
    778             extend_rect->dWidth = pPriv->extend_display_width - destx;
    779             if ((destx + *x11_window_width) > pPriv->display_width)
    780                 local_rect->dWidth = *x11_window_width = pPriv->display_width - destx;
    781             else
    782                 local_rect->dWidth = *x11_window_width;
    783         }
    784 
    785         if ((desty + *x11_window_height) > (pPriv->display_height + pPriv->extend_display_height)) {
    786             *x11_window_height = pPriv->display_height + pPriv->extend_display_height - desty;
    787         }
    788 
    789         if ((desty < pPriv->display_height) && ((desty + *x11_window_height) < pPriv->display_height)) {
    790             local_rect->dHeight = *x11_window_height;
    791             extend_rect->dHeight = 0;
    792             extend_rect->desty = 0;
    793         } else if ((desty < pPriv->display_height) && ((desty + *x11_window_height) >= pPriv->display_height)) {
    794             local_rect->dHeight = pPriv->display_height - desty;
    795             extend_rect->dHeight = *x11_window_height - local_rect->dHeight;
    796             extend_rect->desty = 0;
    797         } else {
    798             local_rect->dHeight = 0;
    799             extend_rect->dHeight = *x11_window_height;
    800             *extend_overlay = OVERLAY_A;
    801             extend_rect->desty = desty - pPriv->display_height;
    802         }
    803         local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor);
    804         local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor);
    805         extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor);
    806         extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor);
    807 
    808         local_rect->srcy = srcy;
    809         extend_rect->srcy = srcy + local_rect->sHeight;
    810         local_rect->srcx = extend_rect->srcx = srcx;
    811 
    812         local_rect->desty = desty;
    813         local_rect->destx = extend_rect->destx = destx;
    814         break;
    815     case NORMAL:
    816     default:
    817         break;
    818     }
    819     return VA_STATUS_SUCCESS;
    820 }
    821 
    822 static void psb_init_subpicture(VADriverContextP ctx, PsbPortPrivPtr pPriv)
    823 {
    824     INIT_DRIVER_DATA;
    825     struct drm_psb_register_rw_arg regs;
    826     unsigned int subpicture_enable_mask = REGRWBITS_DSPACNTR;
    827 
    828     if (!pPriv->subpicture_enabled) {
    829         if (psb_xrandr_hdmi_enabled())
    830             subpicture_enable_mask |= REGRWBITS_DSPBCNTR;
    831         if (psb_xrandr_mipi1_enabled())
    832             subpicture_enable_mask |= REGRWBITS_DSPCCNTR;
    833 
    834         memset(&regs, 0, sizeof(regs));
    835         regs.subpicture_enable_mask = subpicture_enable_mask;
    836         pPriv->subpicture_enable_mask = subpicture_enable_mask;
    837         pPriv->subpicture_enabled = 1;
    838         drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, &regs, sizeof(regs));
    839     }
    840 }
    841 
    842 static void psb_clear_subpictures(
    843     VADriverContextP ctx,
    844     PsbPortPrivPtr pPriv,
    845     int win_width,
    846     int win_height,
    847     object_surface_p obj_surface
    848 )
    849 {
    850     INIT_OUTPUT_PRIV;
    851     PsbVASurfaceRec *subpicture = (PsbVASurfaceRec *)obj_surface->subpictures;
    852     int i;
    853 
    854     if (subpicture == NULL) {
    855         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Surface has no subpicture to render.\n");
    856         return;
    857     }
    858 
    859     for (i = 0; subpicture != NULL; subpicture = subpicture->next, i++) {
    860         if ((subpicture->subpic_dstx != pPriv->clear_key[i].subpic_dstx) ||
    861             (subpicture->subpic_dsty != pPriv->clear_key[i].subpic_dsty) ||
    862             (subpicture->subpic_dstw != pPriv->clear_key[i].subpic_dstw) ||
    863             (subpicture->subpic_dsth != pPriv->clear_key[i].subpic_dsth)) {
    864             XSetForeground((Display *)ctx->native_dpy, output->gc, 0);
    865             XFillRectangle((Display *)ctx->native_dpy, output->output_drawable, output->gc, 0, 0, win_width, win_height);
    866             XSync((Display *)ctx->native_dpy, False);
    867             if (psb_xrandr_extvideo_mode()) {
    868                 XSetForeground((Display *)ctx->native_dpy, output->extend_gc, 0);
    869                 XFillRectangle((Display *)ctx->native_dpy, output->extend_drawable, output->extend_gc,
    870                                0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
    871                 XSync((Display *)ctx->native_dpy, False);
    872             }
    873             pPriv->subpic_clear_flag = 1;
    874         }
    875     }
    876     return;
    877 }
    878 
    879 VAStatus psb_putsurface_coverlay(
    880     VADriverContextP ctx,
    881     VASurfaceID surface,
    882     Drawable draw, /* X Drawable */
    883     short srcx,
    884     short srcy,
    885     unsigned short srcw,
    886     unsigned short srch,
    887     short destx,
    888     short desty,
    889     unsigned short destw,
    890     unsigned short desth,
    891     VARectangle *cliprects, /* client supplied clip list */
    892     unsigned int number_cliprects, /* number of clip rects in the clip list */
    893     unsigned int flags /* de-interlacing flags */
    894 )
    895 {
    896     INIT_DRIVER_DATA;
    897     INIT_OUTPUT_PRIV;
    898     int ret;
    899     int x11_window_width = destw, x11_window_height = desth;
    900     psb_xrandr_location extend_location;
    901     object_surface_p obj_surface = SURFACE(surface);
    902     PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
    903     int primary_crtc_x, primary_crtc_y, extend_crtc_x, extend_crtc_y;
    904     enum pipe_id_t local_pipe = PIPEA, extend_pipe = PIPEB;
    905     int surfacex = destx, surfacey = desty;
    906     float xScaleFactor, yScaleFactor;
    907     Rotation rotation = RR_Rotate_0;
    908     psb_output_device local_device, extend_device;
    909     psb_extvideo_subtitle subtitle;
    910 
    911     if (flags & VA_CLEAR_DRAWABLE) {
    912         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clean draw with color 0x%08x\n", driver_data->clear_color);
    913         psb_cleardrawable_stopoverlay(ctx, draw, destx, desty, destw, desth);
    914 
    915         return VA_STATUS_SUCCESS;
    916     }
    917 
    918     if (output->frame_count % 500 == 0 || driver_data->xrandr_update) {
    919         /* get window screen coordination */
    920         ret = psb_x11_getWindowCoordinate(ctx->native_dpy, draw, &output->winRect, &output->bIsVisible);
    921         if (ret != 0) {
    922             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get X11 window coordinates error # %d\n", __func__, ret);
    923             return VA_STATUS_ERROR_UNKNOWN;
    924         }
    925     }
    926 
    927     if (!output->bIsVisible) {
    928         return VA_STATUS_SUCCESS;
    929     }
    930 
    931     if (NULL == obj_surface) {
    932         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid surface id 0x%08x.\n", __func__, surface);
    933         return VA_STATUS_ERROR_INVALID_SURFACE;
    934     }
    935 
    936     if (output->output_drawable != draw) {
    937         output->output_drawable = draw;
    938     }
    939 
    940     if (!output->gc) {
    941         output->gc = XCreateGC((Display *)ctx->native_dpy, draw, 0, NULL);
    942         /* paint the color key */
    943         if (!obj_surface->subpictures && !driver_data->overlay_auto_paint_color_key) {
    944             XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
    945             XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
    946             XSync((Display *)ctx->native_dpy, False);
    947         }
    948     }
    949 
    950     if (driver_data->use_xrandr_thread && !driver_data->xrandr_thread_id) {
    951         ret = psb_xrandr_thread_create(ctx);
    952         if (ret != 0) {
    953             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to create psb xrandr thread error # %d\n", __func__, ret);
    954             return VA_STATUS_ERROR_UNKNOWN;
    955         }
    956     }
    957 
    958     ret = psb_xrandr_local_crtc_coordinate(&local_device, &primary_crtc_x, &primary_crtc_y, &pPriv->display_width, &pPriv->display_height, &rotation);
    959     if (ret != VA_STATUS_SUCCESS) {
    960         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get primary crtc coordinates error # %d\n", __func__, ret);
    961         return VA_STATUS_ERROR_UNKNOWN;
    962     }
    963     switch (local_device) {
    964     case LVDS0:
    965     case MIPI0:
    966         local_pipe = PIPEA;
    967         break;
    968         /* single HDMI */
    969     case HDMI:
    970         local_pipe = PIPEB;
    971         break;
    972     case MIPI1:
    973         local_pipe = PIPEC;
    974         break;
    975     }
    976 
    977     if (!psb_xrandr_single_mode()) {
    978 
    979         ret = psb_xrandr_extend_crtc_coordinate(&extend_device, &extend_crtc_x, &extend_crtc_y,
    980                                                 &pPriv->extend_display_width, &pPriv->extend_display_height, &extend_location, &rotation);
    981         if (ret != VA_STATUS_SUCCESS) {
    982             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get extend crtc coordinates error # %d\n", __func__, ret);
    983             return VA_STATUS_ERROR_UNKNOWN;
    984         }
    985 
    986         switch (extend_device) {
    987         case HDMI:
    988             extend_pipe = PIPEB;
    989             break;
    990         case MIPI1:
    991             extend_pipe = PIPEC;
    992             break;
    993         default:
    994             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get extend pipe\n", __func__);
    995             break;
    996         }
    997     }
    998 
    999     /*clip in the window area*/
   1000     if (destx < 0) {
   1001         x11_window_width += destx;
   1002         destx = 0;
   1003     }
   1004 
   1005     if (desty < 0) {
   1006         x11_window_height += desty;
   1007         desty = 0;
   1008     }
   1009 
   1010     if (srcx < 0) {
   1011         srcw += srcx;
   1012         srcx = 0;
   1013     }
   1014 
   1015     if (srcy < 0) {
   1016         srch += srcy;
   1017         srcy = 0;
   1018     }
   1019 
   1020     if ((destx + x11_window_width) > output->winRect.ui32Width)
   1021         x11_window_width = output->winRect.ui32Width - destx;
   1022 
   1023     if ((desty + x11_window_height) > output->winRect.ui32Height)
   1024         x11_window_height = output->winRect.ui32Height - desty;
   1025 
   1026     /*translate destx, desty into screen coordinate*/
   1027     destx += output->winRect.i32Left;
   1028     desty += output->winRect.i32Top;
   1029 
   1030     /*clip in the screen area*/
   1031     xScaleFactor = srcw * 1.0 / x11_window_width;
   1032     yScaleFactor = srch * 1.0 / x11_window_height;
   1033 
   1034     if (destx < 0) {
   1035         x11_window_width += destx;
   1036         srcx = (short)((-destx) * xScaleFactor);
   1037         destx = 0;
   1038     }
   1039 
   1040     if (desty < 0) {
   1041         x11_window_height += desty;
   1042         srcy = (short)((-desty) * yScaleFactor);
   1043         desty = 0;
   1044     }
   1045 
   1046     /* display by overlay */
   1047     if (psb_xrandr_single_mode() || IS_MRST(driver_data)) {
   1048         if ((destx + x11_window_width) > pPriv->display_width) {
   1049             x11_window_width = pPriv->display_width - destx;
   1050             srcw = (unsigned short)(x11_window_width * xScaleFactor);
   1051         }
   1052 
   1053         if ((desty + x11_window_height) > pPriv->display_height) {
   1054             x11_window_height = pPriv->display_height - desty;
   1055             srch = (unsigned short)(x11_window_height * yScaleFactor);
   1056         }
   1057 
   1058         if (!driver_data->overlay_auto_paint_color_key) {
   1059             ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
   1060             if (ret != 0) {
   1061                 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
   1062                 return VA_STATUS_ERROR_UNKNOWN;
   1063             }
   1064         }
   1065 
   1066         psb_putsurface_overlay(
   1067             ctx, surface, srcx, srcy, srcw, srch,
   1068             /* screen coordinate */
   1069             destx, desty, x11_window_width, x11_window_height,
   1070             flags, OVERLAY_A, local_pipe);
   1071     } else if (psb_xrandr_clone_mode()) {
   1072         psb_overlay_rect_t local_rect, extend_rect;
   1073 
   1074         if (output->extend_drawable) {
   1075             XDestroyWindow(ctx->native_dpy, output->extend_drawable);
   1076             output->extend_drawable = 0;
   1077             XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
   1078             output->extend_gc = 0;
   1079         }
   1080 
   1081         if (((destx + x11_window_width) < pPriv->display_width) &&
   1082             ((destx + x11_window_width) < pPriv->extend_display_width))
   1083             local_rect.dWidth = extend_rect.dWidth = x11_window_width;
   1084         else if (pPriv->display_width < pPriv->extend_display_width) {
   1085             local_rect.dWidth = pPriv->display_width - destx;
   1086             if ((destx + x11_window_width) > pPriv->extend_display_width)
   1087                 extend_rect.dWidth = x11_window_width = pPriv->extend_display_width - destx;
   1088             else
   1089                 extend_rect.dWidth = x11_window_width;
   1090         } else {
   1091             extend_rect.dWidth = pPriv->extend_display_width - destx;
   1092             if ((destx + x11_window_width) > pPriv->display_width)
   1093                 local_rect.dWidth = x11_window_width = pPriv->display_width - destx;
   1094             else
   1095                 local_rect.dWidth = x11_window_width;
   1096         }
   1097 
   1098         if (((desty + x11_window_height) < pPriv->display_height) &&
   1099             ((desty + x11_window_height) < pPriv->extend_display_height))
   1100             local_rect.dHeight = extend_rect.dHeight = x11_window_height;
   1101         else if (pPriv->display_height < pPriv->extend_display_height) {
   1102             local_rect.dHeight = pPriv->display_height - desty;
   1103             if ((desty + x11_window_height) > pPriv->extend_display_height)
   1104                 extend_rect.dHeight = x11_window_height = pPriv->extend_display_height - desty;
   1105             else
   1106                 extend_rect.dHeight = x11_window_height;
   1107         } else {
   1108             extend_rect.dHeight = pPriv->extend_display_height - desty;
   1109             if ((desty + x11_window_height) > pPriv->display_height)
   1110                 local_rect.dHeight = x11_window_height = pPriv->display_height - desty;
   1111             else
   1112                 local_rect.dHeight = x11_window_height;
   1113         }
   1114         if ((driver_data->mipi0_rotation != VA_ROTATION_NONE) ||
   1115             (driver_data->hdmi_rotation != VA_ROTATION_NONE)) {
   1116             local_rect.sWidth = srcw;
   1117             local_rect.sHeight = srch;
   1118             extend_rect.sWidth = srcw;
   1119             extend_rect.sHeight = srch;
   1120         } else {
   1121             local_rect.sWidth = (unsigned short)(local_rect.dWidth * xScaleFactor);
   1122             local_rect.sHeight = (unsigned short)(local_rect.dHeight * yScaleFactor);
   1123             extend_rect.sWidth = (unsigned short)(extend_rect.dWidth * xScaleFactor);
   1124             extend_rect.sHeight = (unsigned short)(extend_rect.dHeight * yScaleFactor);
   1125         }
   1126         ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
   1127         if (ret != 0) {
   1128             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
   1129             return VA_STATUS_ERROR_UNKNOWN;
   1130         }
   1131         psb_putsurface_overlay(
   1132             ctx, surface, srcx, srcy, extend_rect.sWidth, extend_rect.sHeight,
   1133             /* screen coordinate */
   1134             destx, desty, extend_rect.dWidth, extend_rect.dHeight,
   1135             flags, OVERLAY_C, extend_pipe);
   1136         psb_putsurface_overlay(
   1137             ctx, surface,  srcx, srcy, local_rect.sWidth, local_rect.sHeight,
   1138             /* screen coordinate */
   1139             destx, desty, local_rect.dWidth, local_rect.dHeight,
   1140             flags, OVERLAY_A, local_pipe);
   1141     } else if (psb_xrandr_extend_mode()) {
   1142         if (driver_data->extend_fullscreen) {
   1143             switch (extend_location) {
   1144             case RIGHT_OF:
   1145                 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, pPriv->display_width, 0, pPriv->extend_display_width, pPriv->extend_display_height);
   1146                 break;
   1147             case BELOW:
   1148                 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, 0, pPriv->display_height, pPriv->extend_display_width, pPriv->extend_display_height);
   1149                 break;
   1150             case LEFT_OF:
   1151             case ABOVE:
   1152                 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, 0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
   1153                 break;
   1154             default:
   1155                 break;
   1156 
   1157             }
   1158             XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey);
   1159             XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, pPriv->extend_display_width, pPriv->extend_display_height);
   1160             XFlush(ctx->native_dpy);
   1161 
   1162             psb_putsurface_overlay(
   1163                 ctx, surface, srcx, srcy, srcw, srch,
   1164                 /* screen coordinate */
   1165                 0, 0, pPriv->extend_display_width, pPriv->extend_display_height,
   1166                 flags, OVERLAY_A, PIPEB);
   1167         } else {
   1168             psb_overlay_rect_t local_rect, extend_rect;
   1169             enum overlay_id_t extend_overlay = OVERLAY_C;
   1170 
   1171             if (output->extend_drawable) {
   1172                 XDestroyWindow(ctx->native_dpy, output->extend_drawable);
   1173                 output->extend_drawable = 0;
   1174                 XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
   1175                 output->extend_gc = 0;
   1176             }
   1177             memset(&local_rect, 0, sizeof(psb_overlay_rect_t));
   1178             memset(&extend_rect, 0, sizeof(psb_overlay_rect_t));
   1179             psb_extendMode_getCoordinate(pPriv, extend_location, destx, desty, srcx, srcy,
   1180                                          xScaleFactor, yScaleFactor, &x11_window_width, &x11_window_height,
   1181                                          &local_rect, &extend_rect, &extend_overlay);
   1182 
   1183             ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
   1184             if (ret != 0) {
   1185                 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
   1186                 return VA_STATUS_ERROR_UNKNOWN;
   1187             }
   1188 
   1189             if ((extend_rect.dWidth > 0) && (extend_rect.dHeight > 0)) {
   1190                 psb_putsurface_overlay(
   1191                     ctx, surface,
   1192                     extend_rect.srcx, extend_rect.srcy, extend_rect.sWidth, extend_rect.sHeight,
   1193                     extend_rect.destx, extend_rect.desty, extend_rect.dWidth, extend_rect.dHeight,
   1194                     flags, extend_overlay, extend_pipe);
   1195             }
   1196             if ((local_rect.dWidth > 0) && (local_rect.dHeight > 0)) {
   1197                 psb_putsurface_overlay(
   1198                     ctx, surface,
   1199                     local_rect.srcx, local_rect.srcy, local_rect.sWidth, local_rect.sHeight,
   1200                     local_rect.destx, local_rect.desty, local_rect.dWidth, local_rect.dHeight,
   1201                     flags, OVERLAY_A, local_pipe);
   1202             }
   1203         }
   1204     } else if (psb_xrandr_extvideo_mode()) {
   1205         unsigned int xres, yres, xoffset, yoffset, overscanmode, pannelfitting, x, y;
   1206         psb_extvideo_center center;
   1207 
   1208         psb_xrandr_extvideo_prop(&xres, &yres, &xoffset, &yoffset, &center, &subtitle, &overscanmode, &pannelfitting);
   1209         x = xoffset;
   1210         y = yoffset;
   1211 
   1212         switch (extend_location) {
   1213         case RIGHT_OF:
   1214             x += pPriv->display_width;
   1215             break;
   1216         case BELOW:
   1217             y += pPriv->display_height;
   1218             break;
   1219         case NORMAL:
   1220             break;
   1221         case LEFT_OF:
   1222             if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
   1223                 destx += pPriv->extend_display_width;
   1224                 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, destx, desty, x11_window_width, x11_window_height);
   1225                 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
   1226                 XFlush(ctx->native_dpy);
   1227             }
   1228             destx = destx - pPriv->extend_display_width;
   1229             break;
   1230         case ABOVE:
   1231             if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
   1232                 desty += pPriv->extend_display_height;
   1233                 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, destx, desty, x11_window_width, x11_window_height);
   1234                 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height);
   1235                 XFlush(ctx->native_dpy);
   1236             }
   1237             desty = desty - pPriv->extend_display_height;
   1238             break;
   1239         }
   1240         if ((destx + x11_window_width) > pPriv->display_width)
   1241             x11_window_width = pPriv->display_width - destx;
   1242         if ((desty + x11_window_height) > pPriv->display_height)
   1243             x11_window_height = pPriv->display_height - desty;
   1244 
   1245         if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) {
   1246             Window extend_win;
   1247             extend_win = psb_xrandr_create_full_screen_window(x, y, xres, yres);
   1248             if (output->extend_drawable != extend_win) {
   1249                 output->extend_drawable = extend_win;
   1250                 if (output->extend_gc)
   1251                     XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
   1252                 output->extend_gc = XCreateGC((Display *)ctx->native_dpy, extend_win, 0, NULL);
   1253 
   1254                 /* paint the color key */
   1255                 if (!obj_surface->subpictures) {
   1256                     XSetForeground((Display *)ctx->native_dpy, output->extend_gc, pPriv->colorKey);
   1257                     XFillRectangle((Display *)ctx->native_dpy, extend_win, output->extend_gc, 0, 0, xres, yres);
   1258                     XSync((Display *)ctx->native_dpy, False);
   1259                 }
   1260             }
   1261             driver_data->xrandr_dirty &= ~PSB_NEW_EXTVIDEO;
   1262         }
   1263 
   1264         ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height);
   1265         if (ret != 0) {
   1266             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret);
   1267             return VA_STATUS_ERROR_UNKNOWN;
   1268         }
   1269 
   1270         psb_putsurface_overlay(
   1271             ctx, surface, srcx, srcy, srcw, srch,
   1272             /* screen coordinate */
   1273             xoffset, yoffset, xres, yres,
   1274             flags, OVERLAY_C, PIPEB);
   1275         psb_putsurface_overlay(
   1276             ctx, surface, srcx, srcy, srcw, srch,
   1277             /* screen coordinate */
   1278             destx, desty,
   1279             x11_window_width, x11_window_height,
   1280             flags, OVERLAY_A, local_pipe);
   1281     }
   1282 
   1283     /*Init Overlay subpicuture blending and make proper clear.*/
   1284     if (pPriv->is_mfld && obj_surface->subpictures) {
   1285         PsbVASurfaceRec *subpicture = (PsbVASurfaceRec *)obj_surface->subpictures;
   1286 
   1287         psb_init_subpicture(ctx, pPriv);
   1288         /*clear changed subpicture zones in drawable.*/
   1289         psb_clear_subpictures(ctx, pPriv, x11_window_width, x11_window_height, obj_surface);
   1290         if (pPriv->subpic_clear_flag) {
   1291             psb_DisplayRGBASubpicture(subpicture, ctx, x11_window_width, x11_window_height,
   1292                                       surfacex, surfacey, obj_surface->width, obj_surface->height, subtitle);
   1293         }
   1294     }
   1295 
   1296     output->frame_count++;
   1297 
   1298     return VA_STATUS_SUCCESS;
   1299 }
   1300