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