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