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  *
     28  */
     29 
     30 #include <unistd.h>
     31 #include "psb_xrandr.h"
     32 #include "psb_x11.h"
     33 #include "psb_drv_debug.h"
     34 
     35 /* Global variable for xrandr */
     36 psb_xrandr_info_p psb_xrandr_info;
     37 
     38 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData
     39 #define INIT_OUTPUT_PRIV    psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
     40 
     41 #define MWM_HINTS_DECORATIONS (1L << 1)
     42 typedef struct {
     43     int flags;
     44     int functions;
     45     int decorations;
     46     int input_mode;
     47     int status;
     48 } MWMHints;
     49 
     50 char* location2string(psb_xrandr_location location)
     51 {
     52     switch (location) {
     53     case ABOVE:
     54         return "ABOVE";
     55         break;
     56     case BELOW:
     57         return "BELOW";
     58         break;
     59     case LEFT_OF:
     60         return "LEFT_OF";
     61         break;
     62     case RIGHT_OF:
     63         return "RIGHT_OF";
     64         break;
     65     default:
     66         return "NORMAL";
     67         break;
     68     }
     69 }
     70 
     71 static int RRrotation2VArotation(Rotation rotation)
     72 {
     73     switch (rotation) {
     74     case RR_Rotate_0:
     75         return VA_ROTATION_NONE;
     76     case RR_Rotate_90:
     77         return VA_ROTATION_270;
     78     case RR_Rotate_180:
     79         return VA_ROTATION_180;
     80     case RR_Rotate_270:
     81         return VA_ROTATION_90;
     82     }
     83 
     84     return 0;
     85 }
     86 static psb_xrandr_crtc_p get_crtc_by_id(RRCrtc crtc_id)
     87 {
     88     psb_xrandr_crtc_p p_crtc;
     89     for (p_crtc = psb_xrandr_info->crtc_head; p_crtc; p_crtc = p_crtc->next)
     90         if (p_crtc->crtc_id == crtc_id)
     91             return p_crtc;
     92     return NULL;
     93 }
     94 
     95 static void psb_xrandr_hdmi_property(VADriverContextP ctx)
     96 {
     97     INIT_DRIVER_DATA;
     98     Atom *props;
     99     Atom actual_type;
    100     XRRPropertyInfo *propinfo;
    101     int i, nprop, actual_format;
    102     unsigned long nitems, bytes_after;
    103     char* prop_name;
    104     unsigned char* prop;
    105 
    106     /* Check HDMI properties */
    107     props = XRRListOutputProperties(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, &nprop);
    108     if (!props) {
    109         drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: XRRListOutputProperties failed\n", psb_xrandr_info->extend_output->output_id);
    110         return;
    111     }
    112 
    113     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: extend output %08x has %d properties\n", psb_xrandr_info->extend_output->output_id, nprop);
    114 
    115     for (i = 0; i < nprop; i++) {
    116         XRRGetOutputProperty(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, props[i],
    117                              0, 100, False, False, AnyPropertyType, &actual_type, &actual_format,
    118                              &nitems, &bytes_after, &prop);
    119 
    120         propinfo = XRRQueryOutputProperty(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, props[i]);
    121         if (!propinfo) {
    122             drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: get output %08x prop %08x failed\n", psb_xrandr_info->extend_output->output_id, props[i]);
    123             return;
    124         }
    125 
    126         prop_name = XGetAtomName(psb_xrandr_info->dpy, props[i]);
    127 
    128         /* Currently all properties are XA_INTEGER, 32 */
    129         if (!strcmp(prop_name, "ExtVideoMode")) {
    130             psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode = (int)((INT32*)prop)[0];
    131             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode);
    132         } else if (!strcmp(prop_name, "ExtVideoMode_Xres")) {
    133             psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes = (int)((INT32*)prop)[0];
    134             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_XRes (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes);
    135         } else if (!strcmp(prop_name, "ExtVideoMode_Yres")) {
    136             psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes = (int)((INT32*)prop)[0];
    137             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_YRes (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes);
    138         } else if (!strcmp(prop_name, "ExtVideoMode_X_Offset")) {
    139             psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset = (int)((INT32*)prop)[0];
    140             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_X_Offset (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset);
    141         } else if (!strcmp(prop_name, "ExtVideoMode_Y_Offset")) {
    142             psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset = (int)((INT32*)prop)[0];
    143             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_Y_Offset (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset);
    144         } else if (!strcmp(prop_name, "ExtVideoMode_Center")) {
    145             psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center = (int)((INT32*)prop)[0];
    146             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_Center (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center);
    147         } else if (!strcmp(prop_name, "ExtVideoMode_SubTitle")) {
    148             psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle = (int)((INT32*)prop)[0];
    149             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_SubTitle (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle);
    150         } else if (!strcmp(prop_name, "ExtDesktopMode")) {
    151             if ((psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode != EXTENDEDVIDEO) &&
    152                 ((int)((INT32*)prop)[0] == EXTENDEDVIDEO)) {
    153                 driver_data->xrandr_dirty |= PSB_NEW_EXTVIDEO;
    154             }
    155             psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = (int)((INT32*)prop)[0];
    156             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtDesktopMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode);
    157         } else if (!strcmp(prop_name, "OverscanMode")) {
    158             psb_xrandr_info->hdmi_extvideo_prop->OverscanMode = (int)((INT32*)prop)[0];
    159             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: OverscanMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->OverscanMode);
    160         } else if (!strcmp(prop_name, "PANELFITTING")) {
    161             psb_xrandr_info->hdmi_extvideo_prop->PANELFITTING = (int)((INT32*)prop)[0];
    162             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: PANELFITTING (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->PANELFITTING);
    163         }
    164     }
    165 }
    166 
    167 static void psb_xrandr_mipi_location_init(psb_output_device_mode output_device_mode)
    168 {
    169     psb_xrandr_crtc_p local_crtc = NULL, extend_crtc = NULL;
    170 
    171     switch (output_device_mode) {
    172     case SINGLE_MIPI0:
    173         psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = SINGLE;
    174         psb_xrandr_info->local_crtc[0]->location = NORMAL;
    175         return;
    176     case SINGLE_MIPI1:
    177         psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = SINGLE;
    178         psb_xrandr_info->local_crtc[1]->location = NORMAL;
    179         return;
    180     case MIPI0_MIPI1:
    181         local_crtc = psb_xrandr_info->local_crtc[0];
    182         extend_crtc = psb_xrandr_info->local_crtc[1];
    183         break;
    184     default:
    185         break;
    186     }
    187 
    188     if (!local_crtc || !extend_crtc) {
    189         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to get crtc info\n");
    190         return;
    191     }
    192 
    193     /* MIPI1 clone MIPI0 */
    194     if (local_crtc->x == 0 && local_crtc->y == 0 &&
    195         extend_crtc->x == 0 && extend_crtc->y == 0) {
    196         psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = CLONE;
    197         extend_crtc->location = NORMAL;
    198     } else {
    199         /* MIPI1 entend MIPI0 */
    200         psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = EXTENDED;
    201         if (local_crtc->y == extend_crtc->height)
    202             extend_crtc->location = ABOVE;
    203         else if (extend_crtc->y == local_crtc->height)
    204             extend_crtc->location = BELOW;
    205         else if (local_crtc->x == extend_crtc->width)
    206             extend_crtc->location = LEFT_OF;
    207         else if (extend_crtc->x == local_crtc->width)
    208             extend_crtc->location = RIGHT_OF;
    209     }
    210 }
    211 
    212 static void psb_xrandr_hdmi_location_init(psb_output_device_mode output_device_mode)
    213 {
    214     psb_xrandr_crtc_p local_crtc = NULL, extend_crtc = NULL;
    215 
    216     switch (output_device_mode) {
    217     case SINGLE_HDMI:
    218         psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = SINGLE;
    219         psb_xrandr_info->extend_crtc->location = NORMAL;
    220         return;
    221     case MIPI0_HDMI:
    222     case MIPI0_MIPI1_HDMI:
    223         local_crtc = psb_xrandr_info->local_crtc[0];
    224         extend_crtc = psb_xrandr_info->extend_crtc;
    225         break;
    226     case MIPI1_HDMI:
    227         local_crtc = psb_xrandr_info->local_crtc[1];
    228         extend_crtc = psb_xrandr_info->extend_crtc;
    229         break;
    230     default:
    231         break;
    232     }
    233 
    234     if (!local_crtc || !extend_crtc) {
    235         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to get crtc info\n");
    236         return;
    237     }
    238 
    239     if (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == CLONE)
    240         psb_xrandr_info->extend_crtc->location = NORMAL;
    241 
    242     if (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == EXTENDED
    243         || psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == EXTENDEDVIDEO) {
    244         if (local_crtc->y == extend_crtc->height)
    245             psb_xrandr_info->extend_crtc->location = ABOVE;
    246         else if (extend_crtc->y == local_crtc->height)
    247             psb_xrandr_info->extend_crtc->location = BELOW;
    248         else if (local_crtc->x == extend_crtc->width)
    249             psb_xrandr_info->extend_crtc->location = LEFT_OF;
    250         else if (extend_crtc->x == local_crtc->width)
    251             psb_xrandr_info->extend_crtc->location = RIGHT_OF;
    252     }
    253 }
    254 
    255 static void psb_xrandr_coordinate_init(VADriverContextP ctx)
    256 {
    257     INIT_DRIVER_DATA;
    258     psb_xrandr_output_p p_output;
    259 
    260     psb_xrandr_info->output_changed = 1;
    261 
    262     for (p_output = psb_xrandr_info->output_head; p_output; p_output = p_output->next) {
    263         if (p_output->connection == RR_Connected) {
    264             if (!strcmp(p_output->name, "MIPI0")) {
    265                 if (p_output->crtc) {
    266                     psb_xrandr_info->mipi0_enabled = 1;
    267                     psb_xrandr_info->local_output[0] = p_output;
    268                     psb_xrandr_info->local_crtc[0] = p_output->crtc;
    269                     if (psb_xrandr_info->mipi0_rotation != p_output->crtc->rotation) {
    270                         psb_xrandr_info->mipi0_rotation = p_output->crtc->rotation;
    271                         driver_data->mipi0_rotation = RRrotation2VArotation(psb_xrandr_info->mipi0_rotation);
    272                         driver_data->xrandr_dirty |= PSB_NEW_ROTATION;
    273                     }
    274                 } else {
    275                     psb_xrandr_info->mipi0_enabled = 0;
    276                     psb_xrandr_info->local_output[0] = NULL;
    277                     psb_xrandr_info->local_crtc[0] = NULL;
    278                 }
    279             } else if (!strcmp(p_output->name, "MIPI1")) {
    280                 if (p_output->crtc) {
    281                     psb_xrandr_info->mipi1_enabled = 1;
    282                     psb_xrandr_info->local_output[1] = p_output;
    283                     psb_xrandr_info->local_crtc[1] = p_output->crtc;
    284                     if (psb_xrandr_info->mipi1_rotation != p_output->crtc->rotation) {
    285                         psb_xrandr_info->mipi1_rotation = p_output->crtc->rotation;
    286                         driver_data->mipi1_rotation = RRrotation2VArotation(psb_xrandr_info->mipi1_rotation);
    287                         driver_data->xrandr_dirty |= PSB_NEW_ROTATION;
    288                     }
    289                 } else {
    290                     psb_xrandr_info->mipi1_enabled = 0;
    291                     psb_xrandr_info->local_output[1] = NULL;
    292                     psb_xrandr_info->local_crtc[1] = NULL;
    293                 }
    294             } else if (!strcmp(p_output->name, "TMDS0-1")) {
    295                 if (p_output->crtc) {
    296                     psb_xrandr_info->hdmi_enabled = 1;
    297                     psb_xrandr_info->extend_output = p_output;
    298                     psb_xrandr_info->extend_crtc = p_output->crtc;
    299                     if (psb_xrandr_info->hdmi_rotation != p_output->crtc->rotation) {
    300                         psb_xrandr_info->hdmi_rotation = p_output->crtc->rotation;
    301                         driver_data->hdmi_rotation = RRrotation2VArotation(psb_xrandr_info->hdmi_rotation);
    302                         driver_data->xrandr_dirty |= PSB_NEW_ROTATION;
    303                     }
    304                 } else {
    305                     psb_xrandr_info->hdmi_enabled = 0;
    306                     psb_xrandr_info->extend_output = NULL;
    307                     psb_xrandr_info->extend_crtc = NULL;
    308                 }
    309             } else if (!strcmp(p_output->name, "LVDS0") && IS_MRST(driver_data)) {
    310                 if (p_output->crtc) {
    311                     psb_xrandr_info->lvds0_enabled = 1;
    312                     psb_xrandr_info->local_output[0] = p_output;
    313                     psb_xrandr_info->local_crtc[0] = p_output->crtc;
    314                 } else {
    315                     psb_xrandr_info->lvds0_enabled = 0;
    316                     psb_xrandr_info->local_output[0] = NULL;
    317                     psb_xrandr_info->local_crtc[0] = NULL;
    318                 }
    319             }
    320         }
    321     }
    322 
    323     /* for MRST */
    324     if (IS_MRST(driver_data) && psb_xrandr_info->lvds0_enabled) {
    325         psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = SINGLE;
    326         psb_xrandr_info->output_device_mode = SINGLE_LVDS0;
    327         psb_xrandr_info->local_crtc[0]->location = NORMAL;
    328         return;
    329     }
    330 
    331     /* HDMI + either MIPI0 or MIPI1 */
    332     if (psb_xrandr_info->hdmi_enabled) {
    333 
    334         /* Get HDMI properties if it is enabled*/
    335         psb_xrandr_hdmi_property(ctx);
    336 
    337         /* Only HDMI */
    338         if (!psb_xrandr_info->mipi0_enabled && !psb_xrandr_info->mipi1_enabled)
    339             psb_xrandr_info->output_device_mode = SINGLE_HDMI;
    340 
    341         /* HDMI + MIPI0 */
    342         if (psb_xrandr_info->mipi0_enabled && !psb_xrandr_info->mipi1_enabled)
    343             psb_xrandr_info->output_device_mode = MIPI0_HDMI;
    344 
    345         /* HDMI + MIPI1 */
    346         if (!psb_xrandr_info->mipi0_enabled && psb_xrandr_info->mipi1_enabled)
    347             psb_xrandr_info->output_device_mode = MIPI1_HDMI;
    348 
    349         /* HDMI + MIPI0 + MIPI1 */
    350         if (psb_xrandr_info->mipi0_enabled && psb_xrandr_info->mipi1_enabled)
    351             psb_xrandr_info->output_device_mode = MIPI0_MIPI1_HDMI;
    352 
    353         psb_xrandr_hdmi_location_init(psb_xrandr_info->output_device_mode);
    354     } else {
    355         /* MIPI0 + MIPI1 */
    356         if (psb_xrandr_info->mipi0_enabled && psb_xrandr_info->mipi1_enabled) {
    357             psb_xrandr_info->output_device_mode = MIPI0_MIPI1;
    358         } else {
    359             /* MIPI0/MIPI1 */
    360             if (psb_xrandr_info->mipi0_enabled)
    361                 psb_xrandr_info->output_device_mode = SINGLE_MIPI0;
    362             else if (psb_xrandr_info->mipi1_enabled)
    363                 psb_xrandr_info->output_device_mode = SINGLE_MIPI1;
    364         }
    365 
    366         psb_xrandr_mipi_location_init(psb_xrandr_info->output_device_mode);
    367     }
    368 }
    369 
    370 void psb_xrandr_refresh(VADriverContextP ctx)
    371 {
    372     int i;
    373 
    374     XRROutputInfo *output_info;
    375     XRRCrtcInfo *crtc_info;
    376 
    377     psb_xrandr_crtc_p p_crtc;
    378     psb_xrandr_output_p p_output;
    379 
    380     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    381 
    382     //deinit crtc
    383     if (psb_xrandr_info->crtc_head) {
    384         while (psb_xrandr_info->crtc_head) {
    385             psb_xrandr_info->crtc_tail = psb_xrandr_info->crtc_head->next;
    386 
    387             free(psb_xrandr_info->crtc_head);
    388 
    389             psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail;
    390         }
    391         psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail = NULL;
    392     }
    393 
    394     for (i = 0; i < psb_xrandr_info->res->ncrtc; i++) {
    395         crtc_info = XRRGetCrtcInfo(psb_xrandr_info->dpy, psb_xrandr_info->res, psb_xrandr_info->res->crtcs[i]);
    396         if (crtc_info) {
    397             p_crtc = (psb_xrandr_crtc_p)calloc(1, sizeof(psb_xrandr_crtc_s));
    398             if (!p_crtc) {
    399                 drv_debug_msg(VIDEO_DEBUG_ERROR, "output of memory\n");
    400                 return;
    401             }
    402 
    403             if (i == 0)
    404                 psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail = p_crtc;
    405 
    406             p_crtc->crtc_id = psb_xrandr_info->res->crtcs[i];
    407             p_crtc->x = crtc_info->x;
    408             p_crtc->y = crtc_info->y;
    409             p_crtc->width = crtc_info->width;
    410             p_crtc->height = crtc_info->height;
    411             p_crtc->crtc_mode = crtc_info->mode;
    412             p_crtc->noutput = crtc_info->noutput;
    413             p_crtc->rotation = crtc_info->rotation;
    414 
    415             psb_xrandr_info->crtc_tail->next = p_crtc;
    416             p_crtc->next = NULL;
    417             psb_xrandr_info->crtc_tail = p_crtc;
    418         } else {
    419             drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to get crtc_info\n");
    420             pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    421             return;
    422         }
    423     }
    424 
    425     //deinit output
    426     if (psb_xrandr_info->output_head) {
    427         while (psb_xrandr_info->output_head) {
    428             psb_xrandr_info->output_tail = psb_xrandr_info->output_head->next;
    429 
    430             free(psb_xrandr_info->output_head);
    431 
    432             psb_xrandr_info->output_head = psb_xrandr_info->output_tail;
    433         }
    434         psb_xrandr_info->output_head = psb_xrandr_info->output_tail = NULL;
    435     }
    436 #if 0
    437     //destroy the full-screen window
    438     //FIXME: commited out for X Error message: BadDrawable, need more investigation
    439     if (va_output) {
    440         if (va_output->extend_drawable) {
    441             XDestroyWindow(ctx->native_dpy, va_output->extend_drawable);
    442             va_output->extend_drawable = 0;
    443             texture_priv->extend_dri_init_flag = 0;
    444         }
    445     }
    446 #endif
    447     for (i = 0; i < psb_xrandr_info->res->noutput; i++) {
    448         output_info = XRRGetOutputInfo(psb_xrandr_info->dpy, psb_xrandr_info->res, psb_xrandr_info->res->outputs[i]);
    449         if (output_info) {
    450             p_output = (psb_xrandr_output_p)calloc(1, sizeof(psb_xrandr_output_s));
    451             if (!p_output) {
    452                 drv_debug_msg(VIDEO_DEBUG_ERROR, "output of memory\n");
    453                 return;
    454             }
    455 
    456             if (i == 0)
    457                 psb_xrandr_info->output_head = psb_xrandr_info->output_tail = p_output;
    458 
    459             p_output->output_id = psb_xrandr_info->res->outputs[i];
    460 
    461             p_output->connection = output_info->connection;
    462             if (p_output->connection == RR_Connected)
    463                 psb_xrandr_info->nconnected_output++;
    464 
    465             strcpy(p_output->name, output_info->name);
    466 
    467             if (output_info->crtc)
    468                 p_output->crtc = get_crtc_by_id(output_info->crtc);
    469             else
    470                 p_output->crtc = NULL;
    471 
    472             psb_xrandr_info->output_tail->next = p_output;
    473             p_output->next = NULL;
    474             psb_xrandr_info->output_tail = p_output;
    475         } else {
    476             drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to get output_info\n");
    477             pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    478             return;
    479         }
    480     }
    481 
    482     psb_xrandr_coordinate_init(ctx);
    483 
    484     psb_RecalcRotate(ctx);
    485     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    486 }
    487 
    488 static Bool
    489 outputChangePredicate(Display *display, XEvent *event, char *args)
    490 {
    491     int event_base, error_base;
    492 
    493     XRRQueryExtension(psb_xrandr_info->dpy, &event_base, &error_base);
    494     return ((event->type == event_base + RRNotify_OutputChange) ||
    495             ((event->type == ClientMessage) &&
    496              (((XClientMessageEvent*)event)->message_type == psb_xrandr_info->psb_exit_atom)));
    497 }
    498 
    499 void psb_xrandr_thread(void* arg)
    500 {
    501     VADriverContextP ctx = (VADriverContextP)arg;
    502     INIT_DRIVER_DATA;
    503     int event_base, error_base;
    504     XEvent event;
    505     XRRQueryExtension(psb_xrandr_info->dpy, &event_base, &error_base);
    506     XRRSelectInput(psb_xrandr_info->dpy, psb_xrandr_info->root, RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask);
    507     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: psb xrandr thread start\n");
    508 
    509     while (1) {
    510         if (XCheckIfEvent(psb_xrandr_info->dpy, (XEvent *)&event, outputChangePredicate, NULL)) {
    511             if (event.type == ClientMessage) {
    512                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: receive ClientMessage event, thread should exit\n");
    513                 XClientMessageEvent *evt;
    514                 evt = (XClientMessageEvent*) & event;
    515                 if (evt->message_type == psb_xrandr_info->psb_exit_atom) {
    516                     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: xrandr thread exit safely\n");
    517                     pthread_exit(NULL);
    518                 }
    519             }
    520             switch (event.type - event_base) {
    521             case RRNotify_OutputChange:
    522                 XRRUpdateConfiguration(&event);
    523                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: receive RRNotify_OutputChange event, refresh output/crtc info\n");
    524                 driver_data->xrandr_update = 1;
    525                 psb_xrandr_refresh(ctx);
    526                 break;
    527             default:
    528                 break;
    529             }
    530         }
    531         usleep(200000);
    532     }
    533 }
    534 
    535 Window psb_xrandr_create_full_screen_window(unsigned int destx, unsigned int desty, unsigned int destw, unsigned int desth)
    536 {
    537     int x, y, width, height;
    538     Window win;
    539 
    540     x = psb_xrandr_info->extend_crtc->x;
    541     y = psb_xrandr_info->extend_crtc->y;
    542     width = psb_xrandr_info->extend_crtc->width;
    543     height = psb_xrandr_info->extend_crtc->height;
    544 
    545     if (destw == 0 || desth == 0) {
    546         destw = width;
    547         desth = height;
    548     }
    549     win = XCreateSimpleWindow(psb_xrandr_info->dpy, DefaultRootWindow(psb_xrandr_info->dpy), destx, desty, destw, desth, 0, 0, 0);
    550 
    551     MWMHints mwmhints;
    552     Atom MOTIF_WM_HINTS;
    553 
    554     mwmhints.flags = MWM_HINTS_DECORATIONS;
    555     mwmhints.decorations = 0; /* MWM_DECOR_BORDER */
    556     MOTIF_WM_HINTS = XInternAtom(psb_xrandr_info->dpy, "_MOTIF_WM_HINTS", False);
    557     XChangeProperty(psb_xrandr_info->dpy, win, MOTIF_WM_HINTS, MOTIF_WM_HINTS, sizeof(long) * 8,
    558                     PropModeReplace, (unsigned char*) &mwmhints, sizeof(mwmhints) / sizeof(long));
    559 
    560     XSetWindowAttributes attributes;
    561     attributes.override_redirect = 1;
    562     unsigned long valuemask;
    563     valuemask = CWOverrideRedirect ;
    564     XChangeWindowAttributes(psb_xrandr_info->dpy, win, valuemask, &attributes);
    565 
    566     XMapWindow(psb_xrandr_info->dpy, win);
    567     XFlush(psb_xrandr_info->dpy);
    568     return win;
    569 }
    570 
    571 int psb_xrandr_hdmi_enabled()
    572 {
    573     int ret;
    574     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    575     ret = psb_xrandr_info->hdmi_enabled;
    576     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    577     return ret;
    578 }
    579 
    580 int psb_xrandr_mipi0_enabled()
    581 {
    582     int ret;
    583     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    584     ret = psb_xrandr_info->mipi0_enabled;
    585     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    586     return ret;
    587 }
    588 
    589 int psb_xrandr_mipi1_enabled()
    590 {
    591     int ret;
    592     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    593     ret = psb_xrandr_info->mipi1_enabled;
    594     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    595     return ret;
    596 }
    597 
    598 int psb_xrandr_single_mode()
    599 {
    600     int ret;
    601     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    602     ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == SINGLE) ? 1 : 0;
    603     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    604     return ret;
    605 }
    606 
    607 int psb_xrandr_clone_mode()
    608 {
    609     int ret;
    610     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    611     ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == CLONE) ? 1 : 0;
    612     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    613     return ret;
    614 }
    615 
    616 int psb_xrandr_extend_mode()
    617 {
    618     int ret;
    619     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    620     ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == EXTENDED) ? 1 : 0;
    621     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    622     return ret;
    623 }
    624 
    625 int psb_xrandr_extvideo_mode()
    626 {
    627     int ret;
    628     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    629     ret = (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode == EXTENDEDVIDEO) ? 1 : 0;
    630     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    631     return ret;
    632 }
    633 
    634 int psb_xrandr_outputchanged()
    635 {
    636     int ret;
    637     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    638     if (psb_xrandr_info->output_changed) {
    639         psb_xrandr_info->output_changed = 0;
    640         ret = 1;
    641     } else
    642         ret = 0;
    643     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    644     return ret;
    645 }
    646 
    647 VAStatus psb_xrandr_extvideo_prop(unsigned int *xres, unsigned int *yres, unsigned int *xoffset,
    648                                   unsigned int *yoffset, psb_extvideo_center *center, psb_extvideo_subtitle *subtitle,
    649                                   unsigned int *overscanmode, unsigned int *pannelfitting)
    650 {
    651     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    652 
    653     if (psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode != EXTENDEDVIDEO) {
    654         pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    655         return VA_STATUS_ERROR_UNKNOWN;
    656     }
    657 
    658     *xres = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes;
    659     *yres = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes;
    660     *xoffset = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset;
    661     *yoffset = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset;
    662     *center = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center;
    663     *subtitle = psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle;
    664     *pannelfitting = psb_xrandr_info->hdmi_extvideo_prop->PANELFITTING;
    665     *overscanmode = psb_xrandr_info->hdmi_extvideo_prop->OverscanMode;
    666 
    667     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    668     return VA_STATUS_SUCCESS;
    669 }
    670 
    671 VAStatus psb_xrandr_local_crtc_coordinate(psb_output_device *local_device_enabled, int *x, int *y, int *width, int *height, Rotation *rotation)
    672 {
    673     psb_xrandr_crtc_p p_crtc;
    674     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    675 
    676     switch (psb_xrandr_info->output_device_mode) {
    677     case SINGLE_LVDS0:
    678         *local_device_enabled = LVDS0;
    679         p_crtc = psb_xrandr_info->local_crtc[0];
    680         break;
    681     case SINGLE_MIPI0:
    682     case MIPI0_MIPI1:
    683     case MIPI0_HDMI:
    684     case MIPI0_MIPI1_HDMI:
    685         *local_device_enabled = MIPI0;
    686         p_crtc = psb_xrandr_info->local_crtc[0];
    687         break;
    688     case SINGLE_MIPI1:
    689     case MIPI1_HDMI:
    690         *local_device_enabled = MIPI1;
    691         p_crtc = psb_xrandr_info->local_crtc[1];
    692         break;
    693     case SINGLE_HDMI:
    694         *local_device_enabled = HDMI;
    695         p_crtc = psb_xrandr_info->extend_crtc;
    696         break;
    697     default:
    698         drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: Unknown statue\n");
    699         pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    700         return VA_STATUS_ERROR_UNKNOWN;
    701         break;
    702     }
    703 
    704     if (p_crtc) {
    705         *x = p_crtc->x;
    706         *y = p_crtc->y;
    707         *width = p_crtc->width;
    708         *height = p_crtc->height;
    709         *rotation = p_crtc->rotation;
    710         pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    711         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: device %08x enabled, crtc %08x coordinate: x = %d, y = %d, widht = %d, height = %d, rotate = %08x\n",
    712                                  *local_device_enabled, p_crtc->crtc_id, *x, *y, *width + 1, *height + 1, *rotation);
    713         return VA_STATUS_SUCCESS;
    714     } else {
    715         drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: local device is not available\n");
    716         pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    717         return VA_STATUS_ERROR_UNKNOWN;
    718     }
    719 }
    720 
    721 VAStatus psb_xrandr_extend_crtc_coordinate(psb_output_device *extend_device_enabled, int *x, int *y, int *width, int *height, psb_xrandr_location *location, Rotation *rotation)
    722 {
    723     psb_xrandr_crtc_p p_crtc;
    724 
    725     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    726 
    727     switch (psb_xrandr_info->output_device_mode) {
    728     case MIPI0_MIPI1:
    729         *extend_device_enabled = MIPI1;
    730         p_crtc = psb_xrandr_info->local_crtc[1];
    731         break;
    732     case MIPI0_HDMI:
    733     case MIPI0_MIPI1_HDMI:
    734     case MIPI1_HDMI:
    735         *extend_device_enabled = HDMI;
    736         p_crtc = psb_xrandr_info->extend_crtc;
    737         break;
    738     default:
    739         drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: Unknown status, may be extend device is not available\n");
    740         pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    741         return VA_STATUS_ERROR_UNKNOWN;
    742         break;
    743     }
    744 
    745     if (p_crtc) {
    746         *x = p_crtc->x;
    747         *y = p_crtc->y;
    748         *width = p_crtc->width;
    749         *height = p_crtc->height;
    750         *location = p_crtc->location;
    751         *rotation = p_crtc->rotation;
    752         pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    753         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: extend device %08x enabled, crtc %08x coordinate: x = %d, y = %d, widht = %d, height = %d, location = %s, rotation = %08x\n",
    754                                  *extend_device_enabled, p_crtc->crtc_id, *x, *y, *width + 1, *height + 1, location2string(p_crtc->location), *rotation);
    755     } else {
    756         drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: extend device is not available\n");
    757         pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    758         return VA_STATUS_ERROR_UNKNOWN;
    759     }
    760 
    761     return VA_STATUS_SUCCESS;
    762 }
    763 
    764 VAStatus psb_xrandr_thread_exit()
    765 {
    766     int ret;
    767 
    768     XSelectInput(psb_xrandr_info->dpy, psb_xrandr_info->root, StructureNotifyMask);
    769     XClientMessageEvent xevent;
    770     xevent.type = ClientMessage;
    771     xevent.message_type = psb_xrandr_info->psb_exit_atom;
    772     xevent.window = psb_xrandr_info->root;
    773     xevent.format = 32;
    774     ret = XSendEvent(psb_xrandr_info->dpy, psb_xrandr_info->root, 0, StructureNotifyMask, (XEvent*) & xevent);
    775     XFlush(psb_xrandr_info->dpy);
    776     if (!ret) {
    777         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: send thread exit event to drawable: failed\n");
    778         return VA_STATUS_ERROR_UNKNOWN;
    779     } else {
    780         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: send thread exit event to drawable: success\n");
    781         return VA_STATUS_SUCCESS;
    782     }
    783 }
    784 
    785 VAStatus psb_xrandr_thread_create(VADriverContextP ctx)
    786 {
    787     pthread_t id;
    788     INIT_DRIVER_DATA;
    789 
    790     psb_xrandr_info->psb_exit_atom = XInternAtom(psb_xrandr_info->dpy, "psb_exit_atom", 0);
    791     pthread_create(&id, NULL, (void*)psb_xrandr_thread, ctx);
    792     driver_data->xrandr_thread_id = id;
    793     return VA_STATUS_SUCCESS;
    794 }
    795 
    796 VAStatus psb_xrandr_deinit()
    797 {
    798 #ifdef _FOR_FPGA_
    799     return VA_STATUS_SUCCESS;
    800 #endif
    801     pthread_mutex_lock(&psb_xrandr_info->psb_extvideo_mutex);
    802     //free crtc
    803     if (psb_xrandr_info->crtc_head) {
    804         while (psb_xrandr_info->crtc_head) {
    805             psb_xrandr_info->crtc_tail = psb_xrandr_info->crtc_head->next;
    806 
    807             free(psb_xrandr_info->crtc_head);
    808 
    809             psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail;
    810         }
    811         psb_xrandr_info->crtc_head = psb_xrandr_info->crtc_tail = NULL;
    812     }
    813 
    814     //free output
    815     if (psb_xrandr_info->output_head) {
    816         while (psb_xrandr_info->output_head) {
    817             psb_xrandr_info->output_tail = psb_xrandr_info->output_head->next;
    818 
    819             free(psb_xrandr_info->output_head);
    820 
    821             psb_xrandr_info->output_head = psb_xrandr_info->output_tail;
    822         }
    823         psb_xrandr_info->output_head = psb_xrandr_info->output_tail = NULL;
    824     }
    825 
    826     if (psb_xrandr_info->hdmi_extvideo_prop) {
    827         free(psb_xrandr_info->hdmi_extvideo_prop);
    828     }
    829 
    830     pthread_mutex_unlock(&psb_xrandr_info->psb_extvideo_mutex);
    831     pthread_mutex_destroy(&psb_xrandr_info->psb_extvideo_mutex);
    832 
    833     free(psb_xrandr_info);
    834     return VA_STATUS_SUCCESS;
    835 }
    836 
    837 VAStatus psb_xrandr_init(VADriverContextP ctx)
    838 {
    839     int major, minor;
    840     int screen;
    841 
    842     psb_xrandr_info = (psb_xrandr_info_p)calloc(1, sizeof(psb_xrandr_info_s));
    843 
    844     if (!psb_xrandr_info) {
    845         drv_debug_msg(VIDEO_DEBUG_ERROR, "output of memory\n");
    846         return VA_STATUS_ERROR_UNKNOWN;
    847     }
    848     memset(psb_xrandr_info, 0, sizeof(psb_xrandr_info_s));
    849     psb_xrandr_info->mipi0_rotation = RR_Rotate_0;
    850     psb_xrandr_info->mipi1_rotation = RR_Rotate_0;
    851     psb_xrandr_info->hdmi_rotation = RR_Rotate_0;
    852 
    853     psb_xrandr_info->hdmi_extvideo_prop = (psb_extvideo_prop_p)calloc(1, sizeof(psb_extvideo_prop_s));
    854     if (!psb_xrandr_info->hdmi_extvideo_prop) {
    855         drv_debug_msg(VIDEO_DEBUG_ERROR, "output of memory\n");
    856         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    857     }
    858     memset(psb_xrandr_info->hdmi_extvideo_prop, 0, sizeof(psb_extvideo_prop_s));
    859 
    860     psb_xrandr_info->dpy = (Display *)ctx->native_dpy;
    861     screen = DefaultScreen(psb_xrandr_info->dpy);
    862 
    863     if (screen >= ScreenCount(psb_xrandr_info->dpy)) {
    864         drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: Invalid screen number %d (display has %d)\n",
    865                            screen, ScreenCount(psb_xrandr_info->dpy));
    866         return VA_STATUS_ERROR_UNKNOWN;
    867     }
    868 
    869     psb_xrandr_info->root = RootWindow(psb_xrandr_info->dpy, screen);
    870 
    871     if (!XRRQueryVersion(psb_xrandr_info->dpy, &major, &minor)) {
    872         drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: RandR extension missing\n");
    873         return VA_STATUS_ERROR_UNKNOWN;
    874     }
    875 
    876     psb_xrandr_info->res = XRRGetScreenResources(psb_xrandr_info->dpy, psb_xrandr_info->root);
    877     if (!psb_xrandr_info->res)
    878         drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: failed to get screen resources\n");
    879 
    880     pthread_mutex_init(&psb_xrandr_info->psb_extvideo_mutex, NULL);
    881 
    882     psb_xrandr_refresh(ctx);
    883 
    884     return VA_STATUS_SUCCESS;
    885 }
    886