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